utils-0.94/0000755000000000000000000000000015174515600007540 5ustar00utils-0.94/CHANGES.md0000644000000000000000000002004615174515600011134 0ustar00# CHANGES log for the 'Utils' package ## Version 0.94 for GAP 4.16.0 (30/04/26) * (31/03/26) added new Ch.10 Generalized Straight Line Programs (Thomas Breuer) ## Version 0.93 for GAP 4.15.1 (13/11/25) * (13/11/25) new release to fix the problem described in GAP issue 6164 ## Version 0.92 for GAP 4.14.0 (11/09/25) * (10/09/25) support timeout in Download (Thomas Breuer) added new release mechanism: .github/workflows/release.yml ## Version 0.91 for GAP 4.14.0 (13/08/25) * (13/08/25) replaced DeclareGlobalFunction with DeclareGlobalName, etc. removed all code related to SubdirectProductWithEmbeddings ## Version 0.89 for GAP 4.14.0 (10/04/25) * (10/04/25) corrected creation of left cosets ## Version 0.87 ready for GAP 4.14.0 (20/10/24) * (08/04/25) adjustments to magma.gi and others.tst * (20/10/24) fix tests and examples to new GAP website ## Version 0.86 for GAP 4.13.1 (16/05/24) * (16/05/24) there have been just two minor adjustments since version 0.85 ## Version 0.85 for GAP 4.12.2 (23/01/24) * (08/01/24) avoid trivial function wrappers in List and ForAll ## Version 0.84 for GAP 4.12.2 (11/09/23) * (11/09/23) changed manual and test for DirectSumDecompositionMatrices ## Version 0.83 for GAP 4.12.2 (29/06/23) * (29/06/23) added DirectSumDecompositionMatrices ## Version 0.82 for GAP 4.12.2 (09/02/23) * (23/12/22) changed email address, deleted institution ## Version 0.81 for GAP 4.12.1 (04/12/22) * (17/11/22) removed (the dead) pcp option from PcGroupToMagmaFormat so that the dependency on Polycyclic could be removed * (21/10/22) added OptionRecordWithDefaults in 7.2 from Christopher Jefferson * (04/10/22) declared PreImagesRepresentativeNC in init.g ## Version 0.77 for GAP 4.12.0 (25/09/22) * (25/09/22) added Download operation by Thomas Breuer - new Chapter 8 ## Version 0.76 for GAP 4.12.0 (06/08/22) * (06/08/22) added LeftCoset operations ## Version 0.74 for GAP 4.11.1 (09/07/22) * (07/07/22) Max Horn replaced BIND_GLOBAL with BindGlobal (transfer process) * (05/07/22) CentralProduct added by Thomas Breuer ## Version 0.72 for GAP 4.10.1 (16/11/21) * (06/04/21) Switch CI to use GitHub Actions: PR#37 ## Version 0.69 for GAP 4.10.2 (29/11/19) * (22/11/19) added DirectProductOfAutomorphismGroups * (19/11/19) added DirectProductOfFunctions ## Version 0.67 for GAP 4.10.2 (04/09/19) * (04/09/19) accepted PR34 - changed example in 6.2.1 * (25/08/19) fixed typos with UnorderedPairsIterator in manual ## Version 0.65 for GAP 4.10.2 (11/07/19) * (11/07/19) groups.tst fails in gapdev - temporary(?) fix ## Version 0.64 for GAP 4.10.1 (17/06/19) * (14/06/19) added Iterators chapter: AllSubgroupsIterator CartesianIterator, UnorderedPairsIterator ## Version 0.63 for GAP 4.10.1 (29/05/19) * (28/05/19) added IdempotentEndomorphisms, IdempotentEndomorphismsData * (17/05/19) + AllIsomorphismsIterator, AllIsomorphismsNumber, AllIsomorphisms * (16/02/19) added License field in PackageInfo.g ## Version 0.61 for GAP 4.10.0 (28/11/18) * (28/11/18) made ExponentOfPrime obsolete * (27/11/18) made several AutoDoc functions obsolete (they remain in AutoDoc): FindMatchingFiles; CreateDirIfMissing; StringDotSuffix; SetIfMissing ## Version 0.59 for GAP 4.9.3 (04/10/18) * (04/10/18) made PrintApplicableMethod obsolete ## Version 0.58 for GAP 4.9.3 (12/09/18) * (08/09/18) marked PrintOneItemPerLine as obsolete: use Perform(L,Display); * (07/09/18) marked ExponentOfPrime as obsolete: use PValuation * (05/09/18) transferred code in combinat.g{d,i} to end of lists.g{d,i} * (04/09/18) removed all "if OKtoReadFomUtils( "RCWA" / "ResClasses" )" ## Version 0.57 for GAP 4.9.1 (02/06/18) * (02/06/18) new PrintSelection example due to diff with all packages loaded removed XMod from list of packages to be loaded * (27/03/18) revised file tst/testing.g ## Version 0.54 for GAP 4.9.0 (12/02/18) * (22/01/18) PrintOneItemPerLine plus alternative method for iterators; added function PrintSelection(L,first,step,last) for lists/iterators * (06/01/18) rebuilt the manual using the AutoDoc package * (22/12/17) removed examples/ folder ## Version 0.49 for GAP 4.8.8 (05/12/17) * (05/12/17) removed QPA functions PositionsNonzero and NullList * (21/11/17) changed record.tst so that 4r8 and dev give the same result ## Version 0.48 for GAP 4.8.8 (14/09/17) * (14/09/17) fixes to the gh-pages folder so that README.md is displayed * (12/09/17) corrected web addresses for Stefan and Frank * (04/07/17) README and CHANGES converted to README.md and CHANGES.md ## Version 0.46 for GAP 4.8.6 (08/02/17) * (08/02/17) added Polycyclic as a needed package * (07/02/17) added code for converting matrix groups to Magma strings * (03/02/17) added code for converting perm- and pc-groups to Magma strings * (02/02/17) copied `gaplog.css` to `utils/doc/` from RCWA archive ## Version 0.44 for GAP 4.8.6 (17/01/17) * (08/12/16) added PositionsNonzero and NullList from QPA * (05/12/16) added `tst/loadall.g` and adjusted `tst/testall.g`, `tst/*.tst` * (14/11/16) issue #2 reopened by Max: EpimorphismByGeneratorsNC removed ## Version 0.43 for GAP 4.8.5 (20/10/16) * (18/10/16) now using bibliography file `bib.xml` of type `bibxmlext.dtd` ## Version 0.41 for GAP 4.8.3 (25/05/16) * (25/05/16) fixed issue #8 : `git rm doc/appendix.xml` * (17/03/16) added function PrintApplicableMethod ## Version 0.40 for GAP 4.8.3 (17/03/16) * (17/03/16) moved transfer procedure to a new chapter in the manual * (15/03/16) added fix to QuotientList requested by Stefan added many manual examples supplied by Stefan ## Version 0.39 for GAP 4.8.2 (04/03/16) * (04/03/16) corrected repeated "//" in `PackageInfo.g` * (03/03/16) updated transfers from RCWA and ResClasses (Stefan's input) * (26/02/16) updated README to show the release URL * (25/02/16) New release to GitHub using ReleaseTools (GitHubPagesForGAP) `makedocrel.g` renamed `makedoc.g` * (17/02/16) Removed date/version information from file headers. * (16/02/16) Moved PackageWWWHome to GitHub; added OKtoReadFromUtilsSpec to deal with fns taken out early * (12/02/16) Added warning to manual about the need to load packages. * (11/02/16) BindInRecordIfMissing -> SetIfMissing (from AutoDoc) moved a number of functions to `pending.g{d,i}` * (10/02/16) adjustments due to new RCWA 4.0.0 and ResClasses 4.1.1 ## Version 0.22 for GAP 4.8.1 (04/02/16) * (04/02/16) repository moved to gap-packages ## Version 0.21 for GAP 4.8.1 (03/02/16) * (03/02/16) added several more functions from RCWA * (29/01/16) switching to a protocol based on Frank's suggestion: if TestPackageAvailability("Bla", ">=x.(y+1)") = fail then ... ## Version 0.17 for GAP 4.8.1 (12/01/16) * (12/01/16) more edits to `oper.g` and `global.g` suggested by Chris J. ## Version 0.15 for GAP 4.8.0 (18/12/15) * (17/12/15) added more documentation to `global.g` and `oper.g` ## Version 0.14 for GAP 4.8.0 (16/12/15) * (16/12/15) changed global lists in oper.g to GLOBAL_REDECLARATION_LIST, GLOBAL_REDECLARATION_COUNT and GLOBAL_REINSTALLATION_LIST; added functions (in `oper.g`) AllowGlobalRedeclaration and AllowGlobalReinstallation; added GLOBAL_REBINDING_LIST and AllowGlobalRebinding (in `global.g`) to cope with BIND_GLOBAL. ## Version 0.13 for GAP 4.8.0 (15/12/15) * (15/12/15) added some functions from AutoDoc; packed up version 0.13 * (14/12/15) library file `oper.g` edited to prevent repeat declarations etc. * (14/12/15) `names.g{d,i}` now `first.g{d,i}` with `last.gd` added, containing UTILS_FUNCTION_NAMES and UTILS_FUNCTION_OPERS ## Version 0.11 for GAP 4.8.0 (30/11/15) * (30/11/15) added tests and documentation for ResClasses functions * (25/11/15) added `names.g{d,i}`, `tests.g{d,i}` * (25/11/15) added `sebastian.gi` to `lib/` * (24/11/15) added `rwca.g{d,i}` and `resclasses.g{d,i}` to `lib/` * (24/11/15) added `combinat.g{d,i}` to `lib/` utils-0.94/LICENSE.txt0000644000000000000000000004310315174515600011364 0ustar00 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. utils-0.94/PackageInfo.g0000644000000000000000000001404115174515600012057 0ustar00############################################################################# ## ## PackageInfo.g file for the package Utils ## SetPackageInfo( rec( PackageName := "utils", Subtitle := "Utility functions in GAP", Version := "0.94", Date := "30/04/2026", # dd/mm/yyyy format License := "GPL-2.0-or-later", Persons := [ rec( LastName := "Breuer", FirstNames := "Thomas", IsAuthor := true, IsMaintainer := false, Email := "sam@math.rwth-aachen.de", WWWHome := "https://www.math.rwth-aachen.de/~Thomas.Breuer", Place := "Aachen", Institution := "Lehrstuhl für Algebra und Zahlentheorie, RWTH Aachen" ), rec( LastName := "Gutsche", FirstNames := "Sebastian", IsAuthor := true, IsMaintainer := false, Email := "gutsche@mathematik.uni-siegen.de", WWWHome := "https://sebasguts.github.io/", Place := "Siegen", Institution := "University of Siegen" ), rec( LastName := "Horn", FirstNames := "Max", IsAuthor := true, IsMaintainer := false, Email := "mhorn@rptu.de", WWWHome := "https://github.com/mhorn", ), rec( LastName := "Hulpke", FirstNames := "Alexander", IsAuthor := true, IsMaintainer := false, Email := "hulpke@math.colostate.edu", WWWHome := "https://www.math.colostate.edu/~hulpke", ), rec( LastName := "García-Sánchez", FirstNames := "Pedro", IsAuthor := true, IsMaintainer := false, WWWHome := "http://www.ugr.es/local/pedro", Email := "pedro@ugr.es", ), rec( LastName := "Jefferson", FirstNames := "Christopher", IsAuthor := true, IsMaintainer := false, WWWHome := "https://caj.host.cs.st-andrews.ac.uk/", Email := "caj21@st-andrews.ac.uk", ), rec( LastName := "Kohl", FirstNames := "Stefan", IsAuthor := true, IsMaintainer := false, Email := "stefan@mcs.st-and.ac.uk", WWWHome := "https://www.gap-system.org/DevelopersPages/StefanKohl/" ), rec( LastName := "Lübeck", FirstNames := "Frank", IsAuthor := true, IsMaintainer := false, Email := "Frank.Luebeck@Math.RWTH-Aachen.De", WWWHome := "https://www.math.rwth-aachen.de/~Frank.Luebeck", ), rec( LastName := "Wensley", FirstNames := "Chris", IsAuthor := true, IsMaintainer := true, Email := "cdwensley.maths@btinternet.com", WWWHome := "https://github.com/cdwensley", Place := "Llanfairfechan", Institution := "" ) ], Status := "deposited", ## CommunicatedBy := " ", ## AcceptDate := " ", SourceRepository := rec( Type := "git", URL := "https://github.com/gap-packages/utils" ), IssueTrackerURL := "https://github.com/gap-packages/utils/issues", PackageWWWHome := "https://gap-packages.github.io/utils", README_URL := Concatenation( ~.PackageWWWHome, "/README.md" ), PackageInfoURL := Concatenation( ~.PackageWWWHome, "/PackageInfo.g" ), ArchiveURL := Concatenation( ~.SourceRepository.URL, "/releases/download/v", ~.Version, "/", ~.PackageName, "-", ~.Version ), ArchiveFormats := ".tar.gz .zip", AbstractHTML := "The Utils package provides a collection \ of utility functions gleaned from many packages.", PackageDoc := rec( BookName := "Utils", ArchiveURLSubset := ["doc"], HTMLStart := "doc/chap0_mj.html", PDFFile := "doc/manual.pdf", SixFile := "doc/manual.six", LongTitle := "Utility functions in GAP" ), Dependencies := rec( GAP := ">=4.10.1", NeededOtherPackages := [ ], SuggestedOtherPackages := [ [ "curlInterface", ">= 2.3.0" ] ], ExternalConditions := [ ] ), AvailabilityTest := ReturnTrue, Keywords := [ ], BannerString := Concatenation( "Loading Utils ", String( ~.Version ), " - a collection of utility functions.\n" ), TestFile := "tst/testall.g", AutoDoc := rec( TitlePage := rec( Copyright := Concatenation( "© 2015-2026, The GAP Group.

\n", "The &Utils; package is free software; you can redistribute it ", "and/or modify it under the terms of the GNU General ", "Public License as published by the Free Software Foundation; ", "either version 2 of the License, or (at your option) ", "any later version.\n" ), Abstract := Concatenation( "The &Utils; package provides a space for utility functions ", "in a variety of ⪆ packages to be collected together ", "into a single package. In this way it is hoped that they will ", "become more visible to package authors.\n", "

\n", "Any package author who transfers a function to &Utils; ", "will become an author of &Utils;.\n", "

\n", "If deemed appropriate, functions may also be transferred ", "from the main library.\n", "

\n", "Bug reports, suggestions and comments are, of course, welcome.\n", "Please contact the last author at ", "cdwensley.maths@btinternet.com ", "or submit an issue at the GitHub repository ", "https://github.com/gap-packages/utils/issues/.\n" ), Acknowledgements := Concatenation( "This documentation was prepared using the ", "&GAPDoc; and ", "&AutoDoc; packages.

\n", "The procedure used to produce new releases uses the package ", "GitHubPagesForGAP ", " ", "and the package ReleaseTools.

" ), ) ), )); utils-0.94/README.md0000644000000000000000000000345615174515600011027 0ustar00[![CI](https://github.com/gap-packages/utils/actions/workflows/CI.yml/badge.svg)](https://github.com/gap-packages/utils/actions/workflows/CI.yml) [![Code Coverage](https://codecov.io/github/gap-packages/utils/coverage.svg?branch=master&token=)](https://codecov.io/gh/gap-packages/utils) # The GAP 4 package `Utils` ## Introduction This package collects together utility functions from a selection of GAP packages in order to make them more widely visible to other package authors. Other generally useful functions, which are not deemed suitable for the main library, and also welcome. For example, recent additions are functions to convert certain types of group to Magma format. ## Distribution * The GitHub package repository is at * and the latest release is available at ## Copyright The `Utils` package is Copyright © The GAP Group, 2015-2025. `Utils` is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. For details, see ## Installation * unpack `utils-.tar.gz` in the `pkg` subdirectory of the GAP root directory. * From within GAP load the package with: ``` gap> LoadPackage("utils"); true ``` * The file `manual.pdf` is in the `doc` subdirectory. ## Contact If you have a question relating to `Utils`, encounter any problems, or wish to suggest other functions to be transferred to the package, please * email: * or report an issue on the GitHub issue tracker at: utils-0.94/doc/0000755000000000000000000000000015174515600010305 5ustar00utils-0.94/doc/_entities.xml0000644000000000000000000000053015174515600013010 0ustar00AutoDoc'> {\sf MathJax}'> ResClasses'> RCWA'> XMod'> Home'> {\sf Magma}'> Utils'> utils-0.94/doc/bib.xml0000644000000000000000000000777415174515600011602 0ustar00 SebastianGutsche MaxHorn <C>AutoDoc - Generate documentation from GAP source code (Version 2016.12.04)</C> 2016 GAP package, https://github.com/gap-packages/AutoDoc FrankLübeck MaxNeunhöffer <C>GAPDoc (Version 1.6)</C> RWTH Aachen 2017 GAP package, https://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html MaxHorn <C>GitHubPagesForGAP - Template for easily using GitHub Pages within GAP packages (Version 0.2)</C> 2017 GAP package, https://gap-system.github.io/GitHubPagesForGAP/ http://magma.maths.usyd.edu.au/magma/ WiebBosma JohnCannon CatherinePlayoust <C>The Magma algebra system. {I}. The user language</C> Computational algebra and number theory (London, 1993)} https://doi.org/10.1006/jsco.1996.0125 J. Symbolic Comput. 24 1997 3-4 235--265 0747-7171 68Q40 MR1484478 10.1006/jsco.1996.0125 StefanKohl <C>RCWA - Residue-Class-Wise Affine Groups (Version 4.5.1)</C> 2017 GAP package, https://stefan-kohl.github.io/rcwa.html StefanKohl <C>ResClasses - Set-Theoretic Computations with Residue Classes (Version 4.6.0)</C> 2017 GAP package, https://stefan-kohl.github.io/resclasses.html Chris D.Wensley MuratAlp AlperOdabas Enver OnderUslu <C>XMod - Crossed Modules and Cat1-groups in GAP (Version 2.64)</C> 2017 GAP package, https://github.com/gap-packages/xmod Robert A.Wilson PeterWalsh JonathanTripp IbrahimSuleiman Richard A.Parker Simon P.Norton SimonNickerson SteveLinton JohnBray RachelAbbott <C>ATLAS of Finite Group Representations</C> http://atlas.math.rwth-aachen.de/Atlas/v3 ATLAS utils-0.94/doc/bib.xml.bib0000644000000000000000000001253715174515600012326 0ustar00 @manual{ AutoDoc, author = {Gutsche, S. and Horn, M.}, title = {{AutoDoc \texttt{\symbol{45}} Generate documentation from GAP source code (Version 2016.12.04)}}, year = {2016}, note = {GAP package, \href {https://github.com/gap-packages/AutoDoc} {\texttt{https://github.com/}\discretionary {}{}{}\texttt{gap\texttt{\symbol{45}}packages/}\discretionary {}{}{}\texttt{AutoDoc}}}, printedkey = {GH16} } @manual{ GAPDoc, author = {L{\"u}beck, F. and Neunh{\"o}ffer, M.}, title = {{GAPDoc (Version 1.6)}}, organization = {RWTH Aachen}, year = {2017}, note = {GAP package, \href {https://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html} {\texttt{https://www.math.rwth\texttt{\symbol{45}}aachen.de/}\discretionary {}{}{}\texttt{\texttt{\symbol{126}}Frank.Luebeck/}\discretionary {}{}{}\texttt{GAPDoc/}\discretionary {}{}{}\texttt{index.html}}}, printedkey = {LN17} } @manual{ GitHubPagesForGAP, author = {Horn, M.}, title = {{GitHubPagesForGAP \texttt{\symbol{45}} Template for easily using GitHub Pages within GAP packages (Version 0.2)}}, year = {2017}, note = {GAP package, \href {https://gap-system.github.io/GitHubPagesForGAP/} {\texttt{https://gap\texttt{\symbol{45}}system.github.io/}\discretionary {}{}{}\texttt{GitHubPagesForGAP/}}}, printedkey = {Hor17} } @manual{ MAGMA, author = {Bosma, W. and Cannon, J. and Playoust, C.}, title = {{The Magma algebra system. \texttt{\symbol{123}}I\texttt{\symbol{125}}. The user language}}, journal = {J. Symbolic Comput.}, volume = {24}, number = {3\texttt{\symbol{45}}4}, year = {1997}, pages = {235\texttt{\symbol{45}}\texttt{\symbol{45}}265}, note = {Computational algebra and number theory (London, 1993)\texttt{\symbol{125}} \href {https://doi.org/10.1006/jsco.1996.0125} {\texttt{https://doi.org/}\discretionary {}{}{}\texttt{10.1006/}\discretionary {}{}{}\texttt{jsco.1996.0125}}}, mrclass = {68Q40}, mrnumber = {MR1484478}, ISSN = {0747\texttt{\symbol{45}}7171}, doi = {10.1006/jsco.1996.0125}, printedkey = {BCP97} } @manual{ RCWA, author = {Kohl, S.}, title = {{RCWA \texttt{\symbol{45}} Residue\texttt{\symbol{45}}Class\texttt{\symbol{45}}Wise Affine Groups (Version 4.5.1)}}, year = {2017}, note = {GAP package, \href {https://stefan-kohl.github.io/rcwa.html} {\texttt{https://stefan\texttt{\symbol{45}}kohl.github.io/}\discretionary {}{}{}\texttt{rcwa.html}}}, printedkey = {Koh17} } @manual{ ResClasses, author = {Kohl, S.}, title = {{ResClasses \texttt{\symbol{45}} Set\texttt{\symbol{45}}Theoretic Computations with Residue Classes (Version 4.6.0)}}, year = {2017}, note = {GAP package, \href {https://stefan-kohl.github.io/resclasses.html} {\texttt{https://stefan\texttt{\symbol{45}}kohl.github.io/}\discretionary {}{}{}\texttt{resclasses.html}}}, printedkey = {Koh17} } @manual{ XMod, author = {Wensley, C. D. and Alp, M. and Odabas, A. and Uslu, E. O.}, title = {{XMod \texttt{\symbol{45}} Crossed Modules and Cat1\texttt{\symbol{45}}groups in GAP (Version 2.64)}}, year = {2017}, note = {GAP package, \href {https://github.com/gap-packages/xmod} {\texttt{https://github.com/}\discretionary {}{}{}\texttt{gap\texttt{\symbol{45}}packages/}\discretionary {}{}{}\texttt{xmod}}}, printedkey = {WAOU17} } @misc{ AGRv3, author = {Wilson, R. A. and Walsh, P. and Tripp, J. and Suleiman, I. and Parker, R. A. and Norton, S. P. and Nickerson, S. and Linton, S. and Bray, J. and Abbott, R.}, title = {{ATLAS of Finite Group Representations}}, howpublished = {\href {http://atlas.math.rwth-aachen.de/Atlas/v3} {\texttt{http://atlas.math.rwth\texttt{\symbol{45}}aachen.de/}\discretionary {}{}{}\texttt{Atlas/v3}}}, key = {ATLAS} } utils-0.94/doc/chap0.html0000644000000000000000000005131515174515600012173 0ustar00 GAP (Utils) - Contents

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

utils

Utility functions in GAP

0.94

30 April 2026

Thomas Breuer
Email: sam@math.rwth-aachen.de
Homepage: https://www.math.rwth-aachen.de/~Thomas.Breuer

Sebastian Gutsche
Email: gutsche@mathematik.uni-siegen.de
Homepage: https://sebasguts.github.io/

Max Horn
Email: mhorn@rptu.de
Homepage: https://github.com/mhorn

Alexander Hulpke
Email: hulpke@math.colostate.edu
Homepage: https://www.math.colostate.edu/~hulpke

Pedro García-Sánchez
Email: pedro@ugr.es
Homepage: http://www.ugr.es/local/pedro

Christopher Jefferson
Email: caj21@st-andrews.ac.uk
Homepage: https://caj.host.cs.st-andrews.ac.uk/

Stefan Kohl
Email: stefan@mcs.st-and.ac.uk
Homepage: https://www.gap-system.org/DevelopersPages/StefanKohl/

Frank Lübeck
Email: Frank.Luebeck@Math.RWTH-Aachen.De
Homepage: https://www.math.rwth-aachen.de/~Frank.Luebeck

Chris Wensley
Email: cdwensley.maths@btinternet.com
Homepage: https://github.com/cdwensley

Abstract

The Utils package provides a space for utility functions in a variety of GAP packages to be collected together into a single package. In this way it is hoped that they will become more visible to package authors.

Any package author who transfers a function to Utils will become an author of Utils.

If deemed appropriate, functions may also be transferred from the main library.

Bug reports, suggestions and comments are, of course, welcome. Please contact the last author at cdwensley.maths@btinternet.com or submit an issue at the GitHub repository https://github.com/gap-packages/utils/issues/.

Copyright

© 2015-2026, The GAP Group.

The Utils package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

Acknowledgements

This documentation was prepared using the GAPDoc [LN17] and AutoDoc [GH16] packages.

The procedure used to produce new releases uses the package GitHubPagesForGAP [Hor17] and the package ReleaseTools.

Contents


Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap0.txt0000644000000000000000000001624115174515600012045 0ustar00  utils   Utility functions in GAP  0.94 30 April 2026 Thomas Breuer Sebastian Gutsche Max Horn Alexander Hulpke Pedro García-Sánchez Christopher Jefferson Stefan Kohl Frank Lübeck Chris Wensley Thomas Breuer Email: mailto:sam@math.rwth-aachen.de Homepage: https://www.math.rwth-aachen.de/~Thomas.Breuer Sebastian Gutsche Email: mailto:gutsche@mathematik.uni-siegen.de Homepage: https://sebasguts.github.io/ Max Horn Email: mailto:mhorn@rptu.de Homepage: https://github.com/mhorn Alexander Hulpke Email: mailto:hulpke@math.colostate.edu Homepage: https://www.math.colostate.edu/~hulpke Pedro García-Sánchez Email: mailto:pedro@ugr.es Homepage: http://www.ugr.es/local/pedro Christopher Jefferson Email: mailto:caj21@st-andrews.ac.uk Homepage: https://caj.host.cs.st-andrews.ac.uk/ Stefan Kohl Email: mailto:stefan@mcs.st-and.ac.uk Homepage: https://www.gap-system.org/DevelopersPages/StefanKohl/ Frank Lübeck Email: mailto:Frank.Luebeck@Math.RWTH-Aachen.De Homepage: https://www.math.rwth-aachen.de/~Frank.Luebeck Chris Wensley Email: mailto:cdwensley.maths@btinternet.com Homepage: https://github.com/cdwensley ------------------------------------------------------- Abstract The Utils package provides a space for utility functions in a variety of GAP packages to be collected together into a single package. In this way it is hoped that they will become more visible to package authors. Any package author who transfers a function to Utils will become an author of Utils. If deemed appropriate, functions may also be transferred from the main library. Bug reports, suggestions and comments are, of course, welcome. Please contact the last author at mailto:cdwensley.maths@btinternet.com or submit an issue at the GitHub repository https://github.com/gap-packages/utils/issues/. ------------------------------------------------------- Copyright © 2015-2026, The GAP Group. The Utils package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ------------------------------------------------------- Acknowledgements This documentation was prepared using the GAPDoc [LN17] and AutoDoc [GH16] packages. The procedure used to produce new releases uses the package GitHubPagesForGAP [Hor17] and the package ReleaseTools. ------------------------------------------------------- Contents (Utils) 1 Introduction 1.1 Information for package authors 2 Printing Lists and Iterators 2.1 Printing selected items 2.1-1 PrintSelection 3 Lists, Sets and Strings 3.1 Functions for lists 3.1-1 DifferencesList 3.1-2 QuotientsList 3.1-3 SearchCycle 3.1-4 RandomCombination 3.2 Distinct and Common Representatives 3.2-1 DistinctRepresentatives 3.3 Functions for strings 3.3-1 BlankFreeString 4 Number-theoretic functions 4.1 Functions for integers 4.1-1 AllSmoothIntegers 4.1-2 AllProducts 4.1-3 RestrictedPartitionsWithoutRepetitions 4.1-4 NextProbablyPrimeInt 4.1-5 PrimeNumbersIterator 5 Groups and homomorphisms 5.1 Functions for groups 5.1-1 Comm 5.1-2 IsCommuting 5.1-3 ListOfPowers 5.1-4 GeneratorsAndInverses 5.1-5 UpperFittingSeries 5.2 Left Cosets for Groups 5.2-1 LeftCoset 5.2-2 Inverse 5.3 Functions for group homomorphisms 5.3-1 EpimorphismByGenerators 5.3-2 Pullback 5.3-3 CentralProduct 5.3-4 IdempotentEndomorphisms 5.3-5 DirectProductOfFunctions 5.3-6 DirectProductOfAutomorphismGroups 6 Matrices 6.1 Some operations for matrices 6.1-1 DirectSumDecompositionMatrices 7 Iterators 7.1 Some iterators for groups and their isomorphisms 7.1-1 AllIsomorphismsIterator 7.1-2 AllSubgroupsIterator 7.2 Operations on iterators 7.2-1 CartesianIterator 7.2-2 UnorderedPairsIterator 8 Records 8.1 Functions for records 8.1-1 AssignGlobals 8.2 Option records for functions 8.2-1 OptionRecordWithDefaults 9 Web Downloads 9.1 Functions for downloading files from the web 9.1-1 Download 9.1-2 User preference DownloadVerifyCertificate 9.1-3 User preference DownloadMaxTime 10 Generalized Straight Line Programs 10.1 Functions for Generalized Straight Line Programs 10.1-1 IsGeneralizedStraightLineProgram 10.1-2 GeneralizedStraightLineProgram 10.1-3 DataOfGeneralizedStraightLineProgram 10.1-4 NrInputsOfGeneralizedStraightLineProgram 10.1-5 NrOutputsOfGeneralizedStraightLineProgram 10.1-6 ResultOfGeneralizedStraightLineProgram 10.1-7 EquivalentStraightLineProgram 10.1-8 IsInternallyConsistent 11 Various other functions 11.1 File operations 11.1-1 Log2HTML 11.2 LaTeX strings 11.2-1 IntOrInfinityToLaTeX 11.2-2 LaTeXStringFactorsInt 11.3 Conversion to Magma strings 11.3-1 ConvertToMagmaInputString 12 Obsolete functions 12.1 Operations from AutoDoc 12.2 Functions for printing 12.3 Other obsolete functions 12.3-1 Applicable Methods 12.3-2 ExponentOfPrime 13 The transfer procedure  utils-0.94/doc/chap0_mj.html0000644000000000000000000005232315174515600012661 0ustar00 GAP (Utils) - Contents
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

utils

Utility functions in GAP

0.94

30 April 2026

Thomas Breuer
Email: sam@math.rwth-aachen.de
Homepage: https://www.math.rwth-aachen.de/~Thomas.Breuer

Sebastian Gutsche
Email: gutsche@mathematik.uni-siegen.de
Homepage: https://sebasguts.github.io/

Max Horn
Email: mhorn@rptu.de
Homepage: https://github.com/mhorn

Alexander Hulpke
Email: hulpke@math.colostate.edu
Homepage: https://www.math.colostate.edu/~hulpke

Pedro García-Sánchez
Email: pedro@ugr.es
Homepage: http://www.ugr.es/local/pedro

Christopher Jefferson
Email: caj21@st-andrews.ac.uk
Homepage: https://caj.host.cs.st-andrews.ac.uk/

Stefan Kohl
Email: stefan@mcs.st-and.ac.uk
Homepage: https://www.gap-system.org/DevelopersPages/StefanKohl/

Frank Lübeck
Email: Frank.Luebeck@Math.RWTH-Aachen.De
Homepage: https://www.math.rwth-aachen.de/~Frank.Luebeck

Chris Wensley
Email: cdwensley.maths@btinternet.com
Homepage: https://github.com/cdwensley

Abstract

The Utils package provides a space for utility functions in a variety of GAP packages to be collected together into a single package. In this way it is hoped that they will become more visible to package authors.

Any package author who transfers a function to Utils will become an author of Utils.

If deemed appropriate, functions may also be transferred from the main library.

Bug reports, suggestions and comments are, of course, welcome. Please contact the last author at cdwensley.maths@btinternet.com or submit an issue at the GitHub repository https://github.com/gap-packages/utils/issues/.

Copyright

© 2015-2026, The GAP Group.

The Utils package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

Acknowledgements

This documentation was prepared using the GAPDoc [LN17] and AutoDoc [GH16] packages.

The procedure used to produce new releases uses the package GitHubPagesForGAP [Hor17] and the package ReleaseTools.

Contents


Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap1.html0000644000000000000000000002102015174515600012162 0ustar00 GAP (Utils) - Chapter 1: Introduction
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

1 Introduction

The Utils package provides a space for utility functions from a variety of GAP packages to be collected together into a single package. In this way it is hoped that they will become more visible to other package authors. This package was first distributed as part of the GAP 4.8.2 distribution.

The package is loaded with the command

gap> LoadPackage( "utils" );
true

Functions have been transferred from the following packages:

  • Conversion of a GAP group to a Magma output string, taken from various sources including other.gi in the main library.

Transfer is complete (for now) for functions from the following packages:

The package may be obtained either as a compressed .tar file or as a .zip file, utils-version_number.tar.gz, by ftp from one of the following sites:

The package also has a GitHub repository at: https://github.com/gap-packages/utils.

Once the package is loaded, the manual doc/manual.pdf can be found in the documentation folder. The html versions, with or without MathJax, may be rebuilt as follows:

gap> ReadPackage( "utils", "makedoc.g" ); 

It is possible to check that the package has been installed correctly by running the test files (which terminates the GAP session):

gap> ReadPackage( "utils", "tst/testall.g" );
Architecture: . . . . . 
testing: . . . . . 
. . . 
#I  No errors detected while testing

Note that functions listed in this manual that are currently in the process of being transferred are only read from the source package Home (say), and so can only be used if Home has already been loaded. There are no such functions in transition at present.

1.1 Information for package authors

A function (or collection of functions) is suitable for transfer from a package Home to Utils if the following conditions are satisfied.

  • The function is sufficiently non-specialised so that it might be of use to other authors.

  • The function does not depend on the remaining functions in Home

  • The function does not do what can already be done with a GAP library function.

  • Documentation of the function and test examples are available.

  • When there is more than one active author of Home, they should all be aware (and content) that the transfer is taking place.

Authors of packages may be reluctant to let go of their utility functions. The following principles may help to reassure them. (Suggestions for more items here are welcome.)

  • A function that has been transferred to Utils will not be changed without the approval of the original author.

  • The current package maintainer has every intention of continuing to maintain Utils. In the event that this proves impossible, the GAP development team will surely find someone to take over.

  • Function names will not be changed unless specifically requested by Home's author(s) or unless they have the form HOME_FunctionName.

  • In order to speed up the transfer process, only functions from one package will be in transition at any given time. Hopefully a week or two will suffice for most packages.

  • Any package author who transfers a function to Utils will become an author of Utils. (In truth, Utils does not have authors, just a large number of contributors.)

The process for transferring utility functions from Home to Utils is described in Chapter 13.

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap1.txt0000644000000000000000000001252415174515600012046 0ustar00 1 Introduction The Utils package provides a space for utility functions from a variety of GAP packages to be collected together into a single package. In this way it is hoped that they will become more visible to other package authors. This package was first distributed as part of the GAP 4.8.2 distribution. The package is loaded with the command  Example  gap> LoadPackage( "utils" ); true  Functions have been transferred from the following packages:  Conversion of a GAP group to a Magma output string, taken from various sources including other.gi in the main library. Transfer is complete (for now) for functions from the following packages:  AutoDoc [GH16] (with function names changed);  ResClasses [Koh17b];  RCWA [Koh17a];  XMod [WAOU17]. The package may be obtained either as a compressed .tar file or as a .zip file, utils-version_number.tar.gz, by ftp from one of the following sites:  the Utils GitHub release site: https://gap-packages.github.io/utils/.  any GAP archive, e.g. https://www.gap-system.org/Packages/packages.html; The package also has a GitHub repository at: https://github.com/gap-packages/utils. Once the package is loaded, the manual doc/manual.pdf can be found in the documentation folder. The html versions, with or without MathJax, may be rebuilt as follows:  Example  gap> ReadPackage( "utils", "makedoc.g" );   It is possible to check that the package has been installed correctly by running the test files (which terminates the GAP session):  Example  gap> ReadPackage( "utils", "tst/testall.g" ); Architecture: . . . . .  testing: . . . . .  . . .  #I No errors detected while testing  Note that functions listed in this manual that are currently in the process of being transferred are only read from the source package Home (say), and so can only be used if Home has already been loaded. There are no such functions in transition at present. 1.1 Information for package authors A function (or collection of functions) is suitable for transfer from a package Home to Utils if the following conditions are satisfied.  The function is sufficiently non-specialised so that it might be of use to other authors.  The function does not depend on the remaining functions in Home  The function does not do what can already be done with a GAP library function.  Documentation of the function and test examples are available.  When there is more than one active author of Home, they should all be aware (and content) that the transfer is taking place. Authors of packages may be reluctant to let go of their utility functions. The following principles may help to reassure them. (Suggestions for more items here are welcome.)  A function that has been transferred to Utils will not be changed without the approval of the original author.  The current package maintainer has every intention of continuing to maintain Utils. In the event that this proves impossible, the GAP development team will surely find someone to take over.  Function names will not be changed unless specifically requested by Home's author(s) or unless they have the form HOME_FunctionName.  In order to speed up the transfer process, only functions from one package will be in transition at any given time. Hopefully a week or two will suffice for most packages.  Any package author who transfers a function to Utils will become an author of Utils. (In truth, Utils does not have authors, just a large number of contributors.) The process for transferring utility functions from Home to Utils is described in Chapter 13. utils-0.94/doc/chap10.html0000644000000000000000000006522315174515600012257 0ustar00 GAP (Utils) - Chapter 10: Generalized Straight Line Programs
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

10 Generalized Straight Line Programs

The functions described in this chapter have been written by Thomas Breuer, they are available since Utils 0.94.

Generalized straight line programs (in the following abbreviated as gslps) are a generalization of the straight line programs that are described in the GAP library, see Reference: Straight Line Programs. Like the latter objects, gslps describe an efficient way for evaluating an abstract word at concrete generators. The difference is that gslps can be built from existing (generalized) straight line programs, whereas a straight line program is given by an explicit list of instructions (see LinesOfStraightLineProgram (Reference: LinesOfStraightLineProgram)). So the advantages of using a gslp instead of constructing an equivalent straight line program (see EquivalentStraightLineProgram (10.1-7)) are that

  • available objects (the building blocks of the gslp) are reused,

  • the internal structure of the gslp is retained (one can access the building blocks if one wants), and

  • in the evaluation of a gslp, the intermediate results that arise in a building block of the gslp can be garbage collected as soon as the evaluation of this building block has finished.

A gslp in GAP is represented by an object in the category IsGeneralizedStraightLineProgram (10.1-1). This object has exactly one of the following forms.

  • It is a straight line program, that is, it lies in the category IsStraightLineProgram (Reference: IsStraightLineProgram), and evaluation at some group elements is defined by ResultOfStraightLineProgram (Reference: ResultOfStraightLineProgram).

  • It is of union kind, that is, the defining data are a nonempty list l of gslps, and evaluation at some group elements means to evaluate the gslps in l at these group elements, and to return the concatenation of the results.

  • It is of compose kind, that is, the defining data are a nonempty list l of gslps, and evaluation at some group elements means to evaluate l[1] at these elements, then to evaluate l[2] at the result of the first evaluation, and so on, and to return the last result.

Here are two typical situations where gslps arise. In both cases, suppose that a list l of standard generators for a group G is given.

  1. Suppose that we know a straight line program for computing generators l' of a maximal subgroup M of G from l. For example, these data may be taken from the ATLAS of Group Representations [WWT+]. If M is also a group for which the ATLAS of Group Representations contains generators and straight line programs, we may be interested in computing standard generators l'' for M from l'.

    For that, a second straight line program may be needed, and it makes sense to encode the computation of l'' from l via a gslp of compose kind.

  2. Suppose that we are in fact interested in a downward extension H of G, and that π is the natural epimorphism from H to G, which maps a list L, say, of standard generators of H to l. Then the above gslp for G can be applied to L, but the result L' may generate a proper subgroup of π^-1(M) because some part of the kernel of π is missing.

    A list K of generators of the kernel of π can be described by a straight line program that takes L as its input, and it makes sense to encode the computation of the concatenation of L' and K from L via a gslp of union kind.

Gslps can be constructed using GeneralizedStraightLineProgram (10.1-2).

Defining attributes for gslps are NrInputsOfGeneralizedStraightLineProgram (10.1-4) and DataOfGeneralizedStraightLineProgram (10.1-3). The probably most interesting operation for gslps is ResultOfGeneralizedStraightLineProgram (10.1-6).

Currently we do not intend to provide methods applicable to generalized straight line programs for all operations that are defined for straight line programs. For example, there is no IntermediateResultOfSLP (Reference: IntermediateResultOfSLP) method for generalized straight line programs.

Special methods applicable to gslps are installed for the operations IsInternallyConsistent (10.1-8), ViewString (Reference: ViewString), and String (Reference: String).

10.1 Functions for Generalized Straight Line Programs

10.1-1 IsGeneralizedStraightLineProgram
‣ IsGeneralizedStraightLineProgram( obj )( category )

Each generalized straight line program in GAP lies in the category IsGeneralizedStraightLineProgram. Examples are straight line programs, that is, objects in the category IsStraightLineProgram (Reference: IsStraightLineProgram).

gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> IsGeneralizedStraightLineProgram( gslp );
true
gap> slp:= StraightLineProgram( [[[1,2]]], 1 );
<straight line program>
gap> IsGeneralizedStraightLineProgram( slp );
true
gap> IsGeneralizedStraightLineProgram( [ slp, slp ] );
false

10.1-2 GeneralizedStraightLineProgram
‣ GeneralizedStraightLineProgram( lines[, nrgens] )( function )
‣ GeneralizedStraightLineProgram( kind, list )( function )

In the first form, lines must be a list of lists that defines a unique straight line program (see IsStraightLineProgram (Reference: IsStraightLineProgram)); in this case GeneralizedStraightLineProgram delegates to StraightLineProgram (Reference: StraightLineProgram for a list of lines (and the number of generators)).

In the second form, kind must be one of the strings "union" or "compose", and list must be a nonempty list such that each of its entries is either a gslp or a list l, say, such that CallFuncList (Reference: CallFuncList) applied to GeneralizedStraightLineProgram and l returns a gslp.

gap> GeneralizedStraightLineProgram( [[[1,2]]], 1 );
<straight line program>
gap> GeneralizedStraightLineProgram( "union",
> [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> GeneralizedStraightLineProgram( "compose",
> [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>

10.1-3 DataOfGeneralizedStraightLineProgram
‣ DataOfGeneralizedStraightLineProgram( gslp )( attribute )

For a generalized straight line program gslp that is not a straight line program, DataOfGeneralizedStraightLineProgram returns a list of length two, the first entry being either "union" or "compose" and the second being the list of defining generalized straight line programs.

If gslp is a straight line program then this attribute is not set in gslp. There is no default method to compute the value if it is not stored.

gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> DataOfGeneralizedStraightLineProgram( gslp );
[ "union", [ <straight line program>, <straight line program> ] ]

10.1-4 NrInputsOfGeneralizedStraightLineProgram
‣ NrInputsOfGeneralizedStraightLineProgram( gslp )( attribute )

For a generalized straight line program gslp, this function returns the number of generators that are needed as input.

If gslp is a straight line program then it may be necessary that the value is set in the construction of gslp, see NrInputsOfStraightLineProgram (Reference: NrInputsOfStraightLineProgram). If gslp is not a straight line program then the value is determined by the (generalized) straight line programs from which gslp is constructed.

gap> NrInputsOfGeneralizedStraightLineProgram(
>        GeneralizedStraightLineProgram( "union",
>            [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) );
1

In order to avoid the introduction of unnecessary filters, we define NrInputsOfGeneralizedStraightLineProgram just as a synonym of NrInputsOfStraightLineProgram (Reference: NrInputsOfStraightLineProgram).

10.1-5 NrOutputsOfGeneralizedStraightLineProgram
‣ NrOutputsOfGeneralizedStraightLineProgram( gslp )( attribute )

For a generalized straight line program gslp, this function returns the number of elements returned by ResultOfGeneralizedStraightLineProgram (10.1-6) when gslp is evaluated.

Note that the GAP library does not define a corresponding attribute for straight line programs.

gap> NrOutputsOfGeneralizedStraightLineProgram(
>        GeneralizedStraightLineProgram( "union",
>            [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) );
2
gap> NrOutputsOfGeneralizedStraightLineProgram(
>        GeneralizedStraightLineProgram( "compose",
>            [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) );
1

10.1-6 ResultOfGeneralizedStraightLineProgram
‣ ResultOfGeneralizedStraightLineProgram( gslp, gens )( operation )

ResultOfGeneralizedStraightLineProgram evaluates the generalized straight line program (see IsGeneralizedStraightLineProgram (10.1-1)) gslp at the group elements in the list gens, as follows.

  • If gslp is a straight line program then the value of ResultOfStraightLineProgram (Reference: ResultOfStraightLineProgram) is returned.

  • If gslp is of union kind then ResultOfGeneralizedStraightLineProgram is applied to each of the involved generalized straight line programs, with second argument gens, and the concatenation of the results is returned.

  • If gslp is of compose kind then ResultOfGeneralizedStraightLineProgram is first called with the first involved generalized straight line program and gens, then the operation is called with the second involved generalized straight line program and the result of this call, and so on; the last such result is returned.

gap> gens:= [ (1,2,3,4,5,6) ];;
gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> ResultOfGeneralizedStraightLineProgram( gslp, gens );
[ (1,3,5)(2,4,6), (1,4)(2,5)(3,6) ]
gap> gslp:= GeneralizedStraightLineProgram( "compose",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> ResultOfGeneralizedStraightLineProgram( gslp, gens );
[ () ]

In order to avoid the introduction of unnecessary operations, we define ResultOfGeneralizedStraightLineProgram just as a synonym of ResultOfStraightLineProgram (Reference: ResultOfStraightLineProgram).

10.1-7 EquivalentStraightLineProgram
‣ EquivalentStraightLineProgram( gslp )( attribute )

For a generalized straight line program gslp, EquivalentStraightLineProgram returns a straight line program such that evaluating gslp and this straight line program with ResultOfGeneralizedStraightLineProgram (10.1-6) yields the same output, for any list of input elements.

gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> slp:= EquivalentStraightLineProgram( gslp );
<straight line program>
gap> Display( slp );
# input:
r:= [ g1 ];
# program:
# return values:
[ r[1]^2, r[1]^3 ]
gap> gslp:= GeneralizedStraightLineProgram( "compose",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> slp:= EquivalentStraightLineProgram( gslp );
<straight line program>
gap> Display( slp );
# input:
r:= [ g1 ];
# program:
r[2]:= r[1]^2;
r[1]:= r[2];
# return values:
[ r[1]^3 ]

10.1-8 IsInternallyConsistent
‣ IsInternallyConsistent( gslp )( method )

For a generalized straight line program gslp, it is checked whether all (generalized) straight line programs from which gslp is built are internally consistent, and whether their numbers of inputs and outputs are consistent and compatible with the numbers of inputs and outputs of gslp.

gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );;
gap> IsInternallyConsistent( gslp );
true
gap> gslp:= GeneralizedStraightLineProgram( "compose",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );;
gap> IsInternallyConsistent( gslp );
true
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap10.txt0000644000000000000000000004406115174515600012127 0ustar00 10 Generalized Straight Line Programs The functions described in this chapter have been written by Thomas Breuer, they are available since Utils 0.94. Generalized straight line programs (in the following abbreviated as gslps) are a generalization of the straight line programs that are described in the GAP library, see 'Reference: Straight Line Programs'. Like the latter objects, gslps describe an efficient way for evaluating an abstract word at concrete generators. The difference is that gslps can be built from existing (generalized) straight line programs, whereas a straight line program is given by an explicit list of instructions (see LinesOfStraightLineProgram (Reference: LinesOfStraightLineProgram)). So the advantages of using a gslp instead of constructing an equivalent straight line program (see EquivalentStraightLineProgram (10.1-7)) are that  available objects (the building blocks of the gslp) are reused,  the internal structure of the gslp is retained (one can access the building blocks if one wants), and  in the evaluation of a gslp, the intermediate results that arise in a building block of the gslp can be garbage collected as soon as the evaluation of this building block has finished. A gslp in GAP is represented by an object in the category IsGeneralizedStraightLineProgram (10.1-1). This object has exactly one of the following forms.  It is a straight line program, that is, it lies in the category IsStraightLineProgram (Reference: IsStraightLineProgram), and evaluation at some group elements is defined by ResultOfStraightLineProgram (Reference: ResultOfStraightLineProgram).  It is of union kind, that is, the defining data are a nonempty list l of gslps, and evaluation at some group elements means to evaluate the gslps in l at these group elements, and to return the concatenation of the results.  It is of compose kind, that is, the defining data are a nonempty list l of gslps, and evaluation at some group elements means to evaluate l[1] at these elements, then to evaluate l[2] at the result of the first evaluation, and so on, and to return the last result. Here are two typical situations where gslps arise. In both cases, suppose that a list l of standard generators for a group G is given. 1 Suppose that we know a straight line program for computing generators l' of a maximal subgroup M of G from l. For example, these data may be taken from the ATLAS of Group Representations [WWT+]. If M is also a group for which the ATLAS of Group Representations contains generators and straight line programs, we may be interested in computing standard generators l'' for M from l'. For that, a second straight line program may be needed, and it makes sense to encode the computation of l'' from l via a gslp of compose kind. 2 Suppose that we are in fact interested in a downward extension H of G, and that π is the natural epimorphism from H to G, which maps a list L, say, of standard generators of H to l. Then the above gslp for G can be applied to L, but the result L' may generate a proper subgroup of π^-1(M) because some part of the kernel of π is missing. A list K of generators of the kernel of π can be described by a straight line program that takes L as its input, and it makes sense to encode the computation of the concatenation of L' and K from L via a gslp of union kind. Gslps can be constructed using GeneralizedStraightLineProgram (10.1-2). Defining attributes for gslps are NrInputsOfGeneralizedStraightLineProgram (10.1-4) and DataOfGeneralizedStraightLineProgram (10.1-3). The probably most interesting operation for gslps is ResultOfGeneralizedStraightLineProgram (10.1-6). Currently we do not intend to provide methods applicable to generalized straight line programs for all operations that are defined for straight line programs. For example, there is no IntermediateResultOfSLP (Reference: IntermediateResultOfSLP) method for generalized straight line programs. Special methods applicable to gslps are installed for the operations IsInternallyConsistent (10.1-8), ViewString (Reference: ViewString), and String (Reference: String). 10.1 Functions for Generalized Straight Line Programs 10.1-1 IsGeneralizedStraightLineProgram IsGeneralizedStraightLineProgram( obj )  category Each generalized straight line program in GAP lies in the category IsGeneralizedStraightLineProgram. Examples are straight line programs, that is, objects in the category IsStraightLineProgram (Reference: IsStraightLineProgram).  Example  gap> gslp:= GeneralizedStraightLineProgram( "union", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );  gap> IsGeneralizedStraightLineProgram( gslp ); true gap> slp:= StraightLineProgram( [[[1,2]]], 1 );  gap> IsGeneralizedStraightLineProgram( slp ); true gap> IsGeneralizedStraightLineProgram( [ slp, slp ] ); false  10.1-2 GeneralizedStraightLineProgram GeneralizedStraightLineProgram( lines[, nrgens] )  function GeneralizedStraightLineProgram( kind, list )  function In the first form, lines must be a list of lists that defines a unique straight line program (see IsStraightLineProgram (Reference: IsStraightLineProgram)); in this case GeneralizedStraightLineProgram delegates to StraightLineProgram (Reference: StraightLineProgram for a list of lines (and the number of generators)). In the second form, kind must be one of the strings "union" or "compose", and list must be a nonempty list such that each of its entries is either a gslp or a list l, say, such that CallFuncList (Reference: CallFuncList) applied to GeneralizedStraightLineProgram and l returns a gslp.  Example  gap> GeneralizedStraightLineProgram( [[[1,2]]], 1 );  gap> GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );  gap> GeneralizedStraightLineProgram( "compose", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );   10.1-3 DataOfGeneralizedStraightLineProgram DataOfGeneralizedStraightLineProgram( gslp )  attribute For a generalized straight line program gslp that is not a straight line program, DataOfGeneralizedStraightLineProgram returns a list of length two, the first entry being either "union" or "compose" and the second being the list of defining generalized straight line programs. If gslp is a straight line program then this attribute is not set in gslp. There is no default method to compute the value if it is not stored.  Example  gap> gslp:= GeneralizedStraightLineProgram( "union", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );  gap> DataOfGeneralizedStraightLineProgram( gslp ); [ "union", [ , ] ]  10.1-4 NrInputsOfGeneralizedStraightLineProgram NrInputsOfGeneralizedStraightLineProgram( gslp )  attribute For a generalized straight line program gslp, this function returns the number of generators that are needed as input. If gslp is a straight line program then it may be necessary that the value is set in the construction of gslp, see NrInputsOfStraightLineProgram (Reference: NrInputsOfStraightLineProgram). If gslp is not a straight line program then the value is determined by the (generalized) straight line programs from which gslp is constructed.  Example  gap> NrInputsOfGeneralizedStraightLineProgram( >  GeneralizedStraightLineProgram( "union", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); 1  In order to avoid the introduction of unnecessary filters, we define NrInputsOfGeneralizedStraightLineProgram just as a synonym of NrInputsOfStraightLineProgram (Reference: NrInputsOfStraightLineProgram). 10.1-5 NrOutputsOfGeneralizedStraightLineProgram NrOutputsOfGeneralizedStraightLineProgram( gslp )  attribute For a generalized straight line program gslp, this function returns the number of elements returned by ResultOfGeneralizedStraightLineProgram (10.1-6) when gslp is evaluated. Note that the GAP library does not define a corresponding attribute for straight line programs.  Example  gap> NrOutputsOfGeneralizedStraightLineProgram( >  GeneralizedStraightLineProgram( "union", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); 2 gap> NrOutputsOfGeneralizedStraightLineProgram( >  GeneralizedStraightLineProgram( "compose", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); 1  10.1-6 ResultOfGeneralizedStraightLineProgram ResultOfGeneralizedStraightLineProgram( gslp, gens )  operation ResultOfGeneralizedStraightLineProgram evaluates the generalized straight line program (see IsGeneralizedStraightLineProgram (10.1-1)) gslp at the group elements in the list gens, as follows.  If gslp is a straight line program then the value of ResultOfStraightLineProgram (Reference: ResultOfStraightLineProgram) is returned.  If gslp is of union kind then ResultOfGeneralizedStraightLineProgram is applied to each of the involved generalized straight line programs, with second argument gens, and the concatenation of the results is returned.  If gslp is of compose kind then ResultOfGeneralizedStraightLineProgram is first called with the first involved generalized straight line program and gens, then the operation is called with the second involved generalized straight line program and the result of this call, and so on; the last such result is returned.  Example  gap> gens:= [ (1,2,3,4,5,6) ];; gap> gslp:= GeneralizedStraightLineProgram( "union", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );  gap> ResultOfGeneralizedStraightLineProgram( gslp, gens ); [ (1,3,5)(2,4,6), (1,4)(2,5)(3,6) ] gap> gslp:= GeneralizedStraightLineProgram( "compose", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );  gap> ResultOfGeneralizedStraightLineProgram( gslp, gens ); [ () ]  In order to avoid the introduction of unnecessary operations, we define ResultOfGeneralizedStraightLineProgram just as a synonym of ResultOfStraightLineProgram (Reference: ResultOfStraightLineProgram). 10.1-7 EquivalentStraightLineProgram EquivalentStraightLineProgram( gslp )  attribute For a generalized straight line program gslp, EquivalentStraightLineProgram returns a straight line program such that evaluating gslp and this straight line program with ResultOfGeneralizedStraightLineProgram (10.1-6) yields the same output, for any list of input elements.  Example  gap> gslp:= GeneralizedStraightLineProgram( "union", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );  gap> slp:= EquivalentStraightLineProgram( gslp );  gap> Display( slp ); # input: r:= [ g1 ]; # program: # return values: [ r[1]^2, r[1]^3 ] gap> gslp:= GeneralizedStraightLineProgram( "compose", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );  gap> slp:= EquivalentStraightLineProgram( gslp );  gap> Display( slp ); # input: r:= [ g1 ]; # program: r[2]:= r[1]^2; r[1]:= r[2]; # return values: [ r[1]^3 ]  10.1-8 IsInternallyConsistent IsInternallyConsistent( gslp )  method For a generalized straight line program gslp, it is checked whether all (generalized) straight line programs from which gslp is built are internally consistent, and whether their numbers of inputs and outputs are consistent and compatible with the numbers of inputs and outputs of gslp.  Example  gap> gslp:= GeneralizedStraightLineProgram( "union", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; gap> IsInternallyConsistent( gslp ); true gap> gslp:= GeneralizedStraightLineProgram( "compose", >  [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; gap> IsInternallyConsistent( gslp ); true  utils-0.94/doc/chap10_mj.html0000644000000000000000000006622415174515600012747 0ustar00 GAP (Utils) - Chapter 10: Generalized Straight Line Programs
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

10 Generalized Straight Line Programs

The functions described in this chapter have been written by Thomas Breuer, they are available since Utils 0.94.

Generalized straight line programs (in the following abbreviated as gslps) are a generalization of the straight line programs that are described in the GAP library, see Reference: Straight Line Programs. Like the latter objects, gslps describe an efficient way for evaluating an abstract word at concrete generators. The difference is that gslps can be built from existing (generalized) straight line programs, whereas a straight line program is given by an explicit list of instructions (see LinesOfStraightLineProgram (Reference: LinesOfStraightLineProgram)). So the advantages of using a gslp instead of constructing an equivalent straight line program (see EquivalentStraightLineProgram (10.1-7)) are that

  • available objects (the building blocks of the gslp) are reused,

  • the internal structure of the gslp is retained (one can access the building blocks if one wants), and

  • in the evaluation of a gslp, the intermediate results that arise in a building block of the gslp can be garbage collected as soon as the evaluation of this building block has finished.

A gslp in GAP is represented by an object in the category IsGeneralizedStraightLineProgram (10.1-1). This object has exactly one of the following forms.

  • It is a straight line program, that is, it lies in the category IsStraightLineProgram (Reference: IsStraightLineProgram), and evaluation at some group elements is defined by ResultOfStraightLineProgram (Reference: ResultOfStraightLineProgram).

  • It is of union kind, that is, the defining data are a nonempty list \(l\) of gslps, and evaluation at some group elements means to evaluate the gslps in \(l\) at these group elements, and to return the concatenation of the results.

  • It is of compose kind, that is, the defining data are a nonempty list \(l\) of gslps, and evaluation at some group elements means to evaluate \(l[1]\) at these elements, then to evaluate \(l[2]\) at the result of the first evaluation, and so on, and to return the last result.

Here are two typical situations where gslps arise. In both cases, suppose that a list \(l\) of standard generators for a group \(G\) is given.

  1. Suppose that we know a straight line program for computing generators \(l'\) of a maximal subgroup \(M\) of \(G\) from \(l\). For example, these data may be taken from the ATLAS of Group Representations [WWT+]. If \(M\) is also a group for which the ATLAS of Group Representations contains generators and straight line programs, we may be interested in computing standard generators \(l''\) for \(M\) from \(l'\).

    For that, a second straight line program may be needed, and it makes sense to encode the computation of \(l''\) from \(l\) via a gslp of compose kind.

  2. Suppose that we are in fact interested in a downward extension \(H\) of \(G\), and that \(\pi\) is the natural epimorphism from \(H\) to \(G\), which maps a list \(L\), say, of standard generators of \(H\) to \(l\). Then the above gslp for \(G\) can be applied to \(L\), but the result \(L'\) may generate a proper subgroup of \(\pi^{-1}(M)\) because some part of the kernel of \(\pi\) is missing.

    A list \(K\) of generators of the kernel of \(\pi\) can be described by a straight line program that takes \(L\) as its input, and it makes sense to encode the computation of the concatenation of \(L'\) and \(K\) from \(L\) via a gslp of union kind.

Gslps can be constructed using GeneralizedStraightLineProgram (10.1-2).

Defining attributes for gslps are NrInputsOfGeneralizedStraightLineProgram (10.1-4) and DataOfGeneralizedStraightLineProgram (10.1-3). The probably most interesting operation for gslps is ResultOfGeneralizedStraightLineProgram (10.1-6).

Currently we do not intend to provide methods applicable to generalized straight line programs for all operations that are defined for straight line programs. For example, there is no IntermediateResultOfSLP (Reference: IntermediateResultOfSLP) method for generalized straight line programs.

Special methods applicable to gslps are installed for the operations IsInternallyConsistent (10.1-8), ViewString (Reference: ViewString), and String (Reference: String).

10.1 Functions for Generalized Straight Line Programs

10.1-1 IsGeneralizedStraightLineProgram
‣ IsGeneralizedStraightLineProgram( obj )( category )

Each generalized straight line program in GAP lies in the category IsGeneralizedStraightLineProgram. Examples are straight line programs, that is, objects in the category IsStraightLineProgram (Reference: IsStraightLineProgram).

gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> IsGeneralizedStraightLineProgram( gslp );
true
gap> slp:= StraightLineProgram( [[[1,2]]], 1 );
<straight line program>
gap> IsGeneralizedStraightLineProgram( slp );
true
gap> IsGeneralizedStraightLineProgram( [ slp, slp ] );
false

10.1-2 GeneralizedStraightLineProgram
‣ GeneralizedStraightLineProgram( lines[, nrgens] )( function )
‣ GeneralizedStraightLineProgram( kind, list )( function )

In the first form, lines must be a list of lists that defines a unique straight line program (see IsStraightLineProgram (Reference: IsStraightLineProgram)); in this case GeneralizedStraightLineProgram delegates to StraightLineProgram (Reference: StraightLineProgram for a list of lines (and the number of generators)).

In the second form, kind must be one of the strings "union" or "compose", and list must be a nonempty list such that each of its entries is either a gslp or a list \(l\), say, such that CallFuncList (Reference: CallFuncList) applied to GeneralizedStraightLineProgram and \(l\) returns a gslp.

gap> GeneralizedStraightLineProgram( [[[1,2]]], 1 );
<straight line program>
gap> GeneralizedStraightLineProgram( "union",
> [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> GeneralizedStraightLineProgram( "compose",
> [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>

10.1-3 DataOfGeneralizedStraightLineProgram
‣ DataOfGeneralizedStraightLineProgram( gslp )( attribute )

For a generalized straight line program gslp that is not a straight line program, DataOfGeneralizedStraightLineProgram returns a list of length two, the first entry being either "union" or "compose" and the second being the list of defining generalized straight line programs.

If gslp is a straight line program then this attribute is not set in gslp. There is no default method to compute the value if it is not stored.

gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> DataOfGeneralizedStraightLineProgram( gslp );
[ "union", [ <straight line program>, <straight line program> ] ]

10.1-4 NrInputsOfGeneralizedStraightLineProgram
‣ NrInputsOfGeneralizedStraightLineProgram( gslp )( attribute )

For a generalized straight line program gslp, this function returns the number of generators that are needed as input.

If gslp is a straight line program then it may be necessary that the value is set in the construction of gslp, see NrInputsOfStraightLineProgram (Reference: NrInputsOfStraightLineProgram). If gslp is not a straight line program then the value is determined by the (generalized) straight line programs from which gslp is constructed.

gap> NrInputsOfGeneralizedStraightLineProgram(
>        GeneralizedStraightLineProgram( "union",
>            [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) );
1

In order to avoid the introduction of unnecessary filters, we define NrInputsOfGeneralizedStraightLineProgram just as a synonym of NrInputsOfStraightLineProgram (Reference: NrInputsOfStraightLineProgram).

10.1-5 NrOutputsOfGeneralizedStraightLineProgram
‣ NrOutputsOfGeneralizedStraightLineProgram( gslp )( attribute )

For a generalized straight line program gslp, this function returns the number of elements returned by ResultOfGeneralizedStraightLineProgram (10.1-6) when gslp is evaluated.

Note that the GAP library does not define a corresponding attribute for straight line programs.

gap> NrOutputsOfGeneralizedStraightLineProgram(
>        GeneralizedStraightLineProgram( "union",
>            [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) );
2
gap> NrOutputsOfGeneralizedStraightLineProgram(
>        GeneralizedStraightLineProgram( "compose",
>            [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) );
1

10.1-6 ResultOfGeneralizedStraightLineProgram
‣ ResultOfGeneralizedStraightLineProgram( gslp, gens )( operation )

ResultOfGeneralizedStraightLineProgram evaluates the generalized straight line program (see IsGeneralizedStraightLineProgram (10.1-1)) gslp at the group elements in the list gens, as follows.

  • If gslp is a straight line program then the value of ResultOfStraightLineProgram (Reference: ResultOfStraightLineProgram) is returned.

  • If gslp is of union kind then ResultOfGeneralizedStraightLineProgram is applied to each of the involved generalized straight line programs, with second argument gens, and the concatenation of the results is returned.

  • If gslp is of compose kind then ResultOfGeneralizedStraightLineProgram is first called with the first involved generalized straight line program and gens, then the operation is called with the second involved generalized straight line program and the result of this call, and so on; the last such result is returned.

gap> gens:= [ (1,2,3,4,5,6) ];;
gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> ResultOfGeneralizedStraightLineProgram( gslp, gens );
[ (1,3,5)(2,4,6), (1,4)(2,5)(3,6) ]
gap> gslp:= GeneralizedStraightLineProgram( "compose",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> ResultOfGeneralizedStraightLineProgram( gslp, gens );
[ () ]

In order to avoid the introduction of unnecessary operations, we define ResultOfGeneralizedStraightLineProgram just as a synonym of ResultOfStraightLineProgram (Reference: ResultOfStraightLineProgram).

10.1-7 EquivalentStraightLineProgram
‣ EquivalentStraightLineProgram( gslp )( attribute )

For a generalized straight line program gslp, EquivalentStraightLineProgram returns a straight line program such that evaluating gslp and this straight line program with ResultOfGeneralizedStraightLineProgram (10.1-6) yields the same output, for any list of input elements.

gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> slp:= EquivalentStraightLineProgram( gslp );
<straight line program>
gap> Display( slp );
# input:
r:= [ g1 ];
# program:
# return values:
[ r[1]^2, r[1]^3 ]
gap> gslp:= GeneralizedStraightLineProgram( "compose",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );
<generalized straight line program>
gap> slp:= EquivalentStraightLineProgram( gslp );
<straight line program>
gap> Display( slp );
# input:
r:= [ g1 ];
# program:
r[2]:= r[1]^2;
r[1]:= r[2];
# return values:
[ r[1]^3 ]

10.1-8 IsInternallyConsistent
‣ IsInternallyConsistent( gslp )( method )

For a generalized straight line program gslp, it is checked whether all (generalized) straight line programs from which gslp is built are internally consistent, and whether their numbers of inputs and outputs are consistent and compatible with the numbers of inputs and outputs of gslp.

gap> gslp:= GeneralizedStraightLineProgram( "union",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );;
gap> IsInternallyConsistent( gslp );
true
gap> gslp:= GeneralizedStraightLineProgram( "compose",
>               [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );;
gap> IsInternallyConsistent( gslp );
true
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap11.html0000644000000000000000000002652715174515600012264 0ustar00 GAP (Utils) - Chapter 11: Various other functions
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

11 Various other functions

11.1 File operations

11.1-1 Log2HTML
‣ Log2HTML( filename )( function )

This function has been transferred from package RCWA.

This function converts the GAP logfile filename to HTML. It appears that the logfile should be in your current directory. The extension of the input file must be *.log. The name of the output file is the same as the one of the input file except that the extension *.log is replaced by *.html. There is a sample CSS file in utils/doc/gaplog.css, which you can adjust to your taste.

gap> LogTo( "triv.log" );
gap> a := 33^5;
39135393
gap> LogTo(); 
gap> Log2HTML( "triv.log" );     

11.2 LaTeX strings

11.2-1 IntOrInfinityToLaTeX
‣ IntOrInfinityToLaTeX( n )( function )

This function has been transferred from package ResClasses.

IntOrInfinityToLaTeX returns the LaTeX string for n.

gap> IntOrInfinityToLaTeX( 10^3 );
"1000"
gap> IntOrInfinityToLaTeX( infinity );
"\\infty"

11.2-2 LaTeXStringFactorsInt
‣ LaTeXStringFactorsInt( n )( function )

This function has been transferred from package RCWA.

It returns the prime factorization of the integer n as a string in LaTeX format.

gap> LaTeXStringFactorsInt( Factorial(12) );
"2^{10} \\cdot 3^5 \\cdot 5^2 \\cdot 7 \\cdot 11"

11.3 Conversion to Magma strings

11.3-1 ConvertToMagmaInputString
‣ ConvertToMagmaInputString( arg )( function )

The function ConvertToMagmaInputString( obj [, str] ) attempts to output a string s which can be read into Magma [BCP97] so as to produce the same group in that computer algebra system. In the second form the user specifies the name of the resulting object, so that the output string has the form "str := ...".

When obj is a permutation group, the operation PermGroupToMagmaFormat(obj) is called. This function has been taken from other.gi in the main library where it was called MagmaInputString.

When obj is a pc-group, the operation PcGroupToMagmaFormat(obj) is called. This function was private code of Max Horn.

When obj is a matrix group over a finite field, the operation MatrixGroupToMagmaFormat(obj) is called. This function is a modification of private code of Frank Lübeck.

Hopefully code for other types of group will be added in due course.

These functions should be considered experimental, and more testing is desirable.

gap> ## permutation groups
gap> ConvertToMagmaInputString( Group( (1,2,3,4,5), (3,4,5) ) );
"PermutationGroup<5|(1,2,3,4,5),\n(3,4,5)>;\n"
gap> ConvertToMagmaInputString( Group( (1,2,3,4,5) ), "c5" );        
"c5 := PermutationGroup<5|(1,2,3,4,5)>;\n"
gap> ## pc-group
gap> ConvertToMagmaInputString( DihedralGroup( IsPcGroup, 10 ) );
"PolycyclicGroup< f1,f2 |\nf1^2,\nf2^5,\nf2^f1 = f2^4\n>;\n"
gap> ## fp-group
gap> F2 := FreeGroup( 2 );;
gap> f := F2.1;;  g := F2.2;;
gap> relq8 := [ f^4, g^4, f*g*f*g^-1, f^2*g^2 ];; 
gap> q8 := F2/relq8;; 
gap> ConvertToMagmaInputString( q8 );
no conversion function yet available for fp-groups
fail
gap> ## matrix group
gap> M := GL(2,5);;  Size(M); 
480
gap> s1 := ConvertToMagmaInputString( M );
"F := GF(5);\nP := GL(2,F);\ngens := [\nP![2,0,0,1],\nP![4,1,4,0]\n];\nsub<P |\
 gens>;\n"
gap> Print( s1 );
F := GF(5);
P := GL(2,F);
gens := [
P![2,0,0,1],
P![4,1,4,0]
];
sub<P | gens>;
gap> n1 := [ [ Z(9)^0, Z(9)^0 ], [ Z(9)^0, Z(9) ] ];;
gap> n2 := [ [ Z(9)^0, Z(9)^3 ], [ Z(9)^4, Z(9)^2 ] ];;
gap> N := Group( n1, n2 );;  Size( N );
5760
gap> s2 := ConvertToMagmaInputString( N, "gpN" );;
gap> Print( s2 );
F := GF(3^2);
P := GL(2,F);
w := PrimitiveElement(F);
gens := [
P![ 1, 1, 1,w^1],
P![ 1,w^3, 2,w^2]
];
gpN := sub<P | gens>;
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap11.txt0000644000000000000000000001450415174515600012127 0ustar00 11 Various other functions 11.1 File operations 11.1-1 Log2HTML Log2HTML( filename )  function This function has been transferred from package RCWA. This function converts the GAP logfile filename to HTML. It appears that the logfile should be in your current directory. The extension of the input file must be *.log. The name of the output file is the same as the one of the input file except that the extension *.log is replaced by *.html. There is a sample CSS file in utils/doc/gaplog.css, which you can adjust to your taste.  Example  gap> LogTo( "triv.log" ); gap> a := 33^5; 39135393 gap> LogTo();  gap> Log2HTML( "triv.log" );   11.2 LaTeX strings 11.2-1 IntOrInfinityToLaTeX IntOrInfinityToLaTeX( n )  function This function has been transferred from package ResClasses. IntOrInfinityToLaTeX returns the LaTeX string for n.  Example  gap> IntOrInfinityToLaTeX( 10^3 ); "1000" gap> IntOrInfinityToLaTeX( infinity ); "\\infty"  11.2-2 LaTeXStringFactorsInt LaTeXStringFactorsInt( n )  function This function has been transferred from package RCWA. It returns the prime factorization of the integer n as a string in LaTeX format.  Example  gap> LaTeXStringFactorsInt( Factorial(12) ); "2^{10} \\cdot 3^5 \\cdot 5^2 \\cdot 7 \\cdot 11"  11.3 Conversion to Magma strings 11.3-1 ConvertToMagmaInputString ConvertToMagmaInputString( arg )  function The function ConvertToMagmaInputString( obj [, str] ) attempts to output a string s which can be read into Magma [BCP97] so as to produce the same group in that computer algebra system. In the second form the user specifies the name of the resulting object, so that the output string has the form "str := ...". When obj is a permutation group, the operation PermGroupToMagmaFormat(obj) is called. This function has been taken from other.gi in the main library where it was called MagmaInputString. When obj is a pc-group, the operation PcGroupToMagmaFormat(obj) is called. This function was private code of Max Horn. When obj is a matrix group over a finite field, the operation MatrixGroupToMagmaFormat(obj) is called. This function is a modification of private code of Frank Lübeck. Hopefully code for other types of group will be added in due course. These functions should be considered experimental, and more testing is desirable.  Example  gap> ## permutation groups gap> ConvertToMagmaInputString( Group( (1,2,3,4,5), (3,4,5) ) ); "PermutationGroup<5|(1,2,3,4,5),\n(3,4,5)>;\n" gap> ConvertToMagmaInputString( Group( (1,2,3,4,5) ), "c5" );  "c5 := PermutationGroup<5|(1,2,3,4,5)>;\n" gap> ## pc-group gap> ConvertToMagmaInputString( DihedralGroup( IsPcGroup, 10 ) ); "PolycyclicGroup< f1,f2 |\nf1^2,\nf2^5,\nf2^f1 = f2^4\n>;\n" gap> ## fp-group gap> F2 := FreeGroup( 2 );; gap> f := F2.1;; g := F2.2;; gap> relq8 := [ f^4, g^4, f*g*f*g^-1, f^2*g^2 ];;  gap> q8 := F2/relq8;;  gap> ConvertToMagmaInputString( q8 ); no conversion function yet available for fp-groups fail gap> ## matrix group gap> M := GL(2,5);; Size(M);  480 gap> s1 := ConvertToMagmaInputString( M ); "F := GF(5);\nP := GL(2,F);\ngens := [\nP![2,0,0,1],\nP![4,1,4,0]\n];\nsub

;\n" gap> Print( s1 ); F := GF(5); P := GL(2,F); gens := [ P![2,0,0,1], P![4,1,4,0] ]; sub

; gap> n1 := [ [ Z(9)^0, Z(9)^0 ], [ Z(9)^0, Z(9) ] ];; gap> n2 := [ [ Z(9)^0, Z(9)^3 ], [ Z(9)^4, Z(9)^2 ] ];; gap> N := Group( n1, n2 );; Size( N ); 5760 gap> s2 := ConvertToMagmaInputString( N, "gpN" );; gap> Print( s2 ); F := GF(3^2); P := GL(2,F); w := PrimitiveElement(F); gens := [ P![ 1, 1, 1,w^1], P![ 1,w^3, 2,w^2] ]; gpN := sub

;  utils-0.94/doc/chap11_mj.html0000644000000000000000000002721315174515600012743 0ustar00 GAP (Utils) - Chapter 11: Various other functions

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

11 Various other functions

11.1 File operations

11.1-1 Log2HTML
‣ Log2HTML( filename )( function )

This function has been transferred from package RCWA.

This function converts the GAP logfile filename to HTML. It appears that the logfile should be in your current directory. The extension of the input file must be *.log. The name of the output file is the same as the one of the input file except that the extension *.log is replaced by *.html. There is a sample CSS file in utils/doc/gaplog.css, which you can adjust to your taste.

gap> LogTo( "triv.log" );
gap> a := 33^5;
39135393
gap> LogTo(); 
gap> Log2HTML( "triv.log" );     

11.2 LaTeX strings

11.2-1 IntOrInfinityToLaTeX
‣ IntOrInfinityToLaTeX( n )( function )

This function has been transferred from package ResClasses.

IntOrInfinityToLaTeX returns the LaTeX string for n.

gap> IntOrInfinityToLaTeX( 10^3 );
"1000"
gap> IntOrInfinityToLaTeX( infinity );
"\\infty"

11.2-2 LaTeXStringFactorsInt
‣ LaTeXStringFactorsInt( n )( function )

This function has been transferred from package RCWA.

It returns the prime factorization of the integer \(n\) as a string in LaTeX format.

gap> LaTeXStringFactorsInt( Factorial(12) );
"2^{10} \\cdot 3^5 \\cdot 5^2 \\cdot 7 \\cdot 11"

11.3 Conversion to \({\sf Magma}\) strings

11.3-1 ConvertToMagmaInputString
‣ ConvertToMagmaInputString( arg )( function )

The function ConvertToMagmaInputString( obj [, str] ) attempts to output a string s which can be read into \({\sf Magma}\) [BCP97] so as to produce the same group in that computer algebra system. In the second form the user specifies the name of the resulting object, so that the output string has the form "str := ...".

When obj is a permutation group, the operation PermGroupToMagmaFormat(obj) is called. This function has been taken from other.gi in the main library where it was called MagmaInputString.

When obj is a pc-group, the operation PcGroupToMagmaFormat(obj) is called. This function was private code of Max Horn.

When obj is a matrix group over a finite field, the operation MatrixGroupToMagmaFormat(obj) is called. This function is a modification of private code of Frank Lübeck.

Hopefully code for other types of group will be added in due course.

These functions should be considered experimental, and more testing is desirable.

gap> ## permutation groups
gap> ConvertToMagmaInputString( Group( (1,2,3,4,5), (3,4,5) ) );
"PermutationGroup<5|(1,2,3,4,5),\n(3,4,5)>;\n"
gap> ConvertToMagmaInputString( Group( (1,2,3,4,5) ), "c5" );        
"c5 := PermutationGroup<5|(1,2,3,4,5)>;\n"
gap> ## pc-group
gap> ConvertToMagmaInputString( DihedralGroup( IsPcGroup, 10 ) );
"PolycyclicGroup< f1,f2 |\nf1^2,\nf2^5,\nf2^f1 = f2^4\n>;\n"
gap> ## fp-group
gap> F2 := FreeGroup( 2 );;
gap> f := F2.1;;  g := F2.2;;
gap> relq8 := [ f^4, g^4, f*g*f*g^-1, f^2*g^2 ];; 
gap> q8 := F2/relq8;; 
gap> ConvertToMagmaInputString( q8 );
no conversion function yet available for fp-groups
fail
gap> ## matrix group
gap> M := GL(2,5);;  Size(M); 
480
gap> s1 := ConvertToMagmaInputString( M );
"F := GF(5);\nP := GL(2,F);\ngens := [\nP![2,0,0,1],\nP![4,1,4,0]\n];\nsub<P |\
 gens>;\n"
gap> Print( s1 );
F := GF(5);
P := GL(2,F);
gens := [
P![2,0,0,1],
P![4,1,4,0]
];
sub<P | gens>;
gap> n1 := [ [ Z(9)^0, Z(9)^0 ], [ Z(9)^0, Z(9) ] ];;
gap> n2 := [ [ Z(9)^0, Z(9)^3 ], [ Z(9)^4, Z(9)^2 ] ];;
gap> N := Group( n1, n2 );;  Size( N );
5760
gap> s2 := ConvertToMagmaInputString( N, "gpN" );;
gap> Print( s2 );
F := GF(3^2);
P := GL(2,F);
w := PrimitiveElement(F);
gens := [
P![ 1, 1, 1,w^1],
P![ 1,w^3, 2,w^2]
];
gpN := sub<P | gens>;
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap12.html0000644000000000000000000001735115174515600012260 0ustar00 GAP (Utils) - Chapter 12: Obsolete functions
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

12 Obsolete functions

12.1 Operations from AutoDoc

The file functions FindMatchingFiles and CreateDirIfMissing were copied from package AutoDoc where they are named AutoDoc_FindMatchingFiles and AutoDoc_CreateDirIfMissing.

The string function StringDotSuffix was also copied from package AutoDoc, where it is named AUTODOC_GetSuffix.

The function SetIfMissing was also transferred from package AutoDoc, where it is called AUTODOC_SetIfMissing. It writes into a record provided the position is not yet bound.

As from version 0.61, all these functions became obsolete in Utils, but continue to be defined in AutoDoc.

12.2 Functions for printing

The function PrintOneItemPerLine was used to prints lists vertically, rather than horizontally. Since a very similar result may be achieved using the GAP library functions Perform and Display, this function became obsolete in version 0.61.

gap> s3 := SymmetricGroup( 3 );; 
gap> L := KnownPropertiesOfObject( GeneratorsOfGroup( s3 ) );;
gap> Perform( L, Display );
IsFinite
IsSmallList
IsGeneratorsOfMagmaWithInverses
IsAssociative
IsGeneratorsOfSemigroup
IsSubsetLocallyFiniteGroup
gap> Perform( s3, Display ); 
()
(2,3)
(1,3)
(1,3,2)
(1,2,3)
(1,2)

12.3 Other obsolete functions

12.3-1 Applicable Methods

The function PrintApplicableMethod, which was included in versions from 0.41 to 0.58, has been removed since it was considered superfluous. The example shows how to print out a function.

gap> ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 1, 1 );
#I  Searching Method for IsCyclic with 1 argument:
#I  Total: 8 entries
#I  Method 5: ``IsCyclic'' at GAPROOT/lib/grp.gi:
34 , value: 36
function( G ) ... end
gap> Print( last );
function ( G )
    if Length( GeneratorsOfGroup( G ) ) = 1 then
        return true;
    else
        TryNextMethod();
    fi;
    return;
end
gap> ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 0, 3 );
function( obj ) ... end
gap> Print( last );                                               
function ( obj )
    <<compiled GAP code>> from GAPROOT/lib/oper1.g:767
end

12.3-2 ExponentOfPrime

The function ExponentOfPrime was originally transferred from package RCWA. The command ExponentOfPrime(n,p) returned the exponent of the prime p in the prime factorization of n.

Since the GAP function PValuation produces the same results, and does so more quickly, this function has been made obsolete.

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap12.txt0000644000000000000000000001024115174515600012122 0ustar00 12 Obsolete functions 12.1 Operations from AutoDoc The file functions FindMatchingFiles and CreateDirIfMissing were copied from package AutoDoc where they are named AutoDoc_FindMatchingFiles and AutoDoc_CreateDirIfMissing. The string function StringDotSuffix was also copied from package AutoDoc, where it is named AUTODOC_GetSuffix. The function SetIfMissing was also transferred from package AutoDoc, where it is called AUTODOC_SetIfMissing. It writes into a record provided the position is not yet bound. As from version 0.61, all these functions became obsolete in Utils, but continue to be defined in AutoDoc. 12.2 Functions for printing The function PrintOneItemPerLine was used to prints lists vertically, rather than horizontally. Since a very similar result may be achieved using the GAP library functions Perform and Display, this function became obsolete in version 0.61.  Example  gap> s3 := SymmetricGroup( 3 );;  gap> L := KnownPropertiesOfObject( GeneratorsOfGroup( s3 ) );; gap> Perform( L, Display ); IsFinite IsSmallList IsGeneratorsOfMagmaWithInverses IsAssociative IsGeneratorsOfSemigroup IsSubsetLocallyFiniteGroup gap> Perform( s3, Display );  () (2,3) (1,3) (1,3,2) (1,2,3) (1,2)  12.3 Other obsolete functions 12.3-1 Applicable Methods The function PrintApplicableMethod, which was included in versions from 0.41 to 0.58, has been removed since it was considered superfluous. The example shows how to print out a function.  Example  gap> ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 1, 1 ); #I Searching Method for IsCyclic with 1 argument: #I Total: 8 entries #I Method 5: ``IsCyclic'' at GAPROOT/lib/grp.gi: 34 , value: 36 function( G ) ... end gap> Print( last ); function ( G )  if Length( GeneratorsOfGroup( G ) ) = 1 then  return true;  else  TryNextMethod();  fi;  return; end gap> ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 0, 3 ); function( obj ) ... end gap> Print( last );  function ( obj )  <> from GAPROOT/lib/oper1.g:767 end  12.3-2 ExponentOfPrime The function ExponentOfPrime was originally transferred from package RCWA. The command ExponentOfPrime(n,p) returned the exponent of the prime p in the prime factorization of n. Since the GAP function PValuation produces the same results, and does so more quickly, this function has been made obsolete. utils-0.94/doc/chap12_mj.html0000644000000000000000000001776215174515600012754 0ustar00 GAP (Utils) - Chapter 12: Obsolete functions
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

12 Obsolete functions

12.1 Operations from AutoDoc

The file functions FindMatchingFiles and CreateDirIfMissing were copied from package AutoDoc where they are named AutoDoc_FindMatchingFiles and AutoDoc_CreateDirIfMissing.

The string function StringDotSuffix was also copied from package AutoDoc, where it is named AUTODOC_GetSuffix.

The function SetIfMissing was also transferred from package AutoDoc, where it is called AUTODOC_SetIfMissing. It writes into a record provided the position is not yet bound.

As from version 0.61, all these functions became obsolete in Utils, but continue to be defined in AutoDoc.

12.2 Functions for printing

The function PrintOneItemPerLine was used to prints lists vertically, rather than horizontally. Since a very similar result may be achieved using the GAP library functions Perform and Display, this function became obsolete in version 0.61.

gap> s3 := SymmetricGroup( 3 );; 
gap> L := KnownPropertiesOfObject( GeneratorsOfGroup( s3 ) );;
gap> Perform( L, Display );
IsFinite
IsSmallList
IsGeneratorsOfMagmaWithInverses
IsAssociative
IsGeneratorsOfSemigroup
IsSubsetLocallyFiniteGroup
gap> Perform( s3, Display ); 
()
(2,3)
(1,3)
(1,3,2)
(1,2,3)
(1,2)

12.3 Other obsolete functions

12.3-1 Applicable Methods

The function PrintApplicableMethod, which was included in versions from 0.41 to 0.58, has been removed since it was considered superfluous. The example shows how to print out a function.

gap> ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 1, 1 );
#I  Searching Method for IsCyclic with 1 argument:
#I  Total: 8 entries
#I  Method 5: ``IsCyclic'' at GAPROOT/lib/grp.gi:
34 , value: 36
function( G ) ... end
gap> Print( last );
function ( G )
    if Length( GeneratorsOfGroup( G ) ) = 1 then
        return true;
    else
        TryNextMethod();
    fi;
    return;
end
gap> ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 0, 3 );
function( obj ) ... end
gap> Print( last );                                               
function ( obj )
    <<compiled GAP code>> from GAPROOT/lib/oper1.g:767
end

12.3-2 ExponentOfPrime

The function ExponentOfPrime was originally transferred from package RCWA. The command ExponentOfPrime(n,p) returned the exponent of the prime p in the prime factorization of n.

Since the GAP function PValuation produces the same results, and does so more quickly, this function has been made obsolete.

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap13.html0000644000000000000000000002000015174515600012242 0ustar00 GAP (Utils) - Chapter 13: The transfer procedure
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

13 The transfer procedure

We consider here the process for transferring utility functions from a package Home to Utils which has to avoid the potential problem of duplicate declarations of a function causing loading problems in GAP.

If the functions in Home all have names of the form HOME_FunctionName then, in Utils, these functions are likely to be renamed as FunctionName or something similar. In this case the problem of duplicate declarations does not arise. This is what has happened with transfers from the AutoDoc package.

The case where the function names are unchanged is more complicated. Initially we tried out a process which allowed repeated declarations and installations of the functions being transferred. This involved additions to the main library files global.g and oper.g. Since there were misgivings about interfering in this way with basic operations such as BIND_GLOBAL, a simpler (but slightly less convenient) process has been adopted.

Using this alternative procedure, the following steps will be followed when making transfers from Home to Utils.

  1. (Home:) Offer functions for inclusion. This may be simply done by emailing a list of functions. More usefully, email the declaration, implementation, test and documentation files, e.g.: home.gd, home.gi, home.tst and home.xml. (All active authors should be involved.)

  2. (Home:) Declare that m.n is the last version of Home to contain these functions, so that m.n+1 (or similar) will be the first version of Home to have all these functions removed, and to specify Utils as a required package.

  3. (Utils:) Add strings "home" and "m.n" to the list UtilsPackageVersions in the file utils/lib/start.gd.

    UtilsPackageVersions := 
      [ "autodoc",     "2016.01.31", 
        "resclasses",  "4.2.5", 
        "home",        "m.n",
        ...,           ... 
      ];
    

    While the transfers are being made, it is essential that any new versions of Home should be tested with the latest version of Utils before they are released, so as to avoid loading failures.

  4. (Utils:) Include the function declaration and implementation sections in suitable files, enclosed within a conditional clause of the form:

    if OKtoReadFromUtils( "Home" ) then
    . . . . . . 
     <the code> 
    . . . . . . 
    fi;
    

    The function OKtoReadFromUtils returns true only if there is an installed version of Home and if this version is greater than m.n. So, at this stage, the copied code will not be read, and the transferred functions can only be called if Home has been installed.

  5. (Utils:) Add the test and documentation material to the appropriate files. The copied code can be tested by temporarily moving Home away from GAP's package directory.

  6. (Utils:) Release a new version of Utils containing all the transferred material.

  7. (Home:) Edit out the declarations and implementations of all the transferred functions, and remove references to them in the manual and tests. Possibly add a note to the manual that these functions have been transferred. Add Utils to the list of Home's required packages in PackageInfo.g. Release a new version of Home.

  8. (Utils:) In due course, when the new version(s) of Home are well established, it may be safe to remove the conditional clauses mentioned in item 4 above. The entry for Home in UtilsPackageLists may then be removed.

Finally, a note on the procedure for testing these functions. As long as a function being transferred still exists in the Home package, the code will not be read from Utils. So, when the tests are run, it is necessary to LoadPackage("home") before the function is called. The file utils/tst/testall.g makes sure that all the necessary packages are loaded before the individual tests are called.

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap13.txt0000644000000000000000000001270515174515600012132 0ustar00 13 The transfer procedure We consider here the process for transferring utility functions from a package Home to Utils which has to avoid the potential problem of duplicate declarations of a function causing loading problems in GAP. If the functions in Home all have names of the form HOME_FunctionName then, in Utils, these functions are likely to be renamed as FunctionName or something similar. In this case the problem of duplicate declarations does not arise. This is what has happened with transfers from the AutoDoc package. The case where the function names are unchanged is more complicated. Initially we tried out a process which allowed repeated declarations and installations of the functions being transferred. This involved additions to the main library files global.g and oper.g. Since there were misgivings about interfering in this way with basic operations such as BIND_GLOBAL, a simpler (but slightly less convenient) process has been adopted. Using this alternative procedure, the following steps will be followed when making transfers from Home to Utils. 1 (Home:) Offer functions for inclusion. This may be simply done by emailing a list of functions. More usefully, email the declaration, implementation, test and documentation files, e.g.: home.gd, home.gi, home.tst and home.xml. (All active authors should be involved.) 2 (Home:) Declare that m.n is the last version of Home to contain these functions, so that m.n+1 (or similar) will be the first version of Home to have all these functions removed, and to specify Utils as a required package. 3 (Utils:) Add strings "home" and "m.n" to the list UtilsPackageVersions in the file utils/lib/start.gd.   Example  UtilsPackageVersions :=   [ "autodoc", "2016.01.31",   "resclasses", "4.2.5",   "home", "m.n",  ..., ...   ];  While the transfers are being made, it is essential that any new versions of Home should be tested with the latest version of Utils before they are released, so as to avoid loading failures. 4 (Utils:) Include the function declaration and implementation sections in suitable files, enclosed within a conditional clause of the form:   Example  if OKtoReadFromUtils( "Home" ) then . . . . . .    . . . . . .  fi;  The function OKtoReadFromUtils returns true only if there is an installed version of Home and if this version is greater than m.n. So, at this stage, the copied code will not be read, and the transferred functions can only be called if Home has been installed. 5 (Utils:) Add the test and documentation material to the appropriate files. The copied code can be tested by temporarily moving Home away from GAP's package directory. 6 (Utils:) Release a new version of Utils containing all the transferred material. 7 (Home:) Edit out the declarations and implementations of all the transferred functions, and remove references to them in the manual and tests. Possibly add a note to the manual that these functions have been transferred. Add Utils to the list of Home's required packages in PackageInfo.g. Release a new version of Home. 8 (Utils:) In due course, when the new version(s) of Home are well established, it may be safe to remove the conditional clauses mentioned in item 4 above. The entry for Home in UtilsPackageLists may then be removed. Finally, a note on the procedure for testing these functions. As long as a function being transferred still exists in the Home package, the code will not be read from Utils. So, when the tests are run, it is necessary to LoadPackage("home") before the function is called. The file utils/tst/testall.g makes sure that all the necessary packages are loaded before the individual tests are called. utils-0.94/doc/chap13_mj.html0000644000000000000000000002037215174515600012744 0ustar00 GAP (Utils) - Chapter 13: The transfer procedure
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

13 The transfer procedure

We consider here the process for transferring utility functions from a package Home to Utils which has to avoid the potential problem of duplicate declarations of a function causing loading problems in GAP.

If the functions in Home all have names of the form HOME_FunctionName then, in Utils, these functions are likely to be renamed as FunctionName or something similar. In this case the problem of duplicate declarations does not arise. This is what has happened with transfers from the AutoDoc package.

The case where the function names are unchanged is more complicated. Initially we tried out a process which allowed repeated declarations and installations of the functions being transferred. This involved additions to the main library files global.g and oper.g. Since there were misgivings about interfering in this way with basic operations such as BIND_GLOBAL, a simpler (but slightly less convenient) process has been adopted.

Using this alternative procedure, the following steps will be followed when making transfers from Home to Utils.

  1. (Home:) Offer functions for inclusion. This may be simply done by emailing a list of functions. More usefully, email the declaration, implementation, test and documentation files, e.g.: home.gd, home.gi, home.tst and home.xml. (All active authors should be involved.)

  2. (Home:) Declare that m.n is the last version of Home to contain these functions, so that m.n+1 (or similar) will be the first version of Home to have all these functions removed, and to specify Utils as a required package.

  3. (Utils:) Add strings "home" and "m.n" to the list UtilsPackageVersions in the file utils/lib/start.gd.

    UtilsPackageVersions := 
      [ "autodoc",     "2016.01.31", 
        "resclasses",  "4.2.5", 
        "home",        "m.n",
        ...,           ... 
      ];
    

    While the transfers are being made, it is essential that any new versions of Home should be tested with the latest version of Utils before they are released, so as to avoid loading failures.

  4. (Utils:) Include the function declaration and implementation sections in suitable files, enclosed within a conditional clause of the form:

    if OKtoReadFromUtils( "Home" ) then
    . . . . . . 
     <the code> 
    . . . . . . 
    fi;
    

    The function OKtoReadFromUtils returns true only if there is an installed version of Home and if this version is greater than m.n. So, at this stage, the copied code will not be read, and the transferred functions can only be called if Home has been installed.

  5. (Utils:) Add the test and documentation material to the appropriate files. The copied code can be tested by temporarily moving Home away from GAP's package directory.

  6. (Utils:) Release a new version of Utils containing all the transferred material.

  7. (Home:) Edit out the declarations and implementations of all the transferred functions, and remove references to them in the manual and tests. Possibly add a note to the manual that these functions have been transferred. Add Utils to the list of Home's required packages in PackageInfo.g. Release a new version of Home.

  8. (Utils:) In due course, when the new version(s) of Home are well established, it may be safe to remove the conditional clauses mentioned in item 4 above. The entry for Home in UtilsPackageLists may then be removed.

Finally, a note on the procedure for testing these functions. As long as a function being transferred still exists in the Home package, the code will not be read from Utils. So, when the tests are run, it is necessary to LoadPackage("home") before the function is called. The file utils/tst/testall.g makes sure that all the necessary packages are loaded before the individual tests are called.

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap1_mj.html0000644000000000000000000002146015174515600012660 0ustar00 GAP (Utils) - Chapter 1: Introduction
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

1 Introduction

The Utils package provides a space for utility functions from a variety of GAP packages to be collected together into a single package. In this way it is hoped that they will become more visible to other package authors. This package was first distributed as part of the GAP 4.8.2 distribution.

The package is loaded with the command

gap> LoadPackage( "utils" );
true

Functions have been transferred from the following packages:

  • Conversion of a GAP group to a \({\sf Magma}\) output string, taken from various sources including other.gi in the main library.

Transfer is complete (for now) for functions from the following packages:

The package may be obtained either as a compressed .tar file or as a .zip file, utils-version_number.tar.gz, by ftp from one of the following sites:

The package also has a GitHub repository at: https://github.com/gap-packages/utils.

Once the package is loaded, the manual doc/manual.pdf can be found in the documentation folder. The html versions, with or without \({\sf MathJax}\), may be rebuilt as follows:

gap> ReadPackage( "utils", "makedoc.g" ); 

It is possible to check that the package has been installed correctly by running the test files (which terminates the GAP session):

gap> ReadPackage( "utils", "tst/testall.g" );
Architecture: . . . . . 
testing: . . . . . 
. . . 
#I  No errors detected while testing

Note that functions listed in this manual that are currently in the process of being transferred are only read from the source package Home (say), and so can only be used if Home has already been loaded. There are no such functions in transition at present.

1.1 Information for package authors

A function (or collection of functions) is suitable for transfer from a package Home to Utils if the following conditions are satisfied.

  • The function is sufficiently non-specialised so that it might be of use to other authors.

  • The function does not depend on the remaining functions in Home

  • The function does not do what can already be done with a GAP library function.

  • Documentation of the function and test examples are available.

  • When there is more than one active author of Home, they should all be aware (and content) that the transfer is taking place.

Authors of packages may be reluctant to let go of their utility functions. The following principles may help to reassure them. (Suggestions for more items here are welcome.)

  • A function that has been transferred to Utils will not be changed without the approval of the original author.

  • The current package maintainer has every intention of continuing to maintain Utils. In the event that this proves impossible, the GAP development team will surely find someone to take over.

  • Function names will not be changed unless specifically requested by Home's author(s) or unless they have the form HOME_FunctionName.

  • In order to speed up the transfer process, only functions from one package will be in transition at any given time. Hopefully a week or two will suffice for most packages.

  • Any package author who transfers a function to Utils will become an author of Utils. (In truth, Utils does not have authors, just a large number of contributors.)

The process for transferring utility functions from Home to Utils is described in Chapter 13.

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap2.html0000644000000000000000000001333015174515600012170 0ustar00 GAP (Utils) - Chapter 2: Printing Lists and Iterators
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

2 Printing Lists and Iterators

2.1 Printing selected items

The functions described here print lists or objects with an iterator with one item per line, either the whole list/iterator or certain subsets:

  • by giving a list of positions of items to be printed, or

  • by specifying a first item and then a regular step.

2.1-1 PrintSelection
‣ PrintSelection( obj, list )( function )
‣ PrintSelection( obj, first, step[, last] )( function )

This function, given three (or four) parameters, calls operations PrintSelectionFromList or PrintSelectionFromIterator which prints the first item specified, and then the item at every step. The fourth parameter is essential when the object being printed is infinite.

Alternatively, given two parameters, with the second parameter a list L of positive integers, only the items at positions in L are printed.

gap> L := List( [1..20], n -> n^5 );;
gap> PrintSelection( L, [18..20] );
18 : 1889568
19 : 2476099
20 : 3200000
gap> PrintSelection( L, 2, 9 );       
2 : 32
11 : 161051
20 : 3200000
gap> PrintSelection( L, 2, 3, 11 );
2 : 32
5 : 3125
8 : 32768
11 : 161051
gap> s5 := SymmetricGroup( 5 );;
gap> PrintSelection( s5, [30,31,100,101] );
30 : (1,5)(3,4)
31 : (1,5,2)
100 : (1,4,3)
101 : (1,4)(3,5)
gap> PrintSelection( s5, 1, 30 );
1 : ()
31 : (1,5,2)
61 : (1,2,3)
91 : (1,3,5,2,4)
gap> PrintSelection( s5, 9, 11, 43 );
9 : (2,5,3)
20 : (2,4)
31 : (1,5,2)
42 : (1,5,2,3,4)
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap2.txt0000644000000000000000000000527215174515600012051 0ustar00 2 Printing Lists and Iterators 2.1 Printing selected items The functions described here print lists or objects with an iterator with one item per line, either the whole list/iterator or certain subsets:  by giving a list of positions of items to be printed, or  by specifying a first item and then a regular step. 2.1-1 PrintSelection PrintSelection( obj, list )  function PrintSelection( obj, first, step[, last] )  function This function, given three (or four) parameters, calls operations PrintSelectionFromList or PrintSelectionFromIterator which prints the first item specified, and then the item at every step. The fourth parameter is essential when the object being printed is infinite. Alternatively, given two parameters, with the second parameter a list L of positive integers, only the items at positions in L are printed.  Example  gap> L := List( [1..20], n -> n^5 );; gap> PrintSelection( L, [18..20] ); 18 : 1889568 19 : 2476099 20 : 3200000 gap> PrintSelection( L, 2, 9 );  2 : 32 11 : 161051 20 : 3200000 gap> PrintSelection( L, 2, 3, 11 ); 2 : 32 5 : 3125 8 : 32768 11 : 161051 gap> s5 := SymmetricGroup( 5 );; gap> PrintSelection( s5, [30,31,100,101] ); 30 : (1,5)(3,4) 31 : (1,5,2) 100 : (1,4,3) 101 : (1,4)(3,5) gap> PrintSelection( s5, 1, 30 ); 1 : () 31 : (1,5,2) 61 : (1,2,3) 91 : (1,3,5,2,4) gap> PrintSelection( s5, 9, 11, 43 ); 9 : (2,5,3) 20 : (2,4) 31 : (1,5,2) 42 : (1,5,2,3,4)  utils-0.94/doc/chap2_mj.html0000644000000000000000000001373015174515600012662 0ustar00 GAP (Utils) - Chapter 2: Printing Lists and Iterators
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

2 Printing Lists and Iterators

2.1 Printing selected items

The functions described here print lists or objects with an iterator with one item per line, either the whole list/iterator or certain subsets:

  • by giving a list of positions of items to be printed, or

  • by specifying a first item and then a regular step.

2.1-1 PrintSelection
‣ PrintSelection( obj, list )( function )
‣ PrintSelection( obj, first, step[, last] )( function )

This function, given three (or four) parameters, calls operations PrintSelectionFromList or PrintSelectionFromIterator which prints the first item specified, and then the item at every step. The fourth parameter is essential when the object being printed is infinite.

Alternatively, given two parameters, with the second parameter a list L of positive integers, only the items at positions in L are printed.

gap> L := List( [1..20], n -> n^5 );;
gap> PrintSelection( L, [18..20] );
18 : 1889568
19 : 2476099
20 : 3200000
gap> PrintSelection( L, 2, 9 );       
2 : 32
11 : 161051
20 : 3200000
gap> PrintSelection( L, 2, 3, 11 );
2 : 32
5 : 3125
8 : 32768
11 : 161051
gap> s5 := SymmetricGroup( 5 );;
gap> PrintSelection( s5, [30,31,100,101] );
30 : (1,5)(3,4)
31 : (1,5,2)
100 : (1,4,3)
101 : (1,4)(3,5)
gap> PrintSelection( s5, 1, 30 );
1 : ()
31 : (1,5,2)
61 : (1,2,3)
91 : (1,3,5,2,4)
gap> PrintSelection( s5, 9, 11, 43 );
9 : (2,5,3)
20 : (2,4)
31 : (1,5,2)
42 : (1,5,2,3,4)
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap3.html0000644000000000000000000004031415174515600012173 0ustar00 GAP (Utils) - Chapter 3: Lists, Sets and Strings
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

3 Lists, Sets and Strings

3.1 Functions for lists

3.1-1 DifferencesList
‣ DifferencesList( L )( function )

This function has been transferred from package ResClasses.

It takes a list L of length n and outputs the list of length n-1 containing all the differences L[i]-L[i-1].

gap> List( [1..12], n->n^3 );
[ 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728 ]
gap> DifferencesList( last );
[ 7, 19, 37, 61, 91, 127, 169, 217, 271, 331, 397 ]
gap> DifferencesList( last );
[ 12, 18, 24, 30, 36, 42, 48, 54, 60, 66 ]
gap> DifferencesList( last );
[ 6, 6, 6, 6, 6, 6, 6, 6, 6 ]

3.1-2 QuotientsList
‣ QuotientsList( L )( function )
‣ FloatQuotientsList( L )( function )

These functions have been transferred from package ResClasses.

They take a list L of length n and output the quotients L[i]/L[i-1] of consecutive entries in L. An error is returned if an entry is zero.

gap> List( [0..10], n -> Factorial(n) );
[ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 ]
gap> QuotientsList( last );
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
gap> L := [ 1, 3, 5, -1, -3, -5 ];;
gap> QuotientsList( L );
[ 3, 5/3, -1/5, 3, 5/3 ]
gap> FloatQuotientsList( L );
[ 3., 1.66667, -0.2, 3., 1.66667 ]
gap> QuotientsList( [ 2, 1, 0, -1, -2 ] );
[ 1/2, 0, fail, 2 ]
gap> FloatQuotientsList( [1..10] );
[ 2., 1.5, 1.33333, 1.25, 1.2, 1.16667, 1.14286, 1.125, 1.11111 ]
gap> Product( last );
10. 

3.1-3 SearchCycle
‣ SearchCycle( L )( operation )

This function has been transferred from package RCWA.

SearchCycle is a tool to find likely cycles in lists. What, precisely, a cycle is, is deliberately fuzzy here, and may possibly even change. The idea is that the beginning of the list may be anything, following that the same pattern needs to be repeated several times in order to be recognized as a cycle.

gap> L := [1..20];;  L[1]:=13;;                                              
gap> for i in [1..19] do                                                     
>        if IsOddInt(L[i]) then L[i+1]:=3*L[i]+1; else L[i+1]:=L[i]/2; fi;
>    od;                                                                  
gap> L;                                                                      
[ 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4 ]
gap> SearchCycle( L );                                                       
[ 1, 4, 2 ]
gap> n := 1;;  L := [n];;
gap> for i in [1..100] do  n:=(n^2+1) mod 1093;  Add(L,n);  od;
gap> L; 
[ 1, 2, 5, 26, 677, 363, 610, 481, 739, 715, 795, 272, 754, 157, 604, 848, 
  1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 
  211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 
  378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 
  754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 
  848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 
  271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004 ]
gap> C := SearchCycle( L );
[ 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754 ]
gap> P := Positions( L, 157 );
[ 14, 26, 38, 50, 62, 74, 86, 98 ]
gap> Length( C );  DifferencesList( P );
12
[ 12, 12, 12, 12, 12, 12, 12 ]

3.1-4 RandomCombination
‣ RandomCombination( S, k )( operation )

This function has been transferred from package ResClasses.

It returns a random unordered k-tuple of distinct elements of a set S.

gap> ## "6 aus 49" is a common lottery in Germany
gap> RandomCombination( [1..49], 6 ); 
[ 2, 16, 24, 26, 37, 47 ]

3.2 Distinct and Common Representatives

3.2-1 DistinctRepresentatives
‣ DistinctRepresentatives( list )( operation )
‣ CommonRepresentatives( list )( operation )
‣ CommonTransversal( grp, subgrp )( operation )
‣ IsCommonTransversal( grp, subgrp, list )( operation )

These operations have been transferred from package XMod.

They deal with lists of subsets of [1 ... n] and construct systems of distinct and common representatives using simple, non-recursive, combinatorial algorithms.

When L is a set of n subsets of [1 ... n] and the Hall condition is satisfied (the union of any k subsets has at least k elements), a set of DistinctRepresentatives exists.

When J,K are both lists of n sets, the operation CommonRepresentatives returns two lists: the set of representatives, and a permutation of the subsets of the second list.

The operation CommonTransversal may be used to provide a common transversal for the sets of left and right cosets of a subgroup H of a group G, although a greedy algorithm is usually quicker.

gap> J := [ [1,2,3], [3,4], [3,4], [1,2,4] ];;
gap> DistinctRepresentatives( J );
[ 1, 3, 4, 2 ]
gap> K := [ [3,4], [1,2], [2,3], [2,3,4] ];;
gap> CommonRepresentatives( J, K );
[ [ 3, 3, 3, 1 ], [ 1, 3, 4, 2 ] ]
gap> d16 := DihedralGroup( IsPermGroup, 16 ); 
Group([ (1,2,3,4,5,6,7,8), (2,8)(3,7)(4,6) ])
gap> SetName( d16, "d16" );
gap> c4 := Subgroup( d16, [ d16.1^2 ] ); 
Group([ (1,3,5,7)(2,4,6,8) ])
gap> SetName( c4, "c4" );
gap> RightCosets( d16, c4 );
[ RightCoset(c4,()), RightCoset(c4,(2,8)(3,7)(4,6)), RightCoset(c4,(1,8,7,6,5,
   4,3,2)), RightCoset(c4,(1,8)(2,7)(3,6)(4,5)) ]
gap> trans := CommonTransversal( d16, c4 );
[ (), (2,8)(3,7)(4,6), (1,2,3,4,5,6,7,8), (1,2)(3,8)(4,7)(5,6) ]
gap> IsCommonTransversal( d16, c4, trans );
true

3.3 Functions for strings

3.3-1 BlankFreeString
‣ BlankFreeString( obj )( function )

This function has been transferred from package ResClasses.

The result of BlankFreeString( obj ); is a composite of the functions String( obj ) and RemoveCharacters( obj, " " );.

gap> gens := GeneratorsOfGroup( DihedralGroup(12) );
[ f1, f2, f3 ]
gap> String( gens );                                
"[ f1, f2, f3 ]"
gap> BlankFreeString( gens );                       
"[f1,f2,f3]"
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap3.txt0000644000000000000000000002332615174515600012052 0ustar00 3 Lists, Sets and Strings 3.1 Functions for lists 3.1-1 DifferencesList DifferencesList( L )  function This function has been transferred from package ResClasses. It takes a list L of length n and outputs the list of length n-1 containing all the differences L[i]-L[i-1].  Example  gap> List( [1..12], n->n^3 ); [ 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728 ] gap> DifferencesList( last ); [ 7, 19, 37, 61, 91, 127, 169, 217, 271, 331, 397 ] gap> DifferencesList( last ); [ 12, 18, 24, 30, 36, 42, 48, 54, 60, 66 ] gap> DifferencesList( last ); [ 6, 6, 6, 6, 6, 6, 6, 6, 6 ]  3.1-2 QuotientsList QuotientsList( L )  function FloatQuotientsList( L )  function These functions have been transferred from package ResClasses. They take a list L of length n and output the quotients L[i]/L[i-1] of consecutive entries in L. An error is returned if an entry is zero.  Example  gap> List( [0..10], n -> Factorial(n) ); [ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 ] gap> QuotientsList( last ); [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] gap> L := [ 1, 3, 5, -1, -3, -5 ];; gap> QuotientsList( L ); [ 3, 5/3, -1/5, 3, 5/3 ] gap> FloatQuotientsList( L ); [ 3., 1.66667, -0.2, 3., 1.66667 ] gap> QuotientsList( [ 2, 1, 0, -1, -2 ] ); [ 1/2, 0, fail, 2 ] gap> FloatQuotientsList( [1..10] ); [ 2., 1.5, 1.33333, 1.25, 1.2, 1.16667, 1.14286, 1.125, 1.11111 ] gap> Product( last ); 10.   3.1-3 SearchCycle SearchCycle( L )  operation This function has been transferred from package RCWA. SearchCycle is a tool to find likely cycles in lists. What, precisely, a cycle is, is deliberately fuzzy here, and may possibly even change. The idea is that the beginning of the list may be anything, following that the same pattern needs to be repeated several times in order to be recognized as a cycle.  Example  gap> L := [1..20];; L[1]:=13;;  gap> for i in [1..19] do  >  if IsOddInt(L[i]) then L[i+1]:=3*L[i]+1; else L[i+1]:=L[i]/2; fi; >  od;  gap> L;  [ 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4 ] gap> SearchCycle( L );  [ 1, 4, 2 ] gap> n := 1;; L := [n];; gap> for i in [1..100] do n:=(n^2+1) mod 1093; Add(L,n); od; gap> L;  [ 1, 2, 5, 26, 677, 363, 610, 481, 739, 715, 795, 272, 754, 157, 604, 848,   1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271,   211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521,   378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272,   754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604,   848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004,   271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004 ] gap> C := SearchCycle( L ); [ 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754 ] gap> P := Positions( L, 157 ); [ 14, 26, 38, 50, 62, 74, 86, 98 ] gap> Length( C ); DifferencesList( P ); 12 [ 12, 12, 12, 12, 12, 12, 12 ]  3.1-4 RandomCombination RandomCombination( S, k )  operation This function has been transferred from package ResClasses. It returns a random unordered k-tuple of distinct elements of a set S.  Example  gap> ## "6 aus 49" is a common lottery in Germany gap> RandomCombination( [1..49], 6 );  [ 2, 16, 24, 26, 37, 47 ]  3.2 Distinct and Common Representatives 3.2-1 DistinctRepresentatives DistinctRepresentatives( list )  operation CommonRepresentatives( list )  operation CommonTransversal( grp, subgrp )  operation IsCommonTransversal( grp, subgrp, list )  operation These operations have been transferred from package XMod. They deal with lists of subsets of [1 ... n] and construct systems of distinct and common representatives using simple, non-recursive, combinatorial algorithms. When L is a set of n subsets of [1 ... n] and the Hall condition is satisfied (the union of any k subsets has at least k elements), a set of DistinctRepresentatives exists. When J,K are both lists of n sets, the operation CommonRepresentatives returns two lists: the set of representatives, and a permutation of the subsets of the second list. The operation CommonTransversal may be used to provide a common transversal for the sets of left and right cosets of a subgroup H of a group G, although a greedy algorithm is usually quicker.  Example  gap> J := [ [1,2,3], [3,4], [3,4], [1,2,4] ];; gap> DistinctRepresentatives( J ); [ 1, 3, 4, 2 ] gap> K := [ [3,4], [1,2], [2,3], [2,3,4] ];; gap> CommonRepresentatives( J, K ); [ [ 3, 3, 3, 1 ], [ 1, 3, 4, 2 ] ] gap> d16 := DihedralGroup( IsPermGroup, 16 );  Group([ (1,2,3,4,5,6,7,8), (2,8)(3,7)(4,6) ]) gap> SetName( d16, "d16" ); gap> c4 := Subgroup( d16, [ d16.1^2 ] );  Group([ (1,3,5,7)(2,4,6,8) ]) gap> SetName( c4, "c4" ); gap> RightCosets( d16, c4 ); [ RightCoset(c4,()), RightCoset(c4,(2,8)(3,7)(4,6)), RightCoset(c4,(1,8,7,6,5,  4,3,2)), RightCoset(c4,(1,8)(2,7)(3,6)(4,5)) ] gap> trans := CommonTransversal( d16, c4 ); [ (), (2,8)(3,7)(4,6), (1,2,3,4,5,6,7,8), (1,2)(3,8)(4,7)(5,6) ] gap> IsCommonTransversal( d16, c4, trans ); true  3.3 Functions for strings 3.3-1 BlankFreeString BlankFreeString( obj )  function This function has been transferred from package ResClasses. The result of BlankFreeString( obj ); is a composite of the functions String( obj ) and RemoveCharacters( obj, " " );.  Example  gap> gens := GeneratorsOfGroup( DihedralGroup(12) ); [ f1, f2, f3 ] gap> String( gens );  "[ f1, f2, f3 ]" gap> BlankFreeString( gens );  "[f1,f2,f3]"  utils-0.94/doc/chap3_mj.html0000644000000000000000000004106715174515600012667 0ustar00 GAP (Utils) - Chapter 3: Lists, Sets and Strings
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

3 Lists, Sets and Strings

3.1 Functions for lists

3.1-1 DifferencesList
‣ DifferencesList( L )( function )

This function has been transferred from package ResClasses.

It takes a list \(L\) of length \(n\) and outputs the list of length \(n-1\) containing all the differences \(L[i]-L[i-1]\).

gap> List( [1..12], n->n^3 );
[ 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728 ]
gap> DifferencesList( last );
[ 7, 19, 37, 61, 91, 127, 169, 217, 271, 331, 397 ]
gap> DifferencesList( last );
[ 12, 18, 24, 30, 36, 42, 48, 54, 60, 66 ]
gap> DifferencesList( last );
[ 6, 6, 6, 6, 6, 6, 6, 6, 6 ]

3.1-2 QuotientsList
‣ QuotientsList( L )( function )
‣ FloatQuotientsList( L )( function )

These functions have been transferred from package ResClasses.

They take a list \(L\) of length \(n\) and output the quotients \(L[i]/L[i-1]\) of consecutive entries in \(L\). An error is returned if an entry is zero.

gap> List( [0..10], n -> Factorial(n) );
[ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 ]
gap> QuotientsList( last );
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
gap> L := [ 1, 3, 5, -1, -3, -5 ];;
gap> QuotientsList( L );
[ 3, 5/3, -1/5, 3, 5/3 ]
gap> FloatQuotientsList( L );
[ 3., 1.66667, -0.2, 3., 1.66667 ]
gap> QuotientsList( [ 2, 1, 0, -1, -2 ] );
[ 1/2, 0, fail, 2 ]
gap> FloatQuotientsList( [1..10] );
[ 2., 1.5, 1.33333, 1.25, 1.2, 1.16667, 1.14286, 1.125, 1.11111 ]
gap> Product( last );
10. 

3.1-3 SearchCycle
‣ SearchCycle( L )( operation )

This function has been transferred from package RCWA.

SearchCycle is a tool to find likely cycles in lists. What, precisely, a cycle is, is deliberately fuzzy here, and may possibly even change. The idea is that the beginning of the list may be anything, following that the same pattern needs to be repeated several times in order to be recognized as a cycle.

gap> L := [1..20];;  L[1]:=13;;                                              
gap> for i in [1..19] do                                                     
>        if IsOddInt(L[i]) then L[i+1]:=3*L[i]+1; else L[i+1]:=L[i]/2; fi;
>    od;                                                                  
gap> L;                                                                      
[ 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4 ]
gap> SearchCycle( L );                                                       
[ 1, 4, 2 ]
gap> n := 1;;  L := [n];;
gap> for i in [1..100] do  n:=(n^2+1) mod 1093;  Add(L,n);  od;
gap> L; 
[ 1, 2, 5, 26, 677, 363, 610, 481, 739, 715, 795, 272, 754, 157, 604, 848, 
  1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 
  211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 
  378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 
  754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 
  848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 
  271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004 ]
gap> C := SearchCycle( L );
[ 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754 ]
gap> P := Positions( L, 157 );
[ 14, 26, 38, 50, 62, 74, 86, 98 ]
gap> Length( C );  DifferencesList( P );
12
[ 12, 12, 12, 12, 12, 12, 12 ]

3.1-4 RandomCombination
‣ RandomCombination( S, k )( operation )

This function has been transferred from package ResClasses.

It returns a random unordered \(k\)-tuple of distinct elements of a set \(S\).

gap> ## "6 aus 49" is a common lottery in Germany
gap> RandomCombination( [1..49], 6 ); 
[ 2, 16, 24, 26, 37, 47 ]

3.2 Distinct and Common Representatives

3.2-1 DistinctRepresentatives
‣ DistinctRepresentatives( list )( operation )
‣ CommonRepresentatives( list )( operation )
‣ CommonTransversal( grp, subgrp )( operation )
‣ IsCommonTransversal( grp, subgrp, list )( operation )

These operations have been transferred from package XMod.

They deal with lists of subsets of \([1 \ldots n]\) and construct systems of distinct and common representatives using simple, non-recursive, combinatorial algorithms.

When \(L\) is a set of \(n\) subsets of \([1 \ldots n]\) and the Hall condition is satisfied (the union of any \(k\) subsets has at least \(k\) elements), a set of DistinctRepresentatives exists.

When \(J,K\) are both lists of \(n\) sets, the operation CommonRepresentatives returns two lists: the set of representatives, and a permutation of the subsets of the second list.

The operation CommonTransversal may be used to provide a common transversal for the sets of left and right cosets of a subgroup \(H\) of a group \(G\), although a greedy algorithm is usually quicker.

gap> J := [ [1,2,3], [3,4], [3,4], [1,2,4] ];;
gap> DistinctRepresentatives( J );
[ 1, 3, 4, 2 ]
gap> K := [ [3,4], [1,2], [2,3], [2,3,4] ];;
gap> CommonRepresentatives( J, K );
[ [ 3, 3, 3, 1 ], [ 1, 3, 4, 2 ] ]
gap> d16 := DihedralGroup( IsPermGroup, 16 ); 
Group([ (1,2,3,4,5,6,7,8), (2,8)(3,7)(4,6) ])
gap> SetName( d16, "d16" );
gap> c4 := Subgroup( d16, [ d16.1^2 ] ); 
Group([ (1,3,5,7)(2,4,6,8) ])
gap> SetName( c4, "c4" );
gap> RightCosets( d16, c4 );
[ RightCoset(c4,()), RightCoset(c4,(2,8)(3,7)(4,6)), RightCoset(c4,(1,8,7,6,5,
   4,3,2)), RightCoset(c4,(1,8)(2,7)(3,6)(4,5)) ]
gap> trans := CommonTransversal( d16, c4 );
[ (), (2,8)(3,7)(4,6), (1,2,3,4,5,6,7,8), (1,2)(3,8)(4,7)(5,6) ]
gap> IsCommonTransversal( d16, c4, trans );
true

3.3 Functions for strings

3.3-1 BlankFreeString
‣ BlankFreeString( obj )( function )

This function has been transferred from package ResClasses.

The result of BlankFreeString( obj ); is a composite of the functions String( obj ) and RemoveCharacters( obj, " " );.

gap> gens := GeneratorsOfGroup( DihedralGroup(12) );
[ f1, f2, f3 ]
gap> String( gens );                                
"[ f1, f2, f3 ]"
gap> BlankFreeString( gens );                       
"[f1,f2,f3]"
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap4.html0000644000000000000000000003001015174515600012164 0ustar00 GAP (Utils) - Chapter 4: Number-theoretic functions
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

4 Number-theoretic functions

4.1 Functions for integers

4.1-1 AllSmoothIntegers
‣ AllSmoothIntegers( maxp, maxn )( function )
‣ AllSmoothIntegers( L, maxp )( function )

This function has been transferred from package RCWA.

The function AllSmoothIntegers(maxp,maxn) returns the list of all positive integers less than or equal to maxn whose prime factors are all in the list L = {p ~|~ p leqslant maxp, p~mboxprime }.

In the alternative form, when L is a list of primes, the function returns the list of all positive integers whose prime factors lie in L.

gap> AllSmoothIntegers( 3, 1000 );
[ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96, 
  108, 128, 144, 162, 192, 216, 243, 256, 288, 324, 384, 432, 486, 512, 576, 
  648, 729, 768, 864, 972 ]
gap> AllSmoothIntegers( [5,11,17], 1000 );
[ 1, 5, 11, 17, 25, 55, 85, 121, 125, 187, 275, 289, 425, 605, 625, 935 ]
gap> Length( last );
16
gap> List( [3..20], n -> Length( AllSmoothIntegers( [5,11,17], 10^n ) ) );
[ 16, 29, 50, 78, 114, 155, 212, 282, 359, 452, 565, 691, 831, 992, 1173, 
  1374, 1595, 1843 ]

4.1-2 AllProducts
‣ AllProducts( L, k )( function )

This function has been transferred from package RCWA.

The command AllProducts(L,k) returns the list of all products of k entries of the list L. Note that every ordering of the entries is used so that, in the commuting case, there are bound to be repetitions.

gap> AllProducts([1..4],3); 
[ 1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16, 2, 4, 6, 8, 4, 8, 12, 
  16, 6, 12, 18, 24, 8, 16, 24, 32, 3, 6, 9, 12, 6, 12, 18, 24, 9, 18, 27, 
  36, 12, 24, 36, 48, 4, 8, 12, 16, 8, 16, 24, 32, 12, 24, 36, 48, 16, 32, 
  48, 64 ]
gap> Set(last);            
[ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 64 ]
gap> AllProducts( [(1,2,3),(2,3,4)], 2 );
[ (2,4,3), (1,2)(3,4), (1,3)(2,4), (1,3,2) ]

4.1-3 RestrictedPartitionsWithoutRepetitions
‣ RestrictedPartitionsWithoutRepetitions( n, S )( function )

This function has been transferred from package RCWA.

For a positive integer n and a set of positive integers S, this function returns the list of partitions of n into distinct elements of S. Unlike RestrictedPartitions, no repetitions are allowed.

gap> RestrictedPartitions( 20, [4..10] );
[ [ 4, 4, 4, 4, 4 ], [ 5, 5, 5, 5 ], [ 6, 5, 5, 4 ], [ 6, 6, 4, 4 ], 
  [ 7, 5, 4, 4 ], [ 7, 7, 6 ], [ 8, 4, 4, 4 ], [ 8, 6, 6 ], [ 8, 7, 5 ], 
  [ 8, 8, 4 ], [ 9, 6, 5 ], [ 9, 7, 4 ], [ 10, 5, 5 ], [ 10, 6, 4 ], 
  [ 10, 10 ] ]
gap> RestrictedPartitionsWithoutRepetitions( 20, [4..10] );
[ [ 10, 6, 4 ], [ 9, 7, 4 ], [ 9, 6, 5 ], [ 8, 7, 5 ] ]
gap> RestrictedPartitionsWithoutRepetitions( 10^2, List([1..10], n->n^2 ) );
[ [ 100 ], [ 64, 36 ], [ 49, 25, 16, 9, 1 ] ]

4.1-4 NextProbablyPrimeInt
‣ NextProbablyPrimeInt( n )( function )

This function has been transferred from package RCWA.

The function NextProbablyPrimeInt(n) does the same as NextPrimeInt(n) except that for reasons of performance it tests numbers only for IsProbablyPrimeInt(n) instead of IsPrimeInt(n). For large n, this function is much faster than NextPrimeInt(n)

gap> n := 2^251;
3618502788666131106986593281521497120414687020801267626233049500247285301248
gap> NextProbablyPrimeInt( n );
3618502788666131106986593281521497120414687020801267626233049500247285301313
gap> NextPrimeInt( n );  # same result, just faster
3618502788666131106986593281521497120414687020801267626233049500247285301313

4.1-5 PrimeNumbersIterator
‣ PrimeNumbersIterator( [chunksize] )( function )

This function has been transferred from package RCWA.

This function returns an iterator which runs over the prime numbers in ascending order; it takes an optional argument chunksize which specifies the length of the interval which is sieved in one go (the default is 10^7), and which can be used to balance runtime vs. memory consumption. It is assumed that chunksize is larger than any gap between two consecutive primes within the range one intends to run the iterator over.

gap> iter := PrimeNumbersIterator();;
gap> for i in [1..100] do  p := NextIterator(iter);  od;
gap> p;
541
gap> sum := 0;;
gap> ## "prime number race" 1 vs. 3 mod 4
gap> for p in PrimeNumbersIterator() do 
>       if p <> 2 then sum := sum + E(4)^(p-1); fi;
>       if sum > 0 then break; fi;
>    od;
gap> p;
26861
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap4.txt0000644000000000000000000001603415174515600012051 0ustar00 4 Number-theoretic functions 4.1 Functions for integers 4.1-1 AllSmoothIntegers AllSmoothIntegers( maxp, maxn )  function AllSmoothIntegers( L, maxp )  function This function has been transferred from package RCWA. The function AllSmoothIntegers(maxp,maxn) returns the list of all positive integers less than or equal to maxn whose prime factors are all in the list L = {p ~|~ p leqslant maxp, p~mboxprime }. In the alternative form, when L is a list of primes, the function returns the list of all positive integers whose prime factors lie in L.  Example  gap> AllSmoothIntegers( 3, 1000 ); [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96,   108, 128, 144, 162, 192, 216, 243, 256, 288, 324, 384, 432, 486, 512, 576,   648, 729, 768, 864, 972 ] gap> AllSmoothIntegers( [5,11,17], 1000 ); [ 1, 5, 11, 17, 25, 55, 85, 121, 125, 187, 275, 289, 425, 605, 625, 935 ] gap> Length( last ); 16 gap> List( [3..20], n -> Length( AllSmoothIntegers( [5,11,17], 10^n ) ) ); [ 16, 29, 50, 78, 114, 155, 212, 282, 359, 452, 565, 691, 831, 992, 1173,   1374, 1595, 1843 ]  4.1-2 AllProducts AllProducts( L, k )  function This function has been transferred from package RCWA. The command AllProducts(L,k) returns the list of all products of k entries of the list L. Note that every ordering of the entries is used so that, in the commuting case, there are bound to be repetitions.  Example  gap> AllProducts([1..4],3);  [ 1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16, 2, 4, 6, 8, 4, 8, 12,   16, 6, 12, 18, 24, 8, 16, 24, 32, 3, 6, 9, 12, 6, 12, 18, 24, 9, 18, 27,   36, 12, 24, 36, 48, 4, 8, 12, 16, 8, 16, 24, 32, 12, 24, 36, 48, 16, 32,   48, 64 ] gap> Set(last);  [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 64 ] gap> AllProducts( [(1,2,3),(2,3,4)], 2 ); [ (2,4,3), (1,2)(3,4), (1,3)(2,4), (1,3,2) ]  4.1-3 RestrictedPartitionsWithoutRepetitions RestrictedPartitionsWithoutRepetitions( n, S )  function This function has been transferred from package RCWA. For a positive integer n and a set of positive integers S, this function returns the list of partitions of n into distinct elements of S. Unlike RestrictedPartitions, no repetitions are allowed.  Example  gap> RestrictedPartitions( 20, [4..10] ); [ [ 4, 4, 4, 4, 4 ], [ 5, 5, 5, 5 ], [ 6, 5, 5, 4 ], [ 6, 6, 4, 4 ],   [ 7, 5, 4, 4 ], [ 7, 7, 6 ], [ 8, 4, 4, 4 ], [ 8, 6, 6 ], [ 8, 7, 5 ],   [ 8, 8, 4 ], [ 9, 6, 5 ], [ 9, 7, 4 ], [ 10, 5, 5 ], [ 10, 6, 4 ],   [ 10, 10 ] ] gap> RestrictedPartitionsWithoutRepetitions( 20, [4..10] ); [ [ 10, 6, 4 ], [ 9, 7, 4 ], [ 9, 6, 5 ], [ 8, 7, 5 ] ] gap> RestrictedPartitionsWithoutRepetitions( 10^2, List([1..10], n->n^2 ) ); [ [ 100 ], [ 64, 36 ], [ 49, 25, 16, 9, 1 ] ]  4.1-4 NextProbablyPrimeInt NextProbablyPrimeInt( n )  function This function has been transferred from package RCWA. The function NextProbablyPrimeInt(n) does the same as NextPrimeInt(n) except that for reasons of performance it tests numbers only for IsProbablyPrimeInt(n) instead of IsPrimeInt(n). For large n, this function is much faster than NextPrimeInt(n)  Example  gap> n := 2^251; 3618502788666131106986593281521497120414687020801267626233049500247285301248 gap> NextProbablyPrimeInt( n ); 3618502788666131106986593281521497120414687020801267626233049500247285301313 gap> NextPrimeInt( n ); # same result, just faster 3618502788666131106986593281521497120414687020801267626233049500247285301313  4.1-5 PrimeNumbersIterator PrimeNumbersIterator( [chunksize] )  function This function has been transferred from package RCWA. This function returns an iterator which runs over the prime numbers in ascending order; it takes an optional argument chunksize which specifies the length of the interval which is sieved in one go (the default is 10^7), and which can be used to balance runtime vs. memory consumption. It is assumed that chunksize is larger than any gap between two consecutive primes within the range one intends to run the iterator over.  Example  gap> iter := PrimeNumbersIterator();; gap> for i in [1..100] do p := NextIterator(iter); od; gap> p; 541 gap> sum := 0;; gap> ## "prime number race" 1 vs. 3 mod 4 gap> for p in PrimeNumbersIterator() do  >  if p <> 2 then sum := sum + E(4)^(p-1); fi; >  if sum > 0 then break; fi; >  od; gap> p; 26861  utils-0.94/doc/chap4_mj.html0000644000000000000000000003045215174515600012664 0ustar00 GAP (Utils) - Chapter 4: Number-theoretic functions
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

4 Number-theoretic functions

4.1 Functions for integers

4.1-1 AllSmoothIntegers
‣ AllSmoothIntegers( maxp, maxn )( function )
‣ AllSmoothIntegers( L, maxp )( function )

This function has been transferred from package RCWA.

The function AllSmoothIntegers(maxp,maxn) returns the list of all positive integers less than or equal to maxn whose prime factors are all in the list \(L = \{p ~|~ p \leqslant maxp, p~\mbox{prime} \}\).

In the alternative form, when \(L\) is a list of primes, the function returns the list of all positive integers whose prime factors lie in \(L\).

gap> AllSmoothIntegers( 3, 1000 );
[ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96, 
  108, 128, 144, 162, 192, 216, 243, 256, 288, 324, 384, 432, 486, 512, 576, 
  648, 729, 768, 864, 972 ]
gap> AllSmoothIntegers( [5,11,17], 1000 );
[ 1, 5, 11, 17, 25, 55, 85, 121, 125, 187, 275, 289, 425, 605, 625, 935 ]
gap> Length( last );
16
gap> List( [3..20], n -> Length( AllSmoothIntegers( [5,11,17], 10^n ) ) );
[ 16, 29, 50, 78, 114, 155, 212, 282, 359, 452, 565, 691, 831, 992, 1173, 
  1374, 1595, 1843 ]

4.1-2 AllProducts
‣ AllProducts( L, k )( function )

This function has been transferred from package RCWA.

The command AllProducts(L,k) returns the list of all products of k entries of the list L. Note that every ordering of the entries is used so that, in the commuting case, there are bound to be repetitions.

gap> AllProducts([1..4],3); 
[ 1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16, 2, 4, 6, 8, 4, 8, 12, 
  16, 6, 12, 18, 24, 8, 16, 24, 32, 3, 6, 9, 12, 6, 12, 18, 24, 9, 18, 27, 
  36, 12, 24, 36, 48, 4, 8, 12, 16, 8, 16, 24, 32, 12, 24, 36, 48, 16, 32, 
  48, 64 ]
gap> Set(last);            
[ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 64 ]
gap> AllProducts( [(1,2,3),(2,3,4)], 2 );
[ (2,4,3), (1,2)(3,4), (1,3)(2,4), (1,3,2) ]

4.1-3 RestrictedPartitionsWithoutRepetitions
‣ RestrictedPartitionsWithoutRepetitions( n, S )( function )

This function has been transferred from package RCWA.

For a positive integer n and a set of positive integers S, this function returns the list of partitions of n into distinct elements of S. Unlike RestrictedPartitions, no repetitions are allowed.

gap> RestrictedPartitions( 20, [4..10] );
[ [ 4, 4, 4, 4, 4 ], [ 5, 5, 5, 5 ], [ 6, 5, 5, 4 ], [ 6, 6, 4, 4 ], 
  [ 7, 5, 4, 4 ], [ 7, 7, 6 ], [ 8, 4, 4, 4 ], [ 8, 6, 6 ], [ 8, 7, 5 ], 
  [ 8, 8, 4 ], [ 9, 6, 5 ], [ 9, 7, 4 ], [ 10, 5, 5 ], [ 10, 6, 4 ], 
  [ 10, 10 ] ]
gap> RestrictedPartitionsWithoutRepetitions( 20, [4..10] );
[ [ 10, 6, 4 ], [ 9, 7, 4 ], [ 9, 6, 5 ], [ 8, 7, 5 ] ]
gap> RestrictedPartitionsWithoutRepetitions( 10^2, List([1..10], n->n^2 ) );
[ [ 100 ], [ 64, 36 ], [ 49, 25, 16, 9, 1 ] ]

4.1-4 NextProbablyPrimeInt
‣ NextProbablyPrimeInt( n )( function )

This function has been transferred from package RCWA.

The function NextProbablyPrimeInt(n) does the same as NextPrimeInt(n) except that for reasons of performance it tests numbers only for IsProbablyPrimeInt(n) instead of IsPrimeInt(n). For large n, this function is much faster than NextPrimeInt(n)

gap> n := 2^251;
3618502788666131106986593281521497120414687020801267626233049500247285301248
gap> NextProbablyPrimeInt( n );
3618502788666131106986593281521497120414687020801267626233049500247285301313
gap> NextPrimeInt( n );  # same result, just faster
3618502788666131106986593281521497120414687020801267626233049500247285301313

4.1-5 PrimeNumbersIterator
‣ PrimeNumbersIterator( [chunksize] )( function )

This function has been transferred from package RCWA.

This function returns an iterator which runs over the prime numbers in ascending order; it takes an optional argument chunksize which specifies the length of the interval which is sieved in one go (the default is \(10^7\)), and which can be used to balance runtime vs. memory consumption. It is assumed that chunksize is larger than any gap between two consecutive primes within the range one intends to run the iterator over.

gap> iter := PrimeNumbersIterator();;
gap> for i in [1..100] do  p := NextIterator(iter);  od;
gap> p;
541
gap> sum := 0;;
gap> ## "prime number race" 1 vs. 3 mod 4
gap> for p in PrimeNumbersIterator() do 
>       if p <> 2 then sum := sum + E(4)^(p-1); fi;
>       if sum > 0 then break; fi;
>    od;
gap> p;
26861
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap5.html0000644000000000000000000010364315174515600012202 0ustar00 GAP (Utils) - Chapter 5: Groups and homomorphisms
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

5 Groups and homomorphisms

5.1 Functions for groups

5.1-1 Comm
‣ Comm( L )( operation )

This method has been transferred from package ResClasses.

It provides a method for Comm when the argument is a list (enclosed in square brackets), and calls the function LeftNormedComm.

gap> Comm( [ (1,2), (2,3) ] );
(1,2,3)
gap> Comm( [(1,2),(2,3),(3,4),(4,5),(5,6)] );
(1,5,6)
gap> Comm(Comm(Comm(Comm((1,2),(2,3)),(3,4)),(4,5)),(5,6));  ## the same
(1,5,6)

5.1-2 IsCommuting
‣ IsCommuting( a, b )( operation )

This function has been transferred from package ResClasses.

It tests whether two elements in a group commute.

gap> D12 := DihedralGroup( 12 );
<pc group of size 12 with 3 generators>
gap> SetName( D12, "D12" ); 
gap> a := D12.1;;  b := D12.2;;  
gap> IsCommuting( a, b );
false

5.1-3 ListOfPowers
‣ ListOfPowers( g, exp )( operation )

This function has been transferred from package RCWA.

The operation ListOfPowers(g,exp) returns the list [g,g^2,...,g^exp] of powers of the element g.

gap> ListOfPowers( 2, 20 );
[ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
 32768, 65536, 131072, 262144, 524288, 1048576 ]
gap> ListOfPowers( (1,2,3)(4,5), 12 );
[ (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), (),
 (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), () ]
gap> ListOfPowers( D12.2, 6 );
[ f2, f3, f2*f3, f3^2, f2*f3^2, <identity> of ... ]

5.1-4 GeneratorsAndInverses
‣ GeneratorsAndInverses( G )( operation )

This function has been transferred from package RCWA.

This operation returns a list containing the generators of G followed by the inverses of these generators.

gap> GeneratorsAndInverses( D12 );
[ f1, f2, f3, f1, f2*f3^2, f3^2 ]
gap> GeneratorsAndInverses( SymmetricGroup(5) );     
[ (1,2,3,4,5), (1,2), (1,5,4,3,2), (1,2) ]

5.1-5 UpperFittingSeries
‣ UpperFittingSeries( G )( attribute )
‣ LowerFittingSeries( G )( attribute )
‣ FittingLength( G )( attribute )

These three functions have been transferred from package ResClasses.

The upper and lower Fitting series and the Fitting length of a solvable group are described here: https://en.wikipedia.org/wiki/Fitting_length.

gap> upp:= UpperFittingSeries( D12 );;
gap> List( upp, StructureDescription );
[ "1", "C6", "D12" ]
gap> low:= LowerFittingSeries( D12 );;
gap> List( low, StructureDescription );
[ "D12", "C3", "1" ]
gap> FittingLength( D12 );
2
gap> S4 := SymmetricGroup( 4 );;
gap> UpperFittingSeries( S4 );
[ Group(()), Group([ (1,2)(3,4), (1,4)(2,3) ]), 
  Group([ (2,4,3), (1,2)(3,4) ]), Group([ (3,4), (2,4,3), (1,2)(3,4) ]) ]
gap> List( last, StructureDescription );
[ "1", "C2 x C2", "A4", "S4" ]
gap> LowerFittingSeries( S4 );
[ Sym( [ 1 .. 4 ] ), Alt( [ 1 .. 4 ] ), Group([ (1,4)(2,3), (1,2)(3,4) ]), 
  Group(()) ]
gap> List( last, StructureDescription );
[ "S4", "A4", "C2 x C2", "1" ]
gap> FittingLength( S4);
3

5.2 Left Cosets for Groups

5.2-1 LeftCoset
‣ LeftCoset( g, U )( operation )

Since GAP uses right actions by default, the library contains the operation RightCoset(U,g) for constructing the right coset Ug of a subgroup U ≤ G and an element g ∈ G. It has been noted in the reference manual that, by inverting all the elements in Ug, the left coset g^-1U is obtained.

Just for the sake of completeness, from August 2022 this package provides the operation LeftCoset(g,U) for constructing the left coset gU. Users are strongly recommended to continue to use RightCoset for all serious calculations, since left cosets have a much simpler implementation and do not behave exactly like right cosets.

The methods for left cosets which are provided generally work by converting gU to Ug^-1; applying the equivalent method for right cosets; and, if necessary, converting back again to left cosets.

G acts on left cosets by OnLeftInverse: (gU)^g_0 = g_0^-1*(gU) = (g_0^-1g)U.

gap> a4 := Group( (1,2,3), (2,3,4) );; SetName( a4, "a4" );
gap> k4 := Group( (1,2)(3,4), (1,3)(2,4) );; SetName( k4, "k4" );
gap> rc := RightCosets( a4, k4 );
[ RightCoset(k4,()), RightCoset(k4,(2,3,4)), RightCoset(k4,(2,4,3)) ]
gap> lc := LeftCosets( a4, k4 );
[ LeftCoset((),k4), LeftCoset((2,4,3),k4), LeftCoset((2,3,4),k4) ]
gap> AsSet( lc[2] );
[ (2,4,3), (1,2,3), (1,3,4), (1,4,2) ]
gap> LeftCoset( (1,4,2), k4 ) = lc[2];
true
gap> Representative( lc[2] );
(2,4,3)
gap> ActingDomain( lc[2] );
k4
gap> (1,4,3) in lc[3];
true
gap> (1,2,3)*lc[2] = lc[3];
true
gap> lc[2]^(1,3,2) = lc[3];
true

5.2-2 Inverse

The inverse of the left coset gU is the right coset Ug^-1, and conversely. This is an abuse of the attribute Inverse, since the standard requirement, that x*x^-1 is an identity, does not hold.

gap> Inverse( rc[3] ) = lc[3];
true
gap> Inverse( lc[2] ) = rc[2];
true

5.3 Functions for group homomorphisms

5.3-1 EpimorphismByGenerators
‣ EpimorphismByGenerators( G, H )( operation )

This function has been transferred from package RCWA.

It constructs a group homomorphism which maps the generators of G to those of H. Its intended use is when G is a free group, and a warning is printed when this is not the case. Note that anything may happen if the resulting map is not a homomorphism!

gap> G := Group( (1,2,3), (3,4,5), (5,6,7), (7,8,9) );;
gap> phi := EpimorphismByGenerators( FreeGroup("a","b","c","d"), G );
[ a, b, c, d ] -> [ (1,2,3), (3,4,5), (5,6,7), (7,8,9) ]
gap> PreImagesRepresentativeNC( phi, (1,2,3,4,5,6,7,8,9) );
d*c*b*a
gap> a := G.1;; b := G.2;; c := G.3;; d := G.4;;
gap> d*c*b*a;
(1,2,3,4,5,6,7,8,9)
gap> ## note that it is easy to produce nonsense: 
gap> epi := EpimorphismByGenerators( Group((1,2,3)), Group((8,9)) );
Warning: calling GroupHomomorphismByImagesNC without checks
[ (1,2,3) ] -> [ (8,9) ]
gap> IsGroupHomomorphism( epi );
true
gap> Image( epi, (1,2,3) );                                            
()
gap> Image( epi, (1,3,2) );
(8,9)

5.3-2 Pullback
‣ Pullback( hom1, hom2 )( operation )
‣ PullbackInfo( G )( attribute )

If ϕ_1 : G_1 -> H and ϕ_2 : G_2 -> H are two group homomorphisms with the same range, then their pullback is the subgroup of G_1 × G_2 consisting of those elements (g_1,g_2) such that ϕ_1 g_1 = ϕ_2 g_2.

The attribute PullbackInfo of a pullback group P is similar to DirectProductInfo for a direct product of groups. Its value is a record with the following components:

directProduct

the direct product G_1 × G_2, and

projections

a list with the two projections onto G_1 and G_2.

There are no embeddings in this record, but it is possible to use the embeddings into the direct product, see Embedding (Reference: Embedding).

gap> s4 := Group( (1,2),(2,3),(3,4) );;
gap> s3 := Group( (5,6),(6,7) );;
gap> c3 := Subgroup( s3, [ (5,6,7) ] );;
gap> f := GroupHomomorphismByImages( s4, s3, 
>             [(1,2),(2,3),(3,4)], [(5,6),(6,7),(5,6)] );; 
gap> i := GroupHomomorphismByImages( c3, s3, [(5,6,7)], [(5,6,7)] );; 
gap> Pfi := Pullback( f, i );
Group([ (2,3,4)(5,7,6), (1,2)(3,4) ])
gap> StructureDescription( Pfi );
"A4"
gap> info := PullbackInfo( Pfi );
rec( directProduct := Group([ (1,2), (2,3), (3,4), (5,6,7) ]), 
  projections := [ [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (2,3,4), (1,2)(3,4) ], 
      [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (5,7,6), () ] ] )
gap> g := (1,2,3)(5,6,7);; 
gap> ImageElm( info!.projections[1], g );
(1,2,3)
gap> ImageElm( info!.projections[2], g );
(5,6,7) 
gap> dp := info!.directProduct;; 
gap> a := ImageElm( Embedding( dp, 1 ), (1,4,3) );; 
gap> b := ImageElm( Embedding( dp, 2 ), (5,7,6) );; 
gap> a*b in Pfi;
true

5.3-3 CentralProduct
‣ CentralProduct( G1, G2, Z1, Phi )( operation )
‣ CentralProductInfo( G )( attribute )

This function was added by Thomas Breuer, following discussions with Hongyi Zhao (see https://github.com/gap-packages/hap/issues/73).

Let G1 and G2 be two groups, Z1 be a central subgroup of G1, and Phi be an isomorphism from Z1 to a central subgroup of G2. The central product defined by these arguments is the factor group of the direct product of G1 and G2 by the central subgroup { (z, (Phi(z))^-1) : z ∈ Z1 }.

The attribute CentralProductInfo of a group G that has been created by CentralProduct is similar to PullbackInfo (5.3-2) for pullback groups. Its value is a record with the following components.

projection

the epimorphism from the direct product of G1 and G2 to G, and

phi

the map Phi.

Note that one can access the direct product as the Source (Reference: Source) value of the projection map, and one can access G1 and G2 as the two embeddings of this direct product, see Embedding (Reference: Embedding).

gap> g1 := DihedralGroup( 8 );
<pc group of size 8 with 3 generators>
gap> c1 := Centre( g1 );
Group([ f3 ])
gap> cp1 := CentralProduct( g1, g1, c1, IdentityMapping( c1 ) );
Group([ f1, f2, f5, f3, f4, f5 ])
gap> IdGroup( cp1 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) );
true
gap> g2 := QuaternionGroup( 8 );
<pc group of size 8 with 3 generators>
gap> c2 := Centre( g2 );
Group([ y2 ])
gap> cp2 := CentralProduct( g2, g2, c2, IdentityMapping( c2 ) );
Group([ f1, f2, f5, f3, f4, f5 ])
gap> IdGroup( cp2 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) );
true
gap> info2 := CentralProductInfo( cp2 );
rec( phi := IdentityMapping( Group([ y2 ]) ), 
  projection := [ f1, f2, f3, f4, f5, f6 ] -> [ f1, f2, f5, f3, f4, f5 ] )
gap> Source( Embedding( Source( info2.projection ), 1 ) ) = g2;
true

5.3-4 IdempotentEndomorphisms
‣ IdempotentEndomorphisms( G )( operation )
‣ IdempotentEndomorphismsData( G )( attribute )
‣ IdempotentEndomorphismsWithImage( genG, R )( operation )

An endomorphism f: G -> G is idempotent if f^2 = f. It has an image R ≤ G, is the identity map when restricted to R, and has a kernel N which has trivial intersection with R and has size |G|/|R|.

The operation IdempotentEndomorphismsWithImage(genG,R) returns a list of the images of the generating set genG of a group G under the idempotent endomorphisms with image R.

The attribute IdempotentEndomorphismsData(G) returns a record data with fields data.gens, a fixed generating set for G, and data.images a list of the non-empty outputs of IdempotentEndomorphismsWithImage(genG,R) obtained by iterating over all subgroups R of G.

The operation IdempotentEndomorphisms(G) returns the list of these mappings obtained using IdempotentEndomorphismsData(G). The first of these is the zero map, the last is the identity.

gap> gens := [ (1,2,3,4), (1,2)(3,4) ];; 
gap> d8 := Group( gens );;
gap> SetName( d8, "d8" );
gap> c2 := Subgroup( d8, [ (2,4) ] );;
gap> SortedList( IdempotentEndomorphismsWithImage( gens, c2 ) );
[ [ (), (2,4) ], [ (2,4), () ] ]
gap> data:= IdempotentEndomorphismsData( d8 );;
gap> data.images[1];
[ [ (), () ] ]
gap> List( data.images, Length );
[ 1, 2, 2, 2, 2, 1 ]
gap> all:= IdempotentEndomorphisms( d8 );;
gap> Length( all );
10
gap> all[1];
[ (1,2,3,4), (1,2)(3,4) ] -> [ (), () ]
gap> Size( Image( all[1] ) );
1
gap> Last( all ) = IdentityMapping( d8 );
true

The quaternion group q8 is an example of a group with a tail: there is only one subgroup in the lattice which covers the identity subgroup. The only idempotent isomorphisms of such groups are the identity mapping and the zero mapping because the only pairs N,R are the whole group and the identity subgroup.

gap> q8 := QuaternionGroup( 8 );;
gap> IdempotentEndomorphisms( q8 );
[ [ x, y ] -> [ <identity> of ..., <identity> of ... ], [ x, y ] -> [ x, y ] ]

5.3-5 DirectProductOfFunctions
‣ DirectProductOfFunctions( G, H, f1, f2 )( operation )

Given group homomorphisms f_1 : G_1 -> G_2 and f_2 : H_1 -> H_2, this operation return the product homomorphism f_1 × f_2 : G_1 × G_2 -> H_1 × H_2.

gap> c4 := Group( (1,2,3,4) );; 
gap> c2 := Group( (5,6) );; 
gap> f1 := GroupHomomorphismByImages( c4, c2, [(1,2,3,4)], [(5,6)] );;
gap> c3 := Group( (1,2,3) );; 
gap> c6 := Group( (1,2,3,4,5,6) );; 
gap> f2 := GroupHomomorphismByImages( c3, c6, [(1,2,3)], [(1,3,5)(2,4,6)] );; 
gap> c4c3 := DirectProduct( c4, c3 ); 
Group([ (1,2,3,4), (5,6,7) ])
gap> c2c6 := DirectProduct( c2, c6 ); 
Group([ (1,2), (3,4,5,6,7,8) ])
gap> f := DirectProductOfFunctions( c4c3, c2c6, f1, f2 ); 
[ (1,2,3,4), (5,6,7) ] -> [ (1,2), (3,5,7)(4,6,8) ]
gap> ImageElm( f, (1,4,3,2)(5,7,6) ); 
(1,2)(3,7,5)(4,8,6)

5.3-6 DirectProductOfAutomorphismGroups
‣ DirectProductOfAutomorphismGroups( A1, A2 )( operation )

Let A_1,A_2 be groups of automorphism of groups G_1,G_2 respectively. The output of this function is a group A_1 × A_2 of automorphisms of G_1 × G_2.

gap> c9 := Group( (1,2,3,4,5,6,7,8,9) );; 
gap> ac9 := AutomorphismGroup( c9 );; 
gap> q8 := QuaternionGroup( IsPermGroup, 8 );;
gap> aq8 := AutomorphismGroup( q8 );;
gap> A := DirectProductOfAutomorphismGroups( ac9, aq8 );
<group with 5 generators>
gap> genA := GeneratorsOfGroup( A );;
gap> G := Source( genA[1] );
Group([ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13)
(14,15,16,17) ])
gap> a := genA[1]*genA[5];  
[ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13)(14,15,16,17) 
 ] -> [ (1,3,5,7,9,2,4,6,8), (10,16,12,14)(11,15,13,17), 
  (10,11,12,13)(14,15,16,17) ]
gap> ImageElm( a, (1,9,8,7,6,5,4,3,2)(10,14,12,16)(11,17,13,15) );
(1,8,6,4,2,9,7,5,3)(10,16,12,14)(11,15,13,17)
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap5.txt0000644000000000000000000005536215174515600012061 0ustar00 5 Groups and homomorphisms 5.1 Functions for groups 5.1-1 Comm Comm( L )  operation This method has been transferred from package ResClasses. It provides a method for Comm when the argument is a list (enclosed in square brackets), and calls the function LeftNormedComm.  Example  gap> Comm( [ (1,2), (2,3) ] ); (1,2,3) gap> Comm( [(1,2),(2,3),(3,4),(4,5),(5,6)] ); (1,5,6) gap> Comm(Comm(Comm(Comm((1,2),(2,3)),(3,4)),(4,5)),(5,6)); ## the same (1,5,6)  5.1-2 IsCommuting IsCommuting( a, b )  operation This function has been transferred from package ResClasses. It tests whether two elements in a group commute.  Example  gap> D12 := DihedralGroup( 12 );  gap> SetName( D12, "D12" );  gap> a := D12.1;; b := D12.2;;  gap> IsCommuting( a, b ); false  5.1-3 ListOfPowers ListOfPowers( g, exp )  operation This function has been transferred from package RCWA. The operation ListOfPowers(g,exp) returns the list [g,g^2,...,g^exp] of powers of the element g.  Example  gap> ListOfPowers( 2, 20 ); [ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,  32768, 65536, 131072, 262144, 524288, 1048576 ] gap> ListOfPowers( (1,2,3)(4,5), 12 ); [ (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), (),  (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), () ] gap> ListOfPowers( D12.2, 6 ); [ f2, f3, f2*f3, f3^2, f2*f3^2, of ... ]  5.1-4 GeneratorsAndInverses GeneratorsAndInverses( G )  operation This function has been transferred from package RCWA. This operation returns a list containing the generators of G followed by the inverses of these generators.  Example  gap> GeneratorsAndInverses( D12 ); [ f1, f2, f3, f1, f2*f3^2, f3^2 ] gap> GeneratorsAndInverses( SymmetricGroup(5) );  [ (1,2,3,4,5), (1,2), (1,5,4,3,2), (1,2) ]  5.1-5 UpperFittingSeries UpperFittingSeries( G )  attribute LowerFittingSeries( G )  attribute FittingLength( G )  attribute These three functions have been transferred from package ResClasses. The upper and lower Fitting series and the Fitting length of a solvable group are described here: https://en.wikipedia.org/wiki/Fitting_length.  Example  gap> upp:= UpperFittingSeries( D12 );; gap> List( upp, StructureDescription ); [ "1", "C6", "D12" ] gap> low:= LowerFittingSeries( D12 );; gap> List( low, StructureDescription ); [ "D12", "C3", "1" ] gap> FittingLength( D12 ); 2 gap> S4 := SymmetricGroup( 4 );; gap> UpperFittingSeries( S4 ); [ Group(()), Group([ (1,2)(3,4), (1,4)(2,3) ]),   Group([ (2,4,3), (1,2)(3,4) ]), Group([ (3,4), (2,4,3), (1,2)(3,4) ]) ] gap> List( last, StructureDescription ); [ "1", "C2 x C2", "A4", "S4" ] gap> LowerFittingSeries( S4 ); [ Sym( [ 1 .. 4 ] ), Alt( [ 1 .. 4 ] ), Group([ (1,4)(2,3), (1,2)(3,4) ]),   Group(()) ] gap> List( last, StructureDescription ); [ "S4", "A4", "C2 x C2", "1" ] gap> FittingLength( S4); 3  5.2 Left Cosets for Groups 5.2-1 LeftCoset LeftCoset( g, U )  operation Since GAP uses right actions by default, the library contains the operation RightCoset(U,g) for constructing the right coset Ug of a subgroup U ≤ G and an element g ∈ G. It has been noted in the reference manual that, by inverting all the elements in Ug, the left coset g^-1U is obtained. Just for the sake of completeness, from August 2022 this package provides the operation LeftCoset(g,U) for constructing the left coset gU. Users are strongly recommended to continue to use RightCoset for all serious calculations, since left cosets have a much simpler implementation and do not behave exactly like right cosets. The methods for left cosets which are provided generally work by converting gU to Ug^-1; applying the equivalent method for right cosets; and, if necessary, converting back again to left cosets. G acts on left cosets by OnLeftInverse: (gU)^g_0 = g_0^-1*(gU) = (g_0^-1g)U.  Example  gap> a4 := Group( (1,2,3), (2,3,4) );; SetName( a4, "a4" ); gap> k4 := Group( (1,2)(3,4), (1,3)(2,4) );; SetName( k4, "k4" ); gap> rc := RightCosets( a4, k4 ); [ RightCoset(k4,()), RightCoset(k4,(2,3,4)), RightCoset(k4,(2,4,3)) ] gap> lc := LeftCosets( a4, k4 ); [ LeftCoset((),k4), LeftCoset((2,4,3),k4), LeftCoset((2,3,4),k4) ] gap> AsSet( lc[2] ); [ (2,4,3), (1,2,3), (1,3,4), (1,4,2) ] gap> LeftCoset( (1,4,2), k4 ) = lc[2]; true gap> Representative( lc[2] ); (2,4,3) gap> ActingDomain( lc[2] ); k4 gap> (1,4,3) in lc[3]; true gap> (1,2,3)*lc[2] = lc[3]; true gap> lc[2]^(1,3,2) = lc[3]; true  5.2-2 Inverse The inverse of the left coset gU is the right coset Ug^-1, and conversely. This is an abuse of the attribute Inverse, since the standard requirement, that x*x^-1 is an identity, does not hold.  Example  gap> Inverse( rc[3] ) = lc[3]; true gap> Inverse( lc[2] ) = rc[2]; true  5.3 Functions for group homomorphisms 5.3-1 EpimorphismByGenerators EpimorphismByGenerators( G, H )  operation This function has been transferred from package RCWA. It constructs a group homomorphism which maps the generators of G to those of H. Its intended use is when G is a free group, and a warning is printed when this is not the case. Note that anything may happen if the resulting map is not a homomorphism!  Example  gap> G := Group( (1,2,3), (3,4,5), (5,6,7), (7,8,9) );; gap> phi := EpimorphismByGenerators( FreeGroup("a","b","c","d"), G ); [ a, b, c, d ] -> [ (1,2,3), (3,4,5), (5,6,7), (7,8,9) ] gap> PreImagesRepresentativeNC( phi, (1,2,3,4,5,6,7,8,9) ); d*c*b*a gap> a := G.1;; b := G.2;; c := G.3;; d := G.4;; gap> d*c*b*a; (1,2,3,4,5,6,7,8,9) gap> ## note that it is easy to produce nonsense:  gap> epi := EpimorphismByGenerators( Group((1,2,3)), Group((8,9)) ); Warning: calling GroupHomomorphismByImagesNC without checks [ (1,2,3) ] -> [ (8,9) ] gap> IsGroupHomomorphism( epi ); true gap> Image( epi, (1,2,3) );  () gap> Image( epi, (1,3,2) ); (8,9)  5.3-2 Pullback Pullback( hom1, hom2 )  operation PullbackInfo( G )  attribute If ϕ_1 : G_1 -> H and ϕ_2 : G_2 -> H are two group homomorphisms with the same range, then their pullback is the subgroup of G_1 × G_2 consisting of those elements (g_1,g_2) such that ϕ_1 g_1 = ϕ_2 g_2. The attribute PullbackInfo of a pullback group P is similar to DirectProductInfo for a direct product of groups. Its value is a record with the following components: directProduct the direct product G_1 × G_2, and projections a list with the two projections onto G_1 and G_2. There are no embeddings in this record, but it is possible to use the embeddings into the direct product, see Embedding (Reference: Embedding).  Example  gap> s4 := Group( (1,2),(2,3),(3,4) );; gap> s3 := Group( (5,6),(6,7) );; gap> c3 := Subgroup( s3, [ (5,6,7) ] );; gap> f := GroupHomomorphismByImages( s4, s3,  >  [(1,2),(2,3),(3,4)], [(5,6),(6,7),(5,6)] );;  gap> i := GroupHomomorphismByImages( c3, s3, [(5,6,7)], [(5,6,7)] );;  gap> Pfi := Pullback( f, i ); Group([ (2,3,4)(5,7,6), (1,2)(3,4) ]) gap> StructureDescription( Pfi ); "A4" gap> info := PullbackInfo( Pfi ); rec( directProduct := Group([ (1,2), (2,3), (3,4), (5,6,7) ]),   projections := [ [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (2,3,4), (1,2)(3,4) ],   [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (5,7,6), () ] ] ) gap> g := (1,2,3)(5,6,7);;  gap> ImageElm( info!.projections[1], g ); (1,2,3) gap> ImageElm( info!.projections[2], g ); (5,6,7)  gap> dp := info!.directProduct;;  gap> a := ImageElm( Embedding( dp, 1 ), (1,4,3) );;  gap> b := ImageElm( Embedding( dp, 2 ), (5,7,6) );;  gap> a*b in Pfi; true  5.3-3 CentralProduct CentralProduct( G1, G2, Z1, Phi )  operation CentralProductInfo( G )  attribute This function was added by Thomas Breuer, following discussions with Hongyi Zhao (see https://github.com/gap-packages/hap/issues/73). Let G1 and G2 be two groups, Z1 be a central subgroup of G1, and Phi be an isomorphism from Z1 to a central subgroup of G2. The central product defined by these arguments is the factor group of the direct product of G1 and G2 by the central subgroup { (z, (Phi(z))^-1) : z ∈ Z1 }. The attribute CentralProductInfo of a group G that has been created by CentralProduct is similar to PullbackInfo (5.3-2) for pullback groups. Its value is a record with the following components. projection the epimorphism from the direct product of G1 and G2 to G, and phi the map Phi. Note that one can access the direct product as the Source (Reference: Source) value of the projection map, and one can access G1 and G2 as the two embeddings of this direct product, see Embedding (Reference: Embedding).  Example  gap> g1 := DihedralGroup( 8 );  gap> c1 := Centre( g1 ); Group([ f3 ]) gap> cp1 := CentralProduct( g1, g1, c1, IdentityMapping( c1 ) ); Group([ f1, f2, f5, f3, f4, f5 ]) gap> IdGroup( cp1 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) ); true gap> g2 := QuaternionGroup( 8 );  gap> c2 := Centre( g2 ); Group([ y2 ]) gap> cp2 := CentralProduct( g2, g2, c2, IdentityMapping( c2 ) ); Group([ f1, f2, f5, f3, f4, f5 ]) gap> IdGroup( cp2 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) ); true gap> info2 := CentralProductInfo( cp2 ); rec( phi := IdentityMapping( Group([ y2 ]) ),   projection := [ f1, f2, f3, f4, f5, f6 ] -> [ f1, f2, f5, f3, f4, f5 ] ) gap> Source( Embedding( Source( info2.projection ), 1 ) ) = g2; true  5.3-4 IdempotentEndomorphisms IdempotentEndomorphisms( G )  operation IdempotentEndomorphismsData( G )  attribute IdempotentEndomorphismsWithImage( genG, R )  operation An endomorphism f: G -> G is idempotent if f^2 = f. It has an image R ≤ G, is the identity map when restricted to R, and has a kernel N which has trivial intersection with R and has size |G|/|R|. The operation IdempotentEndomorphismsWithImage(genG,R) returns a list of the images of the generating set genG of a group G under the idempotent endomorphisms with image R. The attribute IdempotentEndomorphismsData(G) returns a record data with fields data.gens, a fixed generating set for G, and data.images a list of the non-empty outputs of IdempotentEndomorphismsWithImage(genG,R) obtained by iterating over all subgroups R of G. The operation IdempotentEndomorphisms(G) returns the list of these mappings obtained using IdempotentEndomorphismsData(G). The first of these is the zero map, the last is the identity.  Example  gap> gens := [ (1,2,3,4), (1,2)(3,4) ];;  gap> d8 := Group( gens );; gap> SetName( d8, "d8" ); gap> c2 := Subgroup( d8, [ (2,4) ] );; gap> SortedList( IdempotentEndomorphismsWithImage( gens, c2 ) ); [ [ (), (2,4) ], [ (2,4), () ] ] gap> data:= IdempotentEndomorphismsData( d8 );; gap> data.images[1]; [ [ (), () ] ] gap> List( data.images, Length ); [ 1, 2, 2, 2, 2, 1 ] gap> all:= IdempotentEndomorphisms( d8 );; gap> Length( all ); 10 gap> all[1]; [ (1,2,3,4), (1,2)(3,4) ] -> [ (), () ] gap> Size( Image( all[1] ) ); 1 gap> Last( all ) = IdentityMapping( d8 ); true  The quaternion group q8 is an example of a group with a tail: there is only one subgroup in the lattice which covers the identity subgroup. The only idempotent isomorphisms of such groups are the identity mapping and the zero mapping because the only pairs N,R are the whole group and the identity subgroup.  Example  gap> q8 := QuaternionGroup( 8 );; gap> IdempotentEndomorphisms( q8 ); [ [ x, y ] -> [ of ..., of ... ], [ x, y ] -> [ x, y ] ]  5.3-5 DirectProductOfFunctions DirectProductOfFunctions( G, H, f1, f2 )  operation Given group homomorphisms f_1 : G_1 -> G_2 and f_2 : H_1 -> H_2, this operation return the product homomorphism f_1 × f_2 : G_1 × G_2 -> H_1 × H_2.  Example  gap> c4 := Group( (1,2,3,4) );;  gap> c2 := Group( (5,6) );;  gap> f1 := GroupHomomorphismByImages( c4, c2, [(1,2,3,4)], [(5,6)] );; gap> c3 := Group( (1,2,3) );;  gap> c6 := Group( (1,2,3,4,5,6) );;  gap> f2 := GroupHomomorphismByImages( c3, c6, [(1,2,3)], [(1,3,5)(2,4,6)] );;  gap> c4c3 := DirectProduct( c4, c3 );  Group([ (1,2,3,4), (5,6,7) ]) gap> c2c6 := DirectProduct( c2, c6 );  Group([ (1,2), (3,4,5,6,7,8) ]) gap> f := DirectProductOfFunctions( c4c3, c2c6, f1, f2 );  [ (1,2,3,4), (5,6,7) ] -> [ (1,2), (3,5,7)(4,6,8) ] gap> ImageElm( f, (1,4,3,2)(5,7,6) );  (1,2)(3,7,5)(4,8,6)  5.3-6 DirectProductOfAutomorphismGroups DirectProductOfAutomorphismGroups( A1, A2 )  operation Let A_1,A_2 be groups of automorphism of groups G_1,G_2 respectively. The output of this function is a group A_1 × A_2 of automorphisms of G_1 × G_2.  Example  gap> c9 := Group( (1,2,3,4,5,6,7,8,9) );;  gap> ac9 := AutomorphismGroup( c9 );;  gap> q8 := QuaternionGroup( IsPermGroup, 8 );; gap> aq8 := AutomorphismGroup( q8 );; gap> A := DirectProductOfAutomorphismGroups( ac9, aq8 );  gap> genA := GeneratorsOfGroup( A );; gap> G := Source( genA[1] ); Group([ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13) (14,15,16,17) ]) gap> a := genA[1]*genA[5];  [ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13)(14,15,16,17)   ] -> [ (1,3,5,7,9,2,4,6,8), (10,16,12,14)(11,15,13,17),   (10,11,12,13)(14,15,16,17) ] gap> ImageElm( a, (1,9,8,7,6,5,4,3,2)(10,14,12,16)(11,17,13,15) ); (1,8,6,4,2,9,7,5,3)(10,16,12,14)(11,15,13,17)  utils-0.94/doc/chap5_mj.html0000644000000000000000000010467015174515600012671 0ustar00 GAP (Utils) - Chapter 5: Groups and homomorphisms
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

5 Groups and homomorphisms

5.1 Functions for groups

5.1-1 Comm
‣ Comm( L )( operation )

This method has been transferred from package ResClasses.

It provides a method for Comm when the argument is a list (enclosed in square brackets), and calls the function LeftNormedComm.

gap> Comm( [ (1,2), (2,3) ] );
(1,2,3)
gap> Comm( [(1,2),(2,3),(3,4),(4,5),(5,6)] );
(1,5,6)
gap> Comm(Comm(Comm(Comm((1,2),(2,3)),(3,4)),(4,5)),(5,6));  ## the same
(1,5,6)

5.1-2 IsCommuting
‣ IsCommuting( a, b )( operation )

This function has been transferred from package ResClasses.

It tests whether two elements in a group commute.

gap> D12 := DihedralGroup( 12 );
<pc group of size 12 with 3 generators>
gap> SetName( D12, "D12" ); 
gap> a := D12.1;;  b := D12.2;;  
gap> IsCommuting( a, b );
false

5.1-3 ListOfPowers
‣ ListOfPowers( g, exp )( operation )

This function has been transferred from package RCWA.

The operation ListOfPowers(g,exp) returns the list \([g,g^2,...,g^{exp}]\) of powers of the element \(g\).

gap> ListOfPowers( 2, 20 );
[ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
 32768, 65536, 131072, 262144, 524288, 1048576 ]
gap> ListOfPowers( (1,2,3)(4,5), 12 );
[ (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), (),
 (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), () ]
gap> ListOfPowers( D12.2, 6 );
[ f2, f3, f2*f3, f3^2, f2*f3^2, <identity> of ... ]

5.1-4 GeneratorsAndInverses
‣ GeneratorsAndInverses( G )( operation )

This function has been transferred from package RCWA.

This operation returns a list containing the generators of \(G\) followed by the inverses of these generators.

gap> GeneratorsAndInverses( D12 );
[ f1, f2, f3, f1, f2*f3^2, f3^2 ]
gap> GeneratorsAndInverses( SymmetricGroup(5) );     
[ (1,2,3,4,5), (1,2), (1,5,4,3,2), (1,2) ]

5.1-5 UpperFittingSeries
‣ UpperFittingSeries( G )( attribute )
‣ LowerFittingSeries( G )( attribute )
‣ FittingLength( G )( attribute )

These three functions have been transferred from package ResClasses.

The upper and lower Fitting series and the Fitting length of a solvable group are described here: https://en.wikipedia.org/wiki/Fitting_length.

gap> upp:= UpperFittingSeries( D12 );;
gap> List( upp, StructureDescription );
[ "1", "C6", "D12" ]
gap> low:= LowerFittingSeries( D12 );;
gap> List( low, StructureDescription );
[ "D12", "C3", "1" ]
gap> FittingLength( D12 );
2
gap> S4 := SymmetricGroup( 4 );;
gap> UpperFittingSeries( S4 );
[ Group(()), Group([ (1,2)(3,4), (1,4)(2,3) ]), 
  Group([ (2,4,3), (1,2)(3,4) ]), Group([ (3,4), (2,4,3), (1,2)(3,4) ]) ]
gap> List( last, StructureDescription );
[ "1", "C2 x C2", "A4", "S4" ]
gap> LowerFittingSeries( S4 );
[ Sym( [ 1 .. 4 ] ), Alt( [ 1 .. 4 ] ), Group([ (1,4)(2,3), (1,2)(3,4) ]), 
  Group(()) ]
gap> List( last, StructureDescription );
[ "S4", "A4", "C2 x C2", "1" ]
gap> FittingLength( S4);
3

5.2 Left Cosets for Groups

5.2-1 LeftCoset
‣ LeftCoset( g, U )( operation )

Since GAP uses right actions by default, the library contains the operation RightCoset(U,g) for constructing the right coset \(Ug\) of a subgroup \(U \leq G\) and an element \(g \in G\). It has been noted in the reference manual that, by inverting all the elements in \(Ug\), the left coset \(g^{-1}U\) is obtained.

Just for the sake of completeness, from August 2022 this package provides the operation LeftCoset(g,U) for constructing the left coset \(gU\). Users are strongly recommended to continue to use RightCoset for all serious calculations, since left cosets have a much simpler implementation and do not behave exactly like right cosets.

The methods for left cosets which are provided generally work by converting \(gU\) to \(Ug^{-1}\); applying the equivalent method for right cosets; and, if necessary, converting back again to left cosets.

\(G\) acts on left cosets by OnLeftInverse: \((gU)^{g_0} = g_0^{-1}*(gU) = (g_0^{-1}g)U\).

gap> a4 := Group( (1,2,3), (2,3,4) );; SetName( a4, "a4" );
gap> k4 := Group( (1,2)(3,4), (1,3)(2,4) );; SetName( k4, "k4" );
gap> rc := RightCosets( a4, k4 );
[ RightCoset(k4,()), RightCoset(k4,(2,3,4)), RightCoset(k4,(2,4,3)) ]
gap> lc := LeftCosets( a4, k4 );
[ LeftCoset((),k4), LeftCoset((2,4,3),k4), LeftCoset((2,3,4),k4) ]
gap> AsSet( lc[2] );
[ (2,4,3), (1,2,3), (1,3,4), (1,4,2) ]
gap> LeftCoset( (1,4,2), k4 ) = lc[2];
true
gap> Representative( lc[2] );
(2,4,3)
gap> ActingDomain( lc[2] );
k4
gap> (1,4,3) in lc[3];
true
gap> (1,2,3)*lc[2] = lc[3];
true
gap> lc[2]^(1,3,2) = lc[3];
true

5.2-2 Inverse

The inverse of the left coset \(gU\) is the right coset \(Ug^{-1}\), and conversely. This is an abuse of the attribute Inverse, since the standard requirement, that \(x*x^{-1}\) is an identity, does not hold.

gap> Inverse( rc[3] ) = lc[3];
true
gap> Inverse( lc[2] ) = rc[2];
true

5.3 Functions for group homomorphisms

5.3-1 EpimorphismByGenerators
‣ EpimorphismByGenerators( G, H )( operation )

This function has been transferred from package RCWA.

It constructs a group homomorphism which maps the generators of \(G\) to those of \(H\). Its intended use is when \(G\) is a free group, and a warning is printed when this is not the case. Note that anything may happen if the resulting map is not a homomorphism!

gap> G := Group( (1,2,3), (3,4,5), (5,6,7), (7,8,9) );;
gap> phi := EpimorphismByGenerators( FreeGroup("a","b","c","d"), G );
[ a, b, c, d ] -> [ (1,2,3), (3,4,5), (5,6,7), (7,8,9) ]
gap> PreImagesRepresentativeNC( phi, (1,2,3,4,5,6,7,8,9) );
d*c*b*a
gap> a := G.1;; b := G.2;; c := G.3;; d := G.4;;
gap> d*c*b*a;
(1,2,3,4,5,6,7,8,9)
gap> ## note that it is easy to produce nonsense: 
gap> epi := EpimorphismByGenerators( Group((1,2,3)), Group((8,9)) );
Warning: calling GroupHomomorphismByImagesNC without checks
[ (1,2,3) ] -> [ (8,9) ]
gap> IsGroupHomomorphism( epi );
true
gap> Image( epi, (1,2,3) );                                            
()
gap> Image( epi, (1,3,2) );
(8,9)

5.3-2 Pullback
‣ Pullback( hom1, hom2 )( operation )
‣ PullbackInfo( G )( attribute )

If \(\phi_1 : G_1 \to H\) and \(\phi_2 : G_2 \to H\) are two group homomorphisms with the same range, then their pullback is the subgroup of \(G_1 \times G_2\) consisting of those elements \((g_1,g_2)\) such that \(\phi_1 g_1 = \phi_2 g_2\).

The attribute PullbackInfo of a pullback group P is similar to DirectProductInfo for a direct product of groups. Its value is a record with the following components:

directProduct

the direct product \(G_1 \times G_2\), and

projections

a list with the two projections onto \(G_1\) and \(G_2\).

There are no embeddings in this record, but it is possible to use the embeddings into the direct product, see Embedding (Reference: Embedding).

gap> s4 := Group( (1,2),(2,3),(3,4) );;
gap> s3 := Group( (5,6),(6,7) );;
gap> c3 := Subgroup( s3, [ (5,6,7) ] );;
gap> f := GroupHomomorphismByImages( s4, s3, 
>             [(1,2),(2,3),(3,4)], [(5,6),(6,7),(5,6)] );; 
gap> i := GroupHomomorphismByImages( c3, s3, [(5,6,7)], [(5,6,7)] );; 
gap> Pfi := Pullback( f, i );
Group([ (2,3,4)(5,7,6), (1,2)(3,4) ])
gap> StructureDescription( Pfi );
"A4"
gap> info := PullbackInfo( Pfi );
rec( directProduct := Group([ (1,2), (2,3), (3,4), (5,6,7) ]), 
  projections := [ [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (2,3,4), (1,2)(3,4) ], 
      [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (5,7,6), () ] ] )
gap> g := (1,2,3)(5,6,7);; 
gap> ImageElm( info!.projections[1], g );
(1,2,3)
gap> ImageElm( info!.projections[2], g );
(5,6,7) 
gap> dp := info!.directProduct;; 
gap> a := ImageElm( Embedding( dp, 1 ), (1,4,3) );; 
gap> b := ImageElm( Embedding( dp, 2 ), (5,7,6) );; 
gap> a*b in Pfi;
true

5.3-3 CentralProduct
‣ CentralProduct( G1, G2, Z1, Phi )( operation )
‣ CentralProductInfo( G )( attribute )

This function was added by Thomas Breuer, following discussions with Hongyi Zhao (see https://github.com/gap-packages/hap/issues/73).

Let G1 and G2 be two groups, Z1 be a central subgroup of G1, and Phi be an isomorphism from Z1 to a central subgroup of G2. The central product defined by these arguments is the factor group of the direct product of G1 and G2 by the central subgroup \(\{ (z, (\textit{Phi}(z))^{-1}) : z \in \textit{Z1} \}\).

The attribute CentralProductInfo of a group \(G\) that has been created by CentralProduct is similar to PullbackInfo (5.3-2) for pullback groups. Its value is a record with the following components.

projection

the epimorphism from the direct product of G1 and G2 to \(G\), and

phi

the map Phi.

Note that one can access the direct product as the Source (Reference: Source) value of the projection map, and one can access G1 and G2 as the two embeddings of this direct product, see Embedding (Reference: Embedding).

gap> g1 := DihedralGroup( 8 );
<pc group of size 8 with 3 generators>
gap> c1 := Centre( g1 );
Group([ f3 ])
gap> cp1 := CentralProduct( g1, g1, c1, IdentityMapping( c1 ) );
Group([ f1, f2, f5, f3, f4, f5 ])
gap> IdGroup( cp1 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) );
true
gap> g2 := QuaternionGroup( 8 );
<pc group of size 8 with 3 generators>
gap> c2 := Centre( g2 );
Group([ y2 ])
gap> cp2 := CentralProduct( g2, g2, c2, IdentityMapping( c2 ) );
Group([ f1, f2, f5, f3, f4, f5 ])
gap> IdGroup( cp2 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) );
true
gap> info2 := CentralProductInfo( cp2 );
rec( phi := IdentityMapping( Group([ y2 ]) ), 
  projection := [ f1, f2, f3, f4, f5, f6 ] -> [ f1, f2, f5, f3, f4, f5 ] )
gap> Source( Embedding( Source( info2.projection ), 1 ) ) = g2;
true

5.3-4 IdempotentEndomorphisms
‣ IdempotentEndomorphisms( G )( operation )
‣ IdempotentEndomorphismsData( G )( attribute )
‣ IdempotentEndomorphismsWithImage( genG, R )( operation )

An endomorphism \(f\colon G \to G\) is idempotent if \(f^2 = f\). It has an image \(R \leq G\), is the identity map when restricted to \(R\), and has a kernel \(N\) which has trivial intersection with \(R\) and has size \(|G|/|R|\).

The operation IdempotentEndomorphismsWithImage(genG,R) returns a list of the images of the generating set genG of a group \(G\) under the idempotent endomorphisms with image \(R\).

The attribute IdempotentEndomorphismsData(G) returns a record data with fields data.gens, a fixed generating set for \(G\), and data.images a list of the non-empty outputs of IdempotentEndomorphismsWithImage(genG,R) obtained by iterating over all subgroups \(R\) of \(G\).

The operation IdempotentEndomorphisms(G) returns the list of these mappings obtained using IdempotentEndomorphismsData(G). The first of these is the zero map, the last is the identity.

gap> gens := [ (1,2,3,4), (1,2)(3,4) ];; 
gap> d8 := Group( gens );;
gap> SetName( d8, "d8" );
gap> c2 := Subgroup( d8, [ (2,4) ] );;
gap> SortedList( IdempotentEndomorphismsWithImage( gens, c2 ) );
[ [ (), (2,4) ], [ (2,4), () ] ]
gap> data:= IdempotentEndomorphismsData( d8 );;
gap> data.images[1];
[ [ (), () ] ]
gap> List( data.images, Length );
[ 1, 2, 2, 2, 2, 1 ]
gap> all:= IdempotentEndomorphisms( d8 );;
gap> Length( all );
10
gap> all[1];
[ (1,2,3,4), (1,2)(3,4) ] -> [ (), () ]
gap> Size( Image( all[1] ) );
1
gap> Last( all ) = IdentityMapping( d8 );
true

The quaternion group q8 is an example of a group with a tail: there is only one subgroup in the lattice which covers the identity subgroup. The only idempotent isomorphisms of such groups are the identity mapping and the zero mapping because the only pairs \(N,R\) are the whole group and the identity subgroup.

gap> q8 := QuaternionGroup( 8 );;
gap> IdempotentEndomorphisms( q8 );
[ [ x, y ] -> [ <identity> of ..., <identity> of ... ], [ x, y ] -> [ x, y ] ]

5.3-5 DirectProductOfFunctions
‣ DirectProductOfFunctions( G, H, f1, f2 )( operation )

Given group homomorphisms \(f_1 : G_1 \to G_2\) and \(f_2 : H_1 \to H_2\), this operation return the product homomorphism \(f_1 \times f_2 : G_1 \times G_2 \to H_1 \times H_2\).

gap> c4 := Group( (1,2,3,4) );; 
gap> c2 := Group( (5,6) );; 
gap> f1 := GroupHomomorphismByImages( c4, c2, [(1,2,3,4)], [(5,6)] );;
gap> c3 := Group( (1,2,3) );; 
gap> c6 := Group( (1,2,3,4,5,6) );; 
gap> f2 := GroupHomomorphismByImages( c3, c6, [(1,2,3)], [(1,3,5)(2,4,6)] );; 
gap> c4c3 := DirectProduct( c4, c3 ); 
Group([ (1,2,3,4), (5,6,7) ])
gap> c2c6 := DirectProduct( c2, c6 ); 
Group([ (1,2), (3,4,5,6,7,8) ])
gap> f := DirectProductOfFunctions( c4c3, c2c6, f1, f2 ); 
[ (1,2,3,4), (5,6,7) ] -> [ (1,2), (3,5,7)(4,6,8) ]
gap> ImageElm( f, (1,4,3,2)(5,7,6) ); 
(1,2)(3,7,5)(4,8,6)

5.3-6 DirectProductOfAutomorphismGroups
‣ DirectProductOfAutomorphismGroups( A1, A2 )( operation )

Let \(A_1,A_2\) be groups of automorphism of groups \(G_1,G_2\) respectively. The output of this function is a group \(A_1 \times A_2\) of automorphisms of \(G_1 \times G_2\).

gap> c9 := Group( (1,2,3,4,5,6,7,8,9) );; 
gap> ac9 := AutomorphismGroup( c9 );; 
gap> q8 := QuaternionGroup( IsPermGroup, 8 );;
gap> aq8 := AutomorphismGroup( q8 );;
gap> A := DirectProductOfAutomorphismGroups( ac9, aq8 );
<group with 5 generators>
gap> genA := GeneratorsOfGroup( A );;
gap> G := Source( genA[1] );
Group([ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13)
(14,15,16,17) ])
gap> a := genA[1]*genA[5];  
[ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13)(14,15,16,17) 
 ] -> [ (1,3,5,7,9,2,4,6,8), (10,16,12,14)(11,15,13,17), 
  (10,11,12,13)(14,15,16,17) ]
gap> ImageElm( a, (1,9,8,7,6,5,4,3,2)(10,14,12,16)(11,17,13,15) );
(1,8,6,4,2,9,7,5,3)(10,16,12,14)(11,15,13,17)
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap6.html0000644000000000000000000002022715174515600012177 0ustar00 GAP (Utils) - Chapter 6: Matrices
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

6 Matrices

6.1 Some operations for matrices

6.1-1 DirectSumDecompositionMatrices
‣ DirectSumDecompositionMatrices( M )( operation )

In June 2023 Hongyi Zhao asked in the Forum for a function to implement matrix decomposition into blocks. Such a function was then provided by Pedro García-Sánchez. Hongyi Zhao then requested that the function be added to Utils. What is provided here is a revised version of the original solution, returning a list of decompositions.

This function is a partial inverse to the undocumented library operation DirectSumMat. So if L is the list of diagonal decompositions of a matrix M then each entry in L is a list of matrices, and the direct sum of each of these lists is equal to the original M.

In the following examples, M_6 is an obvious direct sum with 3 blocks. M_4 is an example with three decompositions, while M_8 = M_4 ⊕ M_4 has 16 decompositions (not listed).

gap> M6 := [ [1,2,0,0,0,0], [3,4,0,0,0,0], [5,6,0,0,0,0],                       
>            [0,0,9,0,0,0], [0,0,0,1,2,3], [0,0,0,4,5,6] ];;
gap> Display( M6 );
[ [  1,  2,  0,  0,  0,  0 ],
  [  3,  4,  0,  0,  0,  0 ],
  [  5,  6,  0,  0,  0,  0 ],
  [  0,  0,  9,  0,  0,  0 ],
  [  0,  0,  0,  1,  2,  3 ],
  [  0,  0,  0,  4,  5,  6 ] ]
gap> L6 := DirectSumDecompositionMatrices( M6 );
[ [ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ], [ [ 9 ] ], [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] 
     ] ]

gap> M4 := [ [0,3,0,0], [0,0,0,0], [0,0,0,0], [0,0,4,0] ];;
gap> Display( M4 );
[ [  0,  3,  0,  0 ],
  [  0,  0,  0,  0 ],
  [  0,  0,  0,  0 ],
  [  0,  0,  4,  0 ] ]
gap> L4 := DirectSumDecompositionMatrices( M4 );
[ [ [ [ 0, 3 ] ], [ [ 0, 0 ], [ 0, 0 ], [ 4, 0 ] ] ], 
  [ [ [ 0, 3 ], [ 0, 0 ] ], [ [ 0, 0 ], [ 4, 0 ] ] ], 
  [ [ [ 0, 3 ], [ 0, 0 ], [ 0, 0 ] ], [ [ 4, 0 ] ] ] ]
gap> for L in L4 do 
>        A := DirectSumMat( L );; 
>        if ( A = M4 ) then Print( "yes, A = M4\n" ); fi; 
>    od;
yes, A = M4
yes, A = M4
yes, A = M4

gap> M8 := DirectSumMat( M4, M4 );; 
gap> Display( M8 );
[ [  0,  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,  4,  0,  0,  0,  0,  0 ],
  [  0,  0,  0,  0,  0,  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,  4,  0 ] ]
gap> L8 := DirectSumDecompositionMatrices( M8 );;
gap> Length( L8 ); 
16

The current method does not, however, catch all possible decompositions. In the following example the matrix M_5 has its third row and third column extirely zero, and the only decomposition found has a [0] factor. There are clearly two 2-factor decompositions with a 2-by-3 and a 3-by-2 factor, but these are not found at present.

gap> M5 := [ [1,2,0,0,0], [3,4,0,0,0], [0,0,0,0,0],
>            [0,0,0,6,7], [0,0,0,8,9] ];;
gap> Display(M5);
[ [  1,  2,  0,  0,  0 ],
  [  3,  4,  0,  0,  0 ],
  [  0,  0,  0,  0,  0 ],
  [  0,  0,  0,  6,  7 ],
  [  0,  0,  0,  8,  9 ] ]
gap> L5 := DirectSumDecompositionMatrices( M5 ); 
[ [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 0 ] ], [ [ 6, 7 ], [ 8, 9 ] ] ] ]
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap6.txt0000644000000000000000000001212615174515600012051 0ustar00 6 Matrices 6.1 Some operations for matrices 6.1-1 DirectSumDecompositionMatrices DirectSumDecompositionMatrices( M )  operation In June 2023 Hongyi Zhao asked in the Forum for a function to implement matrix decomposition into blocks. Such a function was then provided by Pedro García-Sánchez. Hongyi Zhao then requested that the function be added to Utils. What is provided here is a revised version of the original solution, returning a list of decompositions. This function is a partial inverse to the undocumented library operation DirectSumMat. So if L is the list of diagonal decompositions of a matrix M then each entry in L is a list of matrices, and the direct sum of each of these lists is equal to the original M. In the following examples, M_6 is an obvious direct sum with 3 blocks. M_4 is an example with three decompositions, while M_8 = M_4 ⊕ M_4 has 16 decompositions (not listed).  Example  gap> M6 := [ [1,2,0,0,0,0], [3,4,0,0,0,0], [5,6,0,0,0,0],  >  [0,0,9,0,0,0], [0,0,0,1,2,3], [0,0,0,4,5,6] ];; gap> Display( M6 ); [ [ 1, 2, 0, 0, 0, 0 ],  [ 3, 4, 0, 0, 0, 0 ],  [ 5, 6, 0, 0, 0, 0 ],  [ 0, 0, 9, 0, 0, 0 ],  [ 0, 0, 0, 1, 2, 3 ],  [ 0, 0, 0, 4, 5, 6 ] ] gap> L6 := DirectSumDecompositionMatrices( M6 ); [ [ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ], [ [ 9 ] ], [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]   ] ]  gap> M4 := [ [0,3,0,0], [0,0,0,0], [0,0,0,0], [0,0,4,0] ];; gap> Display( M4 ); [ [ 0, 3, 0, 0 ],  [ 0, 0, 0, 0 ],  [ 0, 0, 0, 0 ],  [ 0, 0, 4, 0 ] ] gap> L4 := DirectSumDecompositionMatrices( M4 ); [ [ [ [ 0, 3 ] ], [ [ 0, 0 ], [ 0, 0 ], [ 4, 0 ] ] ],   [ [ [ 0, 3 ], [ 0, 0 ] ], [ [ 0, 0 ], [ 4, 0 ] ] ],   [ [ [ 0, 3 ], [ 0, 0 ], [ 0, 0 ] ], [ [ 4, 0 ] ] ] ] gap> for L in L4 do  >  A := DirectSumMat( L );;  >  if ( A = M4 ) then Print( "yes, A = M4\n" ); fi;  >  od; yes, A = M4 yes, A = M4 yes, A = M4  gap> M8 := DirectSumMat( M4, M4 );;  gap> Display( M8 ); [ [ 0, 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, 4, 0, 0, 0, 0, 0 ],  [ 0, 0, 0, 0, 0, 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, 4, 0 ] ] gap> L8 := DirectSumDecompositionMatrices( M8 );; gap> Length( L8 );  16  The current method does not, however, catch all possible decompositions. In the following example the matrix M_5 has its third row and third column extirely zero, and the only decomposition found has a [0] factor. There are clearly two 2-factor decompositions with a 2-by-3 and a 3-by-2 factor, but these are not found at present.  Example  gap> M5 := [ [1,2,0,0,0], [3,4,0,0,0], [0,0,0,0,0], >  [0,0,0,6,7], [0,0,0,8,9] ];; gap> Display(M5); [ [ 1, 2, 0, 0, 0 ],  [ 3, 4, 0, 0, 0 ],  [ 0, 0, 0, 0, 0 ],  [ 0, 0, 0, 6, 7 ],  [ 0, 0, 0, 8, 9 ] ] gap> L5 := DirectSumDecompositionMatrices( M5 );  [ [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 0 ] ], [ [ 6, 7 ], [ 8, 9 ] ] ] ]  utils-0.94/doc/chap6_mj.html0000644000000000000000000002073215174515600012666 0ustar00 GAP (Utils) - Chapter 6: Matrices
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

6 Matrices

6.1 Some operations for matrices

6.1-1 DirectSumDecompositionMatrices
‣ DirectSumDecompositionMatrices( M )( operation )

In June 2023 Hongyi Zhao asked in the Forum for a function to implement matrix decomposition into blocks. Such a function was then provided by Pedro García-Sánchez. Hongyi Zhao then requested that the function be added to Utils. What is provided here is a revised version of the original solution, returning a list of decompositions.

This function is a partial inverse to the undocumented library operation DirectSumMat. So if \(L\) is the list of diagonal decompositions of a matrix \(M\) then each entry in \(L\) is a list of matrices, and the direct sum of each of these lists is equal to the original \(M\).

In the following examples, \(M_6\) is an obvious direct sum with \(3\) blocks. \(M_4\) is an example with three decompositions, while \(M_8 = M_4 \oplus M_4\) has \(16\) decompositions (not listed).

gap> M6 := [ [1,2,0,0,0,0], [3,4,0,0,0,0], [5,6,0,0,0,0],                       
>            [0,0,9,0,0,0], [0,0,0,1,2,3], [0,0,0,4,5,6] ];;
gap> Display( M6 );
[ [  1,  2,  0,  0,  0,  0 ],
  [  3,  4,  0,  0,  0,  0 ],
  [  5,  6,  0,  0,  0,  0 ],
  [  0,  0,  9,  0,  0,  0 ],
  [  0,  0,  0,  1,  2,  3 ],
  [  0,  0,  0,  4,  5,  6 ] ]
gap> L6 := DirectSumDecompositionMatrices( M6 );
[ [ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ], [ [ 9 ] ], [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] 
     ] ]

gap> M4 := [ [0,3,0,0], [0,0,0,0], [0,0,0,0], [0,0,4,0] ];;
gap> Display( M4 );
[ [  0,  3,  0,  0 ],
  [  0,  0,  0,  0 ],
  [  0,  0,  0,  0 ],
  [  0,  0,  4,  0 ] ]
gap> L4 := DirectSumDecompositionMatrices( M4 );
[ [ [ [ 0, 3 ] ], [ [ 0, 0 ], [ 0, 0 ], [ 4, 0 ] ] ], 
  [ [ [ 0, 3 ], [ 0, 0 ] ], [ [ 0, 0 ], [ 4, 0 ] ] ], 
  [ [ [ 0, 3 ], [ 0, 0 ], [ 0, 0 ] ], [ [ 4, 0 ] ] ] ]
gap> for L in L4 do 
>        A := DirectSumMat( L );; 
>        if ( A = M4 ) then Print( "yes, A = M4\n" ); fi; 
>    od;
yes, A = M4
yes, A = M4
yes, A = M4

gap> M8 := DirectSumMat( M4, M4 );; 
gap> Display( M8 );
[ [  0,  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,  4,  0,  0,  0,  0,  0 ],
  [  0,  0,  0,  0,  0,  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,  4,  0 ] ]
gap> L8 := DirectSumDecompositionMatrices( M8 );;
gap> Length( L8 ); 
16

The current method does not, however, catch all possible decompositions. In the following example the matrix \(M_5\) has its third row and third column extirely zero, and the only decomposition found has a \([0]\) factor. There are clearly two \(2\)-factor decompositions with a \(2\)-by-\(3\) and a \(3\)-by-\(2\) factor, but these are not found at present.

gap> M5 := [ [1,2,0,0,0], [3,4,0,0,0], [0,0,0,0,0],
>            [0,0,0,6,7], [0,0,0,8,9] ];;
gap> Display(M5);
[ [  1,  2,  0,  0,  0 ],
  [  3,  4,  0,  0,  0 ],
  [  0,  0,  0,  0,  0 ],
  [  0,  0,  0,  6,  7 ],
  [  0,  0,  0,  8,  9 ] ]
gap> L5 := DirectSumDecompositionMatrices( M5 ); 
[ [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 0 ] ], [ [ 6, 7 ], [ 8, 9 ] ] ] ]
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap7.html0000644000000000000000000002670615174515600012210 0ustar00 GAP (Utils) - Chapter 7: Iterators
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

7 Iterators

7.1 Some iterators for groups and their isomorphisms

The motivation for adding these operations is partly to give a simple example of an iterator for a list that does not yet exist, and need not be created.

7.1-1 AllIsomorphismsIterator
‣ AllIsomorphismsIterator( G, H )( operation )
‣ AllIsomorphismsNumber( G, H )( operation )
‣ AllIsomorphisms( G, H )( operation )

The main GAP library contains functions producing complete lists of group homomorphisms such as AllHomomorphisms; AllEndomorphisms and AllAutomorphisms. Here we add the missing AllIsomorphisms(G,H) for a list of isomorphisms from G to H. The method is simple -- find one isomorphism G -> H and compose this with all the automorphisms of G. In all these cases it may not be desirable to construct a list of homomorphisms, but just implement an iterator, and that is what is done here. The operation AllIsomorphismsNumber returns the number of isomorphisms iterated over (this is, of course, just the order of the automorphisms group). The operation AllIsomorphisms produces the list or isomorphisms.

gap> G := SmallGroup( 6,1);; 
gap> iter := AllIsomorphismsIterator( G, s3 );;
gap> NextIterator( iter );
[ f1, f2 ] -> [ (6,7), (5,6,7) ]
gap> n := AllIsomorphismsNumber( G, s3 );
6
gap> AllIsomorphisms( G, s3 );
[ [ f1, f2 ] -> [ (6,7), (5,6,7) ], [ f1, f2 ] -> [ (5,7), (5,6,7) ], 
  [ f1, f2 ] -> [ (5,6), (5,7,6) ], [ f1, f2 ] -> [ (6,7), (5,7,6) ], 
  [ f1, f2 ] -> [ (5,7), (5,7,6) ], [ f1, f2 ] -> [ (5,6), (5,6,7) ] ]
gap> iter := AllIsomorphismsIterator( G, s3 );;
gap> for h in iter do Print( ImageElm( h, G.1 ) = (6,7), ", " ); od;
true, false, false, true, false, false,

7.1-2 AllSubgroupsIterator
‣ AllSubgroupsIterator( G )( operation )

The manual entry for the operation AllSubgroups states that it is only intended to be used on small examples in a classroom situation. Access to all subgroups was required by the XMod package, so this iterator was introduced here. It used the operations LatticeSubgroups(G) and ConjugacyClassesSubgroups(lat), and then iterates over the entries in these classes.

gap> c3c3 := Group( (1,2,3), (4,5,6) );; 
gap> iter := AllSubgroupsIterator( c3c3 );
<iterator>
gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od;
Group( () )
Group( [ (4,5,6) ] )
Group( [ (1,2,3) ] )
Group( [ (1,2,3)(4,5,6) ] )
Group( [ (1,3,2)(4,5,6) ] )
Group( [ (4,5,6), (1,2,3) ] )

7.2 Operations on iterators

This section considers ways of producing an iterator from one or more iterators. It may be that operations equivalent to these are available elsewhere in the library -- if so, the ones here can be removed in due course.

7.2-1 CartesianIterator
‣ CartesianIterator( iter1, iter2 )( operation )

This iterator returns all pairs [x,y] where x is the output of a first iterator and y is the output of a second iterator.

gap> it1 := Iterator( [ 1, 2, 3 ] );;
gap> it2 := Iterator( [ 4, 5, 6 ] );;
gap> iter := CartesianIterator( it1, it2 );;
gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od;
[ 1, 4 ]
[ 1, 5 ]
[ 1, 6 ]
[ 2, 4 ]
[ 2, 5 ]
[ 2, 6 ]
[ 3, 4 ]
[ 3, 5 ]
[ 3, 6 ]

7.2-2 UnorderedPairsIterator
‣ UnorderedPairsIterator( iter )( operation )

This operation returns pairs [x,y] where x,y are output from a given iterator iter. Unlike the output from CartesianIterator(iter,iter), unordered pairs are returned. In the case L = [1,2,3,...] the pairs are ordered as [1,1],[1,2],[2,2],[1,3],[2,3],[3,3],....

gap> L := [6,7,8,9];;
gap> iterL := IteratorList( L );; 
gap> pairsL := UnorderedPairsIterator( iterL );;                              
gap> while not IsDoneIterator(pairsL) do Print(NextIterator(pairsL),"\n"); od;
[ 6, 6 ]
[ 6, 7 ]
[ 7, 7 ]
[ 6, 8 ]
[ 7, 8 ]
[ 8, 8 ]
[ 6, 9 ]
[ 7, 9 ]
[ 8, 9 ]
[ 9, 9 ]
gap> iter4 := IteratorList( [ 4 ] );
<iterator>
gap> pairs4 := UnorderedPairsIterator(iter4);
<iterator>
gap> NextIterator( pairs4 );
[ 4, 4 ]
gap> IsDoneIterator( pairs4 );
true
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap7.txt0000644000000000000000000001540315174515600012053 0ustar00 7 Iterators 7.1 Some iterators for groups and their isomorphisms The motivation for adding these operations is partly to give a simple example of an iterator for a list that does not yet exist, and need not be created. 7.1-1 AllIsomorphismsIterator AllIsomorphismsIterator( G, H )  operation AllIsomorphismsNumber( G, H )  operation AllIsomorphisms( G, H )  operation The main GAP library contains functions producing complete lists of group homomorphisms such as AllHomomorphisms; AllEndomorphisms and AllAutomorphisms. Here we add the missing AllIsomorphisms(G,H) for a list of isomorphisms from G to H. The method is simple -- find one isomorphism G -> H and compose this with all the automorphisms of G. In all these cases it may not be desirable to construct a list of homomorphisms, but just implement an iterator, and that is what is done here. The operation AllIsomorphismsNumber returns the number of isomorphisms iterated over (this is, of course, just the order of the automorphisms group). The operation AllIsomorphisms produces the list or isomorphisms.  Example  gap> G := SmallGroup( 6,1);;  gap> iter := AllIsomorphismsIterator( G, s3 );; gap> NextIterator( iter ); [ f1, f2 ] -> [ (6,7), (5,6,7) ] gap> n := AllIsomorphismsNumber( G, s3 ); 6 gap> AllIsomorphisms( G, s3 ); [ [ f1, f2 ] -> [ (6,7), (5,6,7) ], [ f1, f2 ] -> [ (5,7), (5,6,7) ],   [ f1, f2 ] -> [ (5,6), (5,7,6) ], [ f1, f2 ] -> [ (6,7), (5,7,6) ],   [ f1, f2 ] -> [ (5,7), (5,7,6) ], [ f1, f2 ] -> [ (5,6), (5,6,7) ] ] gap> iter := AllIsomorphismsIterator( G, s3 );; gap> for h in iter do Print( ImageElm( h, G.1 ) = (6,7), ", " ); od; true, false, false, true, false, false,  7.1-2 AllSubgroupsIterator AllSubgroupsIterator( G )  operation The manual entry for the operation AllSubgroups states that it is only intended to be used on small examples in a classroom situation. Access to all subgroups was required by the XMod package, so this iterator was introduced here. It used the operations LatticeSubgroups(G) and ConjugacyClassesSubgroups(lat), and then iterates over the entries in these classes.  Example  gap> c3c3 := Group( (1,2,3), (4,5,6) );;  gap> iter := AllSubgroupsIterator( c3c3 );  gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od; Group( () ) Group( [ (4,5,6) ] ) Group( [ (1,2,3) ] ) Group( [ (1,2,3)(4,5,6) ] ) Group( [ (1,3,2)(4,5,6) ] ) Group( [ (4,5,6), (1,2,3) ] )  7.2 Operations on iterators This section considers ways of producing an iterator from one or more iterators. It may be that operations equivalent to these are available elsewhere in the library -- if so, the ones here can be removed in due course. 7.2-1 CartesianIterator CartesianIterator( iter1, iter2 )  operation This iterator returns all pairs [x,y] where x is the output of a first iterator and y is the output of a second iterator.  Example  gap> it1 := Iterator( [ 1, 2, 3 ] );; gap> it2 := Iterator( [ 4, 5, 6 ] );; gap> iter := CartesianIterator( it1, it2 );; gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od; [ 1, 4 ] [ 1, 5 ] [ 1, 6 ] [ 2, 4 ] [ 2, 5 ] [ 2, 6 ] [ 3, 4 ] [ 3, 5 ] [ 3, 6 ]  7.2-2 UnorderedPairsIterator UnorderedPairsIterator( iter )  operation This operation returns pairs [x,y] where x,y are output from a given iterator iter. Unlike the output from CartesianIterator(iter,iter), unordered pairs are returned. In the case L = [1,2,3,...] the pairs are ordered as [1,1],[1,2],[2,2],[1,3],[2,3],[3,3],....  Example  gap> L := [6,7,8,9];; gap> iterL := IteratorList( L );;  gap> pairsL := UnorderedPairsIterator( iterL );;  gap> while not IsDoneIterator(pairsL) do Print(NextIterator(pairsL),"\n"); od; [ 6, 6 ] [ 6, 7 ] [ 7, 7 ] [ 6, 8 ] [ 7, 8 ] [ 8, 8 ] [ 6, 9 ] [ 7, 9 ] [ 8, 9 ] [ 9, 9 ] gap> iter4 := IteratorList( [ 4 ] );  gap> pairs4 := UnorderedPairsIterator(iter4);  gap> NextIterator( pairs4 ); [ 4, 4 ] gap> IsDoneIterator( pairs4 ); true  utils-0.94/doc/chap7_mj.html0000644000000000000000000002740215174515600012670 0ustar00 GAP (Utils) - Chapter 7: Iterators
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

7 Iterators

7.1 Some iterators for groups and their isomorphisms

The motivation for adding these operations is partly to give a simple example of an iterator for a list that does not yet exist, and need not be created.

7.1-1 AllIsomorphismsIterator
‣ AllIsomorphismsIterator( G, H )( operation )
‣ AllIsomorphismsNumber( G, H )( operation )
‣ AllIsomorphisms( G, H )( operation )

The main GAP library contains functions producing complete lists of group homomorphisms such as AllHomomorphisms; AllEndomorphisms and AllAutomorphisms. Here we add the missing AllIsomorphisms(G,H) for a list of isomorphisms from \(G\) to \(H\). The method is simple -- find one isomorphism \(G \to H\) and compose this with all the automorphisms of \(G\). In all these cases it may not be desirable to construct a list of homomorphisms, but just implement an iterator, and that is what is done here. The operation AllIsomorphismsNumber returns the number of isomorphisms iterated over (this is, of course, just the order of the automorphisms group). The operation AllIsomorphisms produces the list or isomorphisms.

gap> G := SmallGroup( 6,1);; 
gap> iter := AllIsomorphismsIterator( G, s3 );;
gap> NextIterator( iter );
[ f1, f2 ] -> [ (6,7), (5,6,7) ]
gap> n := AllIsomorphismsNumber( G, s3 );
6
gap> AllIsomorphisms( G, s3 );
[ [ f1, f2 ] -> [ (6,7), (5,6,7) ], [ f1, f2 ] -> [ (5,7), (5,6,7) ], 
  [ f1, f2 ] -> [ (5,6), (5,7,6) ], [ f1, f2 ] -> [ (6,7), (5,7,6) ], 
  [ f1, f2 ] -> [ (5,7), (5,7,6) ], [ f1, f2 ] -> [ (5,6), (5,6,7) ] ]
gap> iter := AllIsomorphismsIterator( G, s3 );;
gap> for h in iter do Print( ImageElm( h, G.1 ) = (6,7), ", " ); od;
true, false, false, true, false, false,

7.1-2 AllSubgroupsIterator
‣ AllSubgroupsIterator( G )( operation )

The manual entry for the operation AllSubgroups states that it is only intended to be used on small examples in a classroom situation. Access to all subgroups was required by the XMod package, so this iterator was introduced here. It used the operations LatticeSubgroups(G) and ConjugacyClassesSubgroups(lat), and then iterates over the entries in these classes.

gap> c3c3 := Group( (1,2,3), (4,5,6) );; 
gap> iter := AllSubgroupsIterator( c3c3 );
<iterator>
gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od;
Group( () )
Group( [ (4,5,6) ] )
Group( [ (1,2,3) ] )
Group( [ (1,2,3)(4,5,6) ] )
Group( [ (1,3,2)(4,5,6) ] )
Group( [ (4,5,6), (1,2,3) ] )

7.2 Operations on iterators

This section considers ways of producing an iterator from one or more iterators. It may be that operations equivalent to these are available elsewhere in the library -- if so, the ones here can be removed in due course.

7.2-1 CartesianIterator
‣ CartesianIterator( iter1, iter2 )( operation )

This iterator returns all pairs \([x,y]\) where \(x\) is the output of a first iterator and \(y\) is the output of a second iterator.

gap> it1 := Iterator( [ 1, 2, 3 ] );;
gap> it2 := Iterator( [ 4, 5, 6 ] );;
gap> iter := CartesianIterator( it1, it2 );;
gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od;
[ 1, 4 ]
[ 1, 5 ]
[ 1, 6 ]
[ 2, 4 ]
[ 2, 5 ]
[ 2, 6 ]
[ 3, 4 ]
[ 3, 5 ]
[ 3, 6 ]

7.2-2 UnorderedPairsIterator
‣ UnorderedPairsIterator( iter )( operation )

This operation returns pairs \([x,y]\) where \(x,y\) are output from a given iterator iter. Unlike the output from CartesianIterator(iter,iter), unordered pairs are returned. In the case \(L = [1,2,3,\ldots]\) the pairs are ordered as \([1,1],[1,2],[2,2],[1,3],[2,3],[3,3],\ldots\).

gap> L := [6,7,8,9];;
gap> iterL := IteratorList( L );; 
gap> pairsL := UnorderedPairsIterator( iterL );;                              
gap> while not IsDoneIterator(pairsL) do Print(NextIterator(pairsL),"\n"); od;
[ 6, 6 ]
[ 6, 7 ]
[ 7, 7 ]
[ 6, 8 ]
[ 7, 8 ]
[ 8, 8 ]
[ 6, 9 ]
[ 7, 9 ]
[ 8, 9 ]
[ 9, 9 ]
gap> iter4 := IteratorList( [ 4 ] );
<iterator>
gap> pairs4 := UnorderedPairsIterator(iter4);
<iterator>
gap> NextIterator( pairs4 );
[ 4, 4 ]
gap> IsDoneIterator( pairs4 );
true
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap8.html0000644000000000000000000002531215174515600012201 0ustar00 GAP (Utils) - Chapter 8: Records
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

8 Records

8.1 Functions for records

8.1-1 AssignGlobals
‣ AssignGlobals( rec )( function )

This function has been transferred from package RCWA.

It assigns the record components of rec to global variables with the same names.

gap> r := rec( a := 1, b := 2, c := 3 );;                                      
gap> AssignGlobals( r );
The following global variables have been assigned:
[ "a", "b", "c" ]
gap> [a,b,c];
[ 1, 2, 3 ]

8.2 Option records for functions

8.2-1 OptionRecordWithDefaults
‣ OptionRecordWithDefaults( defaults, useroptions )( function )

This functions has been transferred by Chris Jefferson from other packages. It simplifies the handling of records which are intended to be used for expressing configuration options. defaults represents the "default record", and useroptions lets the user give new values for values in defaults.

The function returns a record with the same component names as defaults and which has the same values as defaults, except for those component names in useroptions, where the values in useroptions are used instead. An error is given if useroptions contains any component names not in defaults. If useroptions is an empty list it is treated as an empty record, and if useroptions is a list of length 1 containing a record, this record is used as useroptions.

gap> defaults := rec( a := 1, b := 2, c := 3 );;
gap> OptionRecordWithDefaults( defaults, rec( a := 6) );
rec( a := 6, b := 2, c := 3 )
gap> OptionRecordWithDefaults( defaults, rec( b := 7, c := 8 ) );
rec( a := 1, b := 7, c := 8 )
gap> OptionRecordWithDefaults( defaults, [ ] );
rec( a := 1, b := 2, c := 3 )
gap> OptionRecordWithDefaults( defaults, [ rec( c := 8 ) ] );
rec( a := 1, b := 2, c := 8 )
gap> OptionRecordWithDefaults( defaults, rec( d := 9 ) );
Error, Unknown option: d
gap> OptionRecordWithDefaults( defaults, [ rec( b := 7 ), rec( c := 8 ) ] );
Error, Too many arguments for function
gap> OptionRecordWithDefaults( defaults, [6,7,8] );
Error, Too many arguments for function

This function is designed to support functions with optional arguments given as a variable record, of the form function(x,y,options...).

In the following, very contrived, example function, PrintDimensions, the defaults are given by the variable order which takes values h, w and d having default values 1, 2 and 3. If there is a second argument, then OptionRecordWithDefaults( order, arg[2] ); is used to change the values. These three values then determine the order in which the three dimensions are printed using a SortParallel command.

gap> PrintDimensions := function( arg )
>    local nargs, dim, order, V, L, len, K, i;
>    nargs := Length( arg );
>    dim := [ arg[1]!.height, arg[1]!.width, arg[1]!.depth ];
>    order := rec( h := 1, w := 2, d := 3 );
>    V := [ "height", "width", "depth" ];
>    if ( nargs > 1 ) and IsRecord( arg[2] ) then
>        order := OptionRecordWithDefaults( order, arg[2] );
>    fi;
>    L := [ order!.h, order!.w, order!.d ];
>    len := Length( L );
>    K := [ 1..len ];
>    SortParallel( L, K );
>    Print( "dimensions: " );
>    Print( V[K[1]], " = ", dim[K[1]], ", " );
>    Print( V[K[2]], " = ", dim[K[2]], ", " );
>    Print( V[K[3]], " = ", dim[K[3]], "\n" );
> end;;

In the example below the first call to PrintDimensions has just one parameter, mydim, so the default order is used. In the second call, alternate values for h, w and d are given, causing the width to be printed first, and then the depth and height.

gap> mydim := rec( height := 45, width := 31, depth := 17 ); 
rec( depth := 17, height := 45, width := 31 )
gap> PrintDimensions( mydim );
dimensions: height = 45, width = 31, depth = 17
gap> PrintDimensions( mydim, rec( h:=3, w:=1, d:=2 ) );
dimensions: width = 31, depth = 17, height = 45
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap8.txt0000644000000000000000000001422315174515600012053 0ustar00 8 Records 8.1 Functions for records 8.1-1 AssignGlobals AssignGlobals( rec )  function This function has been transferred from package RCWA. It assigns the record components of rec to global variables with the same names.  Example  gap> r := rec( a := 1, b := 2, c := 3 );;  gap> AssignGlobals( r ); The following global variables have been assigned: [ "a", "b", "c" ] gap> [a,b,c]; [ 1, 2, 3 ]  8.2 Option records for functions 8.2-1 OptionRecordWithDefaults OptionRecordWithDefaults( defaults, useroptions )  function This functions has been transferred by Chris Jefferson from other packages. It simplifies the handling of records which are intended to be used for expressing configuration options. defaults represents the "default record", and useroptions lets the user give new values for values in defaults. The function returns a record with the same component names as defaults and which has the same values as defaults, except for those component names in useroptions, where the values in useroptions are used instead. An error is given if useroptions contains any component names not in defaults. If useroptions is an empty list it is treated as an empty record, and if useroptions is a list of length 1 containing a record, this record is used as useroptions.  Example  gap> defaults := rec( a := 1, b := 2, c := 3 );; gap> OptionRecordWithDefaults( defaults, rec( a := 6) ); rec( a := 6, b := 2, c := 3 ) gap> OptionRecordWithDefaults( defaults, rec( b := 7, c := 8 ) ); rec( a := 1, b := 7, c := 8 ) gap> OptionRecordWithDefaults( defaults, [ ] ); rec( a := 1, b := 2, c := 3 ) gap> OptionRecordWithDefaults( defaults, [ rec( c := 8 ) ] ); rec( a := 1, b := 2, c := 8 ) gap> OptionRecordWithDefaults( defaults, rec( d := 9 ) ); Error, Unknown option: d gap> OptionRecordWithDefaults( defaults, [ rec( b := 7 ), rec( c := 8 ) ] ); Error, Too many arguments for function gap> OptionRecordWithDefaults( defaults, [6,7,8] ); Error, Too many arguments for function  This function is designed to support functions with optional arguments given as a variable record, of the form function(x,y,options...). In the following, very contrived, example function, PrintDimensions, the defaults are given by the variable order which takes values h, w and d having default values 1, 2 and 3. If there is a second argument, then OptionRecordWithDefaults( order, arg[2] ); is used to change the values. These three values then determine the order in which the three dimensions are printed using a SortParallel command.  Example  gap> PrintDimensions := function( arg ) >  local nargs, dim, order, V, L, len, K, i; >  nargs := Length( arg ); >  dim := [ arg[1]!.height, arg[1]!.width, arg[1]!.depth ]; >  order := rec( h := 1, w := 2, d := 3 ); >  V := [ "height", "width", "depth" ]; >  if ( nargs > 1 ) and IsRecord( arg[2] ) then >  order := OptionRecordWithDefaults( order, arg[2] ); >  fi; >  L := [ order!.h, order!.w, order!.d ]; >  len := Length( L ); >  K := [ 1..len ]; >  SortParallel( L, K ); >  Print( "dimensions: " ); >  Print( V[K[1]], " = ", dim[K[1]], ", " ); >  Print( V[K[2]], " = ", dim[K[2]], ", " ); >  Print( V[K[3]], " = ", dim[K[3]], "\n" ); > end;;  In the example below the first call to PrintDimensions has just one parameter, mydim, so the default order is used. In the second call, alternate values for h, w and d are given, causing the width to be printed first, and then the depth and height.  Example  gap> mydim := rec( height := 45, width := 31, depth := 17 );  rec( depth := 17, height := 45, width := 31 ) gap> PrintDimensions( mydim ); dimensions: height = 45, width = 31, depth = 17 gap> PrintDimensions( mydim, rec( h:=3, w:=1, d:=2 ) ); dimensions: width = 31, depth = 17, height = 45  utils-0.94/doc/chap8_mj.html0000644000000000000000000002574015174515600012674 0ustar00 GAP (Utils) - Chapter 8: Records
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

8 Records

8.1 Functions for records

8.1-1 AssignGlobals
‣ AssignGlobals( rec )( function )

This function has been transferred from package RCWA.

It assigns the record components of rec to global variables with the same names.

gap> r := rec( a := 1, b := 2, c := 3 );;                                      
gap> AssignGlobals( r );
The following global variables have been assigned:
[ "a", "b", "c" ]
gap> [a,b,c];
[ 1, 2, 3 ]

8.2 Option records for functions

8.2-1 OptionRecordWithDefaults
‣ OptionRecordWithDefaults( defaults, useroptions )( function )

This functions has been transferred by Chris Jefferson from other packages. It simplifies the handling of records which are intended to be used for expressing configuration options. defaults represents the "default record", and useroptions lets the user give new values for values in defaults.

The function returns a record with the same component names as defaults and which has the same values as defaults, except for those component names in useroptions, where the values in useroptions are used instead. An error is given if useroptions contains any component names not in defaults. If useroptions is an empty list it is treated as an empty record, and if useroptions is a list of length \(1\) containing a record, this record is used as useroptions.

gap> defaults := rec( a := 1, b := 2, c := 3 );;
gap> OptionRecordWithDefaults( defaults, rec( a := 6) );
rec( a := 6, b := 2, c := 3 )
gap> OptionRecordWithDefaults( defaults, rec( b := 7, c := 8 ) );
rec( a := 1, b := 7, c := 8 )
gap> OptionRecordWithDefaults( defaults, [ ] );
rec( a := 1, b := 2, c := 3 )
gap> OptionRecordWithDefaults( defaults, [ rec( c := 8 ) ] );
rec( a := 1, b := 2, c := 8 )
gap> OptionRecordWithDefaults( defaults, rec( d := 9 ) );
Error, Unknown option: d
gap> OptionRecordWithDefaults( defaults, [ rec( b := 7 ), rec( c := 8 ) ] );
Error, Too many arguments for function
gap> OptionRecordWithDefaults( defaults, [6,7,8] );
Error, Too many arguments for function

This function is designed to support functions with optional arguments given as a variable record, of the form function(x,y,options...).

In the following, very contrived, example function, PrintDimensions, the defaults are given by the variable order which takes values h, w and d having default values \(1\), \(2\) and \(3\). If there is a second argument, then OptionRecordWithDefaults( order, arg[2] ); is used to change the values. These three values then determine the order in which the three dimensions are printed using a SortParallel command.

gap> PrintDimensions := function( arg )
>    local nargs, dim, order, V, L, len, K, i;
>    nargs := Length( arg );
>    dim := [ arg[1]!.height, arg[1]!.width, arg[1]!.depth ];
>    order := rec( h := 1, w := 2, d := 3 );
>    V := [ "height", "width", "depth" ];
>    if ( nargs > 1 ) and IsRecord( arg[2] ) then
>        order := OptionRecordWithDefaults( order, arg[2] );
>    fi;
>    L := [ order!.h, order!.w, order!.d ];
>    len := Length( L );
>    K := [ 1..len ];
>    SortParallel( L, K );
>    Print( "dimensions: " );
>    Print( V[K[1]], " = ", dim[K[1]], ", " );
>    Print( V[K[2]], " = ", dim[K[2]], ", " );
>    Print( V[K[3]], " = ", dim[K[3]], "\n" );
> end;;

In the example below the first call to PrintDimensions has just one parameter, mydim, so the default order is used. In the second call, alternate values for h, w and d are given, causing the width to be printed first, and then the depth and height.

gap> mydim := rec( height := 45, width := 31, depth := 17 ); 
rec( depth := 17, height := 45, width := 31 )
gap> PrintDimensions( mydim );
dimensions: height = 45, width = 31, depth = 17
gap> PrintDimensions( mydim, rec( h:=3, w:=1, d:=2 ) );
dimensions: width = 31, depth = 17, height = 45
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap9.html0000644000000000000000000002624515174515600012210 0ustar00 GAP (Utils) - Chapter 9: Web Downloads
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

9 Web Downloads

The Download operation has been written by Thomas Breuer, incorporating a number of suggestions from Max Horn, for version 0.77 of Utils. It implements downloading a file from within GAP. It can use the IO or curlInterface packages, or wget or curl, if installed, and it can be extended with other download methods quite easily. It is envisaged that, once other packages have started to use it, and any problems have been addressed, that the functions will be transferred to the main GAP library.

9.1 Functions for downloading files from the web

9.1-1 Download
‣ Download( url[, opt] )( function )

This function downloads the file with the web address url, which must be a string.

The result is a record which has at least the component success, with value true if the download was successful and false otherwise. In the former case, the component result is bound, whose value is a string that contains the contents of the downloaded file. In the latter case, the component error is bound, whose value is a string that describes the problem.

The function calls the methods stored in the global list Download_Methods until one of them is successful. Currently there are methods based on the GAP functions DownloadURL (curl: DownloadURL) and SingleHTTPRequest (IO: SingleHTTPRequest), and methods based on the external programs wget and curl.

An optional record opt can be given. The following components are supported.

maxTime

If this component is bound then its value must be a nonnegative integer n, meaning that the function gives up after n seconds.

A zero value of n means that no timeout is set, the method will never give up in this case.

The default for n is given by the value of the user preference DownloadMaxTime (see 9.1-3).

target

If this component is bound then its value must be a string that is a local filename, and the function writes the downloaded contents to this file; the returned record does not have a result component in this case.

verifyCert

If this component is bound and has the value false then those download methods that are based on curl or wget will omit the check of the server's certificate.

The same effect is achieved for all Download calls by setting the user preference DownloadVerifyCertificate (see 9.1-2) to false and omitting the verifyCert component from opt.

gap> url:= "https://www.gap-system.org/index.html";;
gap> res1:= Download( url );;
gap> res1.success;
true
gap> IsBound( res1.result ) and IsString( res1.result );
true
gap> res2:= Download( Concatenation( url, "xxx" ) );;
gap> res2.success;
false
gap> IsBound( res2.error ) and IsString( res2.error );
true

9.1-2 User preference DownloadVerifyCertificate

The value true (the default) means that the server's certificate is checked in calls of Download (9.1-1), such that nothing gets downloaded if the certificate is invalid.

If the value is false then download methods are supposed to omit the check of the server's certificate (this may not be supported by all download methods).

One can set the value of the preference to be val via SetUserPreference (Reference: SetUserPreference), by calling SetUserPreference( "utils", "DownloadVerifyCertificate", val ), and access the current value via UserPreference (Reference: UserPreference), by calling UserPreference( "utils", "DownloadVerifyCertificate" ).

We recommend leaving this preference at its default value true. Sometimes it can be necessary to change it, e.g. to work around issues with old operating systems which may not be able to correctly verify new certificates. In general it is better to update such a system, but if that is not an option, then disabling certificate checks may be a good last resort.

9.1-3 User preference DownloadMaxTime

The value 0 (the default) means that no timeout is set in calls of Download (9.1-1). If the value is a positive integer n then those download methods that support a timeout will give up after n seconds.

One can set the value of the preference to be val via SetUserPreference (Reference: SetUserPreference), by calling SetUserPreference( "utils", "DownloadMaxTime", val ), and access the current value via UserPreference (Reference: UserPreference), by calling UserPreference( "utils", "DownloadMaxTime" ).

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chap9.txt0000644000000000000000000001435215174515600012057 0ustar00 9 Web Downloads The Download operation has been written by Thomas Breuer, incorporating a number of suggestions from Max Horn, for version 0.77 of Utils. It implements downloading a file from within GAP. It can use the IO or curlInterface packages, or wget or curl, if installed, and it can be extended with other download methods quite easily. It is envisaged that, once other packages have started to use it, and any problems have been addressed, that the functions will be transferred to the main GAP library. 9.1 Functions for downloading files from the web 9.1-1 Download Download( url[, opt] )  function This function downloads the file with the web address url, which must be a string. The result is a record which has at least the component success, with value true if the download was successful and false otherwise. In the former case, the component result is bound, whose value is a string that contains the contents of the downloaded file. In the latter case, the component error is bound, whose value is a string that describes the problem. The function calls the methods stored in the global list Download_Methods until one of them is successful. Currently there are methods based on the GAP functions DownloadURL (curl: DownloadURL) and SingleHTTPRequest (IO: SingleHTTPRequest), and methods based on the external programs wget and curl. An optional record opt can be given. The following components are supported. maxTime If this component is bound then its value must be a nonnegative integer n, meaning that the function gives up after n seconds. A zero value of n means that no timeout is set, the method will never give up in this case. The default for n is given by the value of the user preference DownloadMaxTime (see 9.1-3). target If this component is bound then its value must be a string that is a local filename, and the function writes the downloaded contents to this file; the returned record does not have a result component in this case. verifyCert If this component is bound and has the value false then those download methods that are based on curl or wget will omit the check of the server's certificate. The same effect is achieved for all Download calls by setting the user preference DownloadVerifyCertificate (see 9.1-2) to false and omitting the verifyCert component from opt.  Example  gap> url:= "https://www.gap-system.org/index.html";; gap> res1:= Download( url );; gap> res1.success; true gap> IsBound( res1.result ) and IsString( res1.result ); true gap> res2:= Download( Concatenation( url, "xxx" ) );; gap> res2.success; false gap> IsBound( res2.error ) and IsString( res2.error ); true  9.1-2 User preference DownloadVerifyCertificate The value true (the default) means that the server's certificate is checked in calls of Download (9.1-1), such that nothing gets downloaded if the certificate is invalid. If the value is false then download methods are supposed to omit the check of the server's certificate (this may not be supported by all download methods). One can set the value of the preference to be val via SetUserPreference (Reference: SetUserPreference), by calling SetUserPreference( "utils", "DownloadVerifyCertificate", val ), and access the current value via UserPreference (Reference: UserPreference), by calling UserPreference( "utils", "DownloadVerifyCertificate" ). We recommend leaving this preference at its default value true. Sometimes it can be necessary to change it, e.g. to work around issues with old operating systems which may not be able to correctly verify new certificates. In general it is better to update such a system, but if that is not an option, then disabling certificate checks may be a good last resort. 9.1-3 User preference DownloadMaxTime The value 0 (the default) means that no timeout is set in calls of Download (9.1-1). If the value is a positive integer n then those download methods that support a timeout will give up after n seconds. One can set the value of the preference to be val via SetUserPreference (Reference: SetUserPreference), by calling SetUserPreference( "utils", "DownloadMaxTime", val ), and access the current value via UserPreference (Reference: UserPreference), by calling UserPreference( "utils", "DownloadMaxTime" ). utils-0.94/doc/chap9_mj.html0000644000000000000000000002674115174515600012677 0ustar00 GAP (Utils) - Chapter 9: Web Downloads
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

9 Web Downloads

The Download operation has been written by Thomas Breuer, incorporating a number of suggestions from Max Horn, for version 0.77 of Utils. It implements downloading a file from within GAP. It can use the IO or curlInterface packages, or wget or curl, if installed, and it can be extended with other download methods quite easily. It is envisaged that, once other packages have started to use it, and any problems have been addressed, that the functions will be transferred to the main GAP library.

9.1 Functions for downloading files from the web

9.1-1 Download
‣ Download( url[, opt] )( function )

This function downloads the file with the web address url, which must be a string.

The result is a record which has at least the component success, with value true if the download was successful and false otherwise. In the former case, the component result is bound, whose value is a string that contains the contents of the downloaded file. In the latter case, the component error is bound, whose value is a string that describes the problem.

The function calls the methods stored in the global list Download_Methods until one of them is successful. Currently there are methods based on the GAP functions DownloadURL (curl: DownloadURL) and SingleHTTPRequest (IO: SingleHTTPRequest), and methods based on the external programs wget and curl.

An optional record opt can be given. The following components are supported.

maxTime

If this component is bound then its value must be a nonnegative integer \(n\), meaning that the function gives up after \(n\) seconds.

A zero value of \(n\) means that no timeout is set, the method will never give up in this case.

The default for \(n\) is given by the value of the user preference DownloadMaxTime (see 9.1-3).

target

If this component is bound then its value must be a string that is a local filename, and the function writes the downloaded contents to this file; the returned record does not have a result component in this case.

verifyCert

If this component is bound and has the value false then those download methods that are based on curl or wget will omit the check of the server's certificate.

The same effect is achieved for all Download calls by setting the user preference DownloadVerifyCertificate (see 9.1-2) to false and omitting the verifyCert component from opt.

gap> url:= "https://www.gap-system.org/index.html";;
gap> res1:= Download( url );;
gap> res1.success;
true
gap> IsBound( res1.result ) and IsString( res1.result );
true
gap> res2:= Download( Concatenation( url, "xxx" ) );;
gap> res2.success;
false
gap> IsBound( res2.error ) and IsString( res2.error );
true

9.1-2 User preference DownloadVerifyCertificate

The value true (the default) means that the server's certificate is checked in calls of Download (9.1-1), such that nothing gets downloaded if the certificate is invalid.

If the value is false then download methods are supposed to omit the check of the server's certificate (this may not be supported by all download methods).

One can set the value of the preference to be val via SetUserPreference (Reference: SetUserPreference), by calling SetUserPreference( "utils", "DownloadVerifyCertificate", val ), and access the current value via UserPreference (Reference: UserPreference), by calling UserPreference( "utils", "DownloadVerifyCertificate" ).

We recommend leaving this preference at its default value true. Sometimes it can be necessary to change it, e.g. to work around issues with old operating systems which may not be able to correctly verify new certificates. In general it is better to update such a system, but if that is not an option, then disabling certificate checks may be a good last resort.

9.1-3 User preference DownloadMaxTime

The value 0 (the default) means that no timeout is set in calls of Download (9.1-1). If the value is a positive integer \(n\) then those download methods that support a timeout will give up after \(n\) seconds.

One can set the value of the preference to be val via SetUserPreference (Reference: SetUserPreference), by calling SetUserPreference( "utils", "DownloadMaxTime", val ), and access the current value via UserPreference (Reference: UserPreference), by calling UserPreference( "utils", "DownloadMaxTime" ).

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chapBib.html0000644000000000000000000001456015174515600012531 0ustar00 GAP (Utils) - References
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

References

[BCP97] Bosma, W., Cannon, J. and Playoust, C., The Magma algebra system. {I}. The user language, J. Symbolic Comput., 24 (3-4) (1997), 235--265 pages
( Computational algebra and number theory (London, 1993)} https://doi.org/10.1006/jsco.1996.0125 ).

[GH16] Gutsche, S. and Horn, M., AutoDoc - Generate documentation from GAP source code (Version 2016.12.04) (2016)
( GAP package, https://github.com/gap-packages/AutoDoc ).

[Hor17] Horn, M., GitHubPagesForGAP - Template for easily using GitHub Pages within GAP packages (Version 0.2) (2017)
( GAP package, https://gap-system.github.io/GitHubPagesForGAP/ ).

[Koh17a] Kohl, S., RCWA - Residue-Class-Wise Affine Groups (Version 4.5.1) (2017)
( GAP package, https://stefan-kohl.github.io/rcwa.html ).

[Koh17b] Kohl, S., ResClasses - Set-Theoretic Computations with Residue Classes (Version 4.6.0) (2017)
( GAP package, https://stefan-kohl.github.io/resclasses.html ).

[LN17] Lübeck, F. and Neunhöffer, M., GAPDoc (Version 1.6), RWTH Aachen (2017)
( GAP package, https://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html ).

[WAOU17] Wensley, C. D., Alp, M., Odabas, A. and Uslu, E. O., XMod - Crossed Modules and Cat1-groups in GAP (Version 2.64) (2017)
( GAP package, https://github.com/gap-packages/xmod ).

[WWT+] Wilson, R. A., Walsh, P., Tripp, J., Suleiman, I., Parker, R. A., Norton, S. P., Nickerson, S., Linton, S., Bray, J. and Abbott, R., ATLAS of Finite Group Representations, http://atlas.math.rwth-aachen.de/Atlas/v3.

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chapBib.txt0000644000000000000000000000402615174515600012400 0ustar00 References [BCP97] Bosma, W., Cannon, J. and Playoust, C., The Magma algebra system. {I}. The user language, J. Symbolic Comput., 24, 3-4 (1997), 235--265 pages, ( Computational algebra and number theory (London, 1993)} https://doi.org/10.1006/jsco.1996.0125 ). [GH16] Gutsche, S. and Horn, M., AutoDoc - Generate documentation from GAP source code (Version 2016.12.04) (2016), ( GAP package, https://github.com/gap-packages/AutoDoc ). [Hor17] Horn, M., GitHubPagesForGAP - Template for easily using GitHub Pages within GAP packages (Version 0.2) (2017), ( GAP package, https://gap-system.github.io/GitHubPagesForGAP/ ). [Koh17a] Kohl, S., RCWA - Residue-Class-Wise Affine Groups (Version 4.5.1) (2017), ( GAP package, https://stefan-kohl.github.io/rcwa.html ). [Koh17b] Kohl, S., ResClasses - Set-Theoretic Computations with Residue Classes (Version 4.6.0) (2017), ( GAP package, https://stefan-kohl.github.io/resclasses.html ). [LN17] Lübeck, F. and Neunhöffer, M., GAPDoc (Version 1.6), RWTH Aachen (2017), ( GAP package, https://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html ). [WAOU17] Wensley, C. D., Alp, M., Odabas, A. and Uslu, E. O., XMod - Crossed Modules and Cat1-groups in GAP (Version 2.64) (2017), ( GAP package, https://github.com/gap-packages/xmod ). [WWT+] Wilson, R. A., Walsh, P., Tripp, J., Suleiman, I., Parker, R. A., Norton, S. P., Nickerson, S., Linton, S., Bray, J. and Abbott, R., ATLAS of Finite Group Representations, http://atlas.math.rwth-aachen.de/Atlas/v3.  utils-0.94/doc/chapBib_mj.html0000644000000000000000000001514715174515600013221 0ustar00 GAP (Utils) - References
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

References

[BCP97] Bosma, W., Cannon, J. and Playoust, C., The Magma algebra system. {I}. The user language, J. Symbolic Comput., 24 (3-4) (1997), 235--265 pages
( Computational algebra and number theory (London, 1993)} https://doi.org/10.1006/jsco.1996.0125 ).

[GH16] Gutsche, S. and Horn, M., AutoDoc - Generate documentation from GAP source code (Version 2016.12.04) (2016)
( GAP package, https://github.com/gap-packages/AutoDoc ).

[Hor17] Horn, M., GitHubPagesForGAP - Template for easily using GitHub Pages within GAP packages (Version 0.2) (2017)
( GAP package, https://gap-system.github.io/GitHubPagesForGAP/ ).

[Koh17a] Kohl, S., RCWA - Residue-Class-Wise Affine Groups (Version 4.5.1) (2017)
( GAP package, https://stefan-kohl.github.io/rcwa.html ).

[Koh17b] Kohl, S., ResClasses - Set-Theoretic Computations with Residue Classes (Version 4.6.0) (2017)
( GAP package, https://stefan-kohl.github.io/resclasses.html ).

[LN17] Lübeck, F. and Neunhöffer, M., GAPDoc (Version 1.6), RWTH Aachen (2017)
( GAP package, https://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html ).

[WAOU17] Wensley, C. D., Alp, M., Odabas, A. and Uslu, E. O., XMod - Crossed Modules and Cat1-groups in GAP (Version 2.64) (2017)
( GAP package, https://github.com/gap-packages/xmod ).

[WWT+] Wilson, R. A., Walsh, P., Tripp, J., Suleiman, I., Parker, R. A., Norton, S. P., Nickerson, S., Linton, S., Bray, J. and Abbott, R., ATLAS of Finite Group Representations, http://atlas.math.rwth-aachen.de/Atlas/v3.

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chapInd.html0000644000000000000000000002412415174515600012544 0ustar00 GAP (Utils) - Index
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

Index

AllIsomorphisms 7.1-1
AllIsomorphismsIterator 7.1-1
AllIsomorphismsNumber 7.1-1
AllProducts 4.1-2
AllSmoothIntegers, for a list and an integer 4.1-1
    for two integers 4.1-1
AllSubgroupsIterator 7.1-2
AssignGlobals 8.1-1
BlankFreeString 3.3-1
CartesianIterator 7.2-1
CentralProduct 5.3-3
CentralProductInfo 5.3-3
Comm 5.1-1
CommonRepresentatives 3.2-1
CommonTransversal 3.2-1
ConvertToMagmaInputString 11.3-1
CreateDirIfMissing 12.1
DataOfGeneralizedStraightLineProgram 10.1-3
DifferencesList 3.1-1
DirectProductOfAutomorphismGroups 5.3-6
DirectProductOfFunctions 5.3-5
DirectSumDecompositionMatrices 6.1-1
distinct and common representatives 3.2
DistinctRepresentatives 3.2-1
Download 9.1-1
DownloadMaxTime 9.1-3
DownloadVerifyCertificate 9.1-2
EpimorphismByGenerators 5.3-1
EquivalentStraightLineProgram 10.1-7
ExponentOfPrime 12.3-2
FindMatchingFiles 12.1
Fitting series 5.1-5
FittingLength 5.1-5
FloatQuotientsList 3.1-2
GeneralizedStraightLineProgram, for a list of lines (and the number of generators) 10.1-2
    for kind and list 10.1-2
GeneratorsAndInverses 5.1-4
GetSuffix 12.1
GitHub repository 1.
IdempotentEndomorphisms 5.3-4
IdempotentEndomorphismsData 5.3-4
IdempotentEndomorphismsWithImage 5.3-4
IntOrInfinityToLaTeX 11.2-1
IsCommonTransversal 3.2-1
IsCommuting 5.1-2
IsGeneralizedStraightLineProgram 10.1-1
IsInternallyConsistent, for generalized straight line program 10.1-8
Iterators 7.1
LaTeXStringFactorsInt 11.2-2
LeftCoset 5.2-1
ListOfPowers 5.1-3
Log2HTML 11.1-1
LowerFittingSeries 5.1-5
MatrixGroupToMagmaFormat 11.3-1
NextProbablyPrimeInt 4.1-4
NrInputsOfGeneralizedStraightLineProgram 10.1-4
NrOutputsOfGeneralizedStraightLineProgram 10.1-5
OKtoReadFromUtils 13.
OptionRecordWithDefaults 8.2-1
PcGroupToMagmaFormat 11.3-1
PermGroupToMagmaFormat 11.3-1
PrimeNumbersIterator 4.1-5
PrintApplicableMethod 12.3-1
PrintOneItemPerLine 12.2
PrintSelection, for a first item and a step 2.1-1
    for a list of positions 2.1-1
Pullback 5.3-2
PullbackInfo 5.3-2
QuotientsList 3.1-2
RandomCombination 3.1-4
RestrictedPartitionsWithoutRepetitions 4.1-3
ResultOfGeneralizedStraightLineProgram 10.1-6
SearchCycle 3.1-3
SetIfMissing 12.1
smooth integer 4.1-1
StringDotSuffix 12.1
UnorderedPairsIterator 7.2-2
UpperFittingSeries 5.1-5

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chapInd.txt0000644000000000000000000000612315174515600012416 0ustar00 Index AllIsomorphisms 7.1-1 AllIsomorphismsIterator 7.1-1 AllIsomorphismsNumber 7.1-1 AllProducts 4.1-2 AllSmoothIntegers, for a list and an integer 4.1-1 for two integers 4.1-1 AllSubgroupsIterator 7.1-2 AssignGlobals 8.1-1 BlankFreeString 3.3-1 CartesianIterator 7.2-1 CentralProduct 5.3-3 CentralProductInfo 5.3-3 Comm 5.1-1 CommonRepresentatives 3.2-1 CommonTransversal 3.2-1 ConvertToMagmaInputString 11.3-1 CreateDirIfMissing 12.1 DataOfGeneralizedStraightLineProgram 10.1-3 DifferencesList 3.1-1 DirectProductOfAutomorphismGroups 5.3-6 DirectProductOfFunctions 5.3-5 DirectSumDecompositionMatrices 6.1-1 distinct and common representatives 3.2 DistinctRepresentatives 3.2-1 Download 9.1-1 DownloadMaxTime 9.1-3 DownloadVerifyCertificate 9.1-2 EpimorphismByGenerators 5.3-1 EquivalentStraightLineProgram 10.1-7 ExponentOfPrime 12.3-2 FindMatchingFiles 12.1 Fitting series 5.1-5 FittingLength 5.1-5 FloatQuotientsList 3.1-2 GeneralizedStraightLineProgram, for a list of lines (and the number of generators) 10.1-2 for kind and list 10.1-2 GeneratorsAndInverses 5.1-4 GetSuffix 12.1 GitHub repository 1.0 IdempotentEndomorphisms 5.3-4 IdempotentEndomorphismsData 5.3-4 IdempotentEndomorphismsWithImage 5.3-4 IntOrInfinityToLaTeX 11.2-1 IsCommonTransversal 3.2-1 IsCommuting 5.1-2 IsGeneralizedStraightLineProgram 10.1-1 IsInternallyConsistent, for generalized straight line program 10.1-8 Iterators 7.1 LaTeXStringFactorsInt 11.2-2 LeftCoset 5.2-1 ListOfPowers 5.1-3 Log2HTML 11.1-1 LowerFittingSeries 5.1-5 MatrixGroupToMagmaFormat 11.3-1 NextProbablyPrimeInt 4.1-4 NrInputsOfGeneralizedStraightLineProgram 10.1-4 NrOutputsOfGeneralizedStraightLineProgram 10.1-5 OKtoReadFromUtils 13.0 OptionRecordWithDefaults 8.2-1 PcGroupToMagmaFormat 11.3-1 PermGroupToMagmaFormat 11.3-1 PrimeNumbersIterator 4.1-5 PrintApplicableMethod 12.3-1 PrintOneItemPerLine 12.2 PrintSelection, for a first item and a step 2.1-1 for a list of positions 2.1-1 Pullback 5.3-2 PullbackInfo 5.3-2 QuotientsList 3.1-2 RandomCombination 3.1-4 RestrictedPartitionsWithoutRepetitions 4.1-3 ResultOfGeneralizedStraightLineProgram 10.1-6 SearchCycle 3.1-3 SetIfMissing 12.1 smooth integer 4.1-1 StringDotSuffix 12.1 UnorderedPairsIterator 7.2-2 UpperFittingSeries 5.1-5 ------------------------------------------------------- utils-0.94/doc/chapInd_mj.html0000644000000000000000000002505715174515600013240 0ustar00 GAP (Utils) - Index
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

Index

AllIsomorphisms 7.1-1
AllIsomorphismsIterator 7.1-1
AllIsomorphismsNumber 7.1-1
AllProducts 4.1-2
AllSmoothIntegers, for a list and an integer 4.1-1
    for two integers 4.1-1
AllSubgroupsIterator 7.1-2
AssignGlobals 8.1-1
BlankFreeString 3.3-1
CartesianIterator 7.2-1
CentralProduct 5.3-3
CentralProductInfo 5.3-3
Comm 5.1-1
CommonRepresentatives 3.2-1
CommonTransversal 3.2-1
ConvertToMagmaInputString 11.3-1
CreateDirIfMissing 12.1
DataOfGeneralizedStraightLineProgram 10.1-3
DifferencesList 3.1-1
DirectProductOfAutomorphismGroups 5.3-6
DirectProductOfFunctions 5.3-5
DirectSumDecompositionMatrices 6.1-1
distinct and common representatives 3.2
DistinctRepresentatives 3.2-1
Download 9.1-1
DownloadMaxTime 9.1-3
DownloadVerifyCertificate 9.1-2
EpimorphismByGenerators 5.3-1
EquivalentStraightLineProgram 10.1-7
ExponentOfPrime 12.3-2
FindMatchingFiles 12.1
Fitting series 5.1-5
FittingLength 5.1-5
FloatQuotientsList 3.1-2
GeneralizedStraightLineProgram, for a list of lines (and the number of generators) 10.1-2
    for kind and list 10.1-2
GeneratorsAndInverses 5.1-4
GetSuffix 12.1
GitHub repository 1.
IdempotentEndomorphisms 5.3-4
IdempotentEndomorphismsData 5.3-4
IdempotentEndomorphismsWithImage 5.3-4
IntOrInfinityToLaTeX 11.2-1
IsCommonTransversal 3.2-1
IsCommuting 5.1-2
IsGeneralizedStraightLineProgram 10.1-1
IsInternallyConsistent, for generalized straight line program 10.1-8
Iterators 7.1
LaTeXStringFactorsInt 11.2-2
LeftCoset 5.2-1
ListOfPowers 5.1-3
Log2HTML 11.1-1
LowerFittingSeries 5.1-5
MatrixGroupToMagmaFormat 11.3-1
NextProbablyPrimeInt 4.1-4
NrInputsOfGeneralizedStraightLineProgram 10.1-4
NrOutputsOfGeneralizedStraightLineProgram 10.1-5
OKtoReadFromUtils 13.
OptionRecordWithDefaults 8.2-1
PcGroupToMagmaFormat 11.3-1
PermGroupToMagmaFormat 11.3-1
PrimeNumbersIterator 4.1-5
PrintApplicableMethod 12.3-1
PrintOneItemPerLine 12.2
PrintSelection, for a first item and a step 2.1-1
    for a list of positions 2.1-1
Pullback 5.3-2
PullbackInfo 5.3-2
QuotientsList 3.1-2
RandomCombination 3.1-4
RestrictedPartitionsWithoutRepetitions 4.1-3
ResultOfGeneralizedStraightLineProgram 10.1-6
SearchCycle 3.1-3
SetIfMissing 12.1
smooth integer 4.1-1
StringDotSuffix 12.1
UnorderedPairsIterator 7.2-2
UpperFittingSeries 5.1-5

Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 Bib Ind

generated by GAPDoc2HTML

utils-0.94/doc/chooser.html0000644000000000000000000000745615174515600012651 0ustar00 GAPDoc Style Chooser

Setting preferences for GAPDoc manuals

Unfold subsections in menus only by mouse clicks: no (default)     yes

Show GAP examples as in sessions with ColorPrompt(true): yes (default)     no

Display side of table of contents within chapters: right (default)     left

Main document font: Helvetica/sans serif (default)     Times/serif

Paragraph formatting: left-right justified (default)     ragged right

Apply settings to last page.

utils-0.94/doc/download.xml0000644000000000000000000001356515174515600012650 0ustar00 Web Downloads The Download operation has been written by Thomas Breuer, incorporating a number of suggestions from Max Horn, for version 0.77 of Utils. It implements downloading a file from within &GAP;. It can use the IO or curlInterface packages, or wget or curl, if installed, and it can be extended with other download methods quite easily. It is envisaged that, once other packages have started to use it, and any problems have been addressed, that the functions will be transferred to the main &GAP; library.
Functions for downloading files from the web This function downloads the file with the web address url, which must be a string.

The result is a record which has at least the component success, with value true if the download was successful and false otherwise. In the former case, the component result is bound, whose value is a string that contains the contents of the downloaded file. In the latter case, the component error is bound, whose value is a string that describes the problem.

The function calls the methods stored in the global list Download_Methods until one of them is successful. Currently there are methods based on the &GAP; functions and , and methods based on the external programs wget and curl.

An optional record opt can be given. The following components are supported.

maxTime If this component is bound then its value must be a nonnegative integer n, meaning that the function gives up after n seconds.

A zero value of n means that no timeout is set, the method will never give up in this case.

The default for n is given by the value of the user preference DownloadMaxTime (see ). target If this component is bound then its value must be a string that is a local filename, and the function writes the downloaded contents to this file; the returned record does not have a result component in this case. verifyCert If this component is bound and has the value false then those download methods that are based on curl or wget will omit the check of the server's certificate.

The same effect is achieved for all calls by setting the user preference DownloadVerifyCertificate (see ) to false and omitting the verifyCert component from opt.

url:= "https://www.gap-system.org/index.html";; gap> res1:= Download( url );; gap> res1.success; true gap> IsBound( res1.result ) and IsString( res1.result ); true gap> res2:= Download( Concatenation( url, "xxx" ) );; gap> res2.success; false gap> IsBound( res2.error ) and IsString( res2.error ); true ]]> User preference DownloadVerifyCertificate DownloadVerifyCertificate The value true (the default) means that the server's certificate is checked in calls of , such that nothing gets downloaded if the certificate is invalid.

If the value is false then download methods are supposed to omit the check of the server's certificate (this may not be supported by all download methods).

One can set the value of the preference to be val via , by calling SetUserPreference( "utils", "DownloadVerifyCertificate", val ), and access the current value via , by calling UserPreference( "utils", "DownloadVerifyCertificate" ).

We recommend leaving this preference at its default value true. Sometimes it can be necessary to change it, e.g. to work around issues with old operating systems which may not be able to correctly verify new certificates. In general it is better to update such a system, but if that is not an option, then disabling certificate checks may be a good last resort. User preference DownloadMaxTime DownloadMaxTime The value 0 (the default) means that no timeout is set in calls of . If the value is a positive integer n then those download methods that support a timeout will give up after n seconds.

One can set the value of the preference to be val via , by calling SetUserPreference( "utils", "DownloadMaxTime", val ), and access the current value via , by calling UserPreference( "utils", "DownloadMaxTime" ).

utils-0.94/doc/gaplog.css0000644000000000000000000000227715174515600012300 0ustar00/* ####################################################################### */ /* ## ## */ /* ## gaplog.css GAP *.log - File Style Stefan Kohl ## */ /* ## ## */ /* ####################################################################### */ body { background: #FFFFFF; color: #000000; margin-top: 5mm; margin-bottom: 5mm; margin-left: 5mm; margin-right: 5mm; font-family: Helvetica,Verdana,Arial,sans-serif; } pre.logfile { font-family: "Courier New",Courier,monospace; font-size: 100%; } em.prompt { font-size: 100%; font-style: normal; color: #FF0000; } em.input { font-size: 100%; font-style: normal; color: #0000FF; } em.output { font-size: 100%; font-style: normal; color: #284D49; } a:link { color: #0000AE; text-decoration: none; } a:visited { color: #0000AE; text-decoration: none; } a:active { color: #000000; text-decoration: none; } /* ####################################################################### */ utils-0.94/doc/groups.xml0000644000000000000000000003766015174515600012362 0ustar00 Groups and homomorphisms
Functions for groups This method has been transferred from package &ResClasses;.

It provides a method for Comm when the argument is a list (enclosed in square brackets), and calls the function LeftNormedComm.

Comm( [ (1,2), (2,3) ] ); (1,2,3) gap> Comm( [(1,2),(2,3),(3,4),(4,5),(5,6)] ); (1,5,6) gap> Comm(Comm(Comm(Comm((1,2),(2,3)),(3,4)),(4,5)),(5,6)); ## the same (1,5,6) ]]> This function has been transferred from package &ResClasses;.

It tests whether two elements in a group commute.

D12 := DihedralGroup( 12 ); gap> SetName( D12, "D12" ); gap> a := D12.1;; b := D12.2;; gap> IsCommuting( a, b ); false ]]> This function has been transferred from package &RCWA;.

The operation ListOfPowers(g,exp) returns the list [g,g^2,...,g^{exp}] of powers of the element g.

ListOfPowers( 2, 20 ); [ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 ] gap> ListOfPowers( (1,2,3)(4,5), 12 ); [ (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), (), (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), () ] gap> ListOfPowers( D12.2, 6 ); [ f2, f3, f2*f3, f3^2, f2*f3^2, of ... ] ]]> This function has been transferred from package &RCWA;.

This operation returns a list containing the generators of G followed by the inverses of these generators.

GeneratorsAndInverses( D12 ); [ f1, f2, f3, f1, f2*f3^2, f3^2 ] gap> GeneratorsAndInverses( SymmetricGroup(5) ); [ (1,2,3,4,5), (1,2), (1,5,4,3,2), (1,2) ] ]]> These three functions have been transferred from package &ResClasses;.

Fitting series The upper and lower Fitting series and the Fitting length of a solvable group are described here: https://en.wikipedia.org/wiki/Fitting_length.

upp:= UpperFittingSeries( D12 );; gap> List( upp, StructureDescription ); [ "1", "C6", "D12" ] gap> low:= LowerFittingSeries( D12 );; gap> List( low, StructureDescription ); [ "D12", "C3", "1" ] gap> FittingLength( D12 ); 2 gap> S4 := SymmetricGroup( 4 );; gap> UpperFittingSeries( S4 ); [ Group(()), Group([ (1,2)(3,4), (1,4)(2,3) ]), Group([ (2,4,3), (1,2)(3,4) ]), Group([ (3,4), (2,4,3), (1,2)(3,4) ]) ] gap> List( last, StructureDescription ); [ "1", "C2 x C2", "A4", "S4" ] gap> LowerFittingSeries( S4 ); [ Sym( [ 1 .. 4 ] ), Alt( [ 1 .. 4 ] ), Group([ (1,4)(2,3), (1,2)(3,4) ]), Group(()) ] gap> List( last, StructureDescription ); [ "S4", "A4", "C2 x C2", "1" ] gap> FittingLength( S4); 3 ]]>

Left Cosets for Groups Since &GAP; uses right actions by default, the library contains the operation RightCoset(U,g) for constructing the right coset Ug of a subgroup U \leq G and an element g \in G. It has been noted in the reference manual that, by inverting all the elements in Ug, the left coset g^{-1}U is obtained.

Just for the sake of completeness, from August 2022 this package provides the operation LeftCoset(g,U) for constructing the left coset gU. Users are strongly recommended to continue to use RightCoset for all serious calculations, since left cosets have a much simpler implementation and do not behave exactly like right cosets.

The methods for left cosets which are provided generally work by converting gU to Ug^{-1}; applying the equivalent method for right cosets; and, if necessary, converting back again to left cosets.

G acts on left cosets by OnLeftInverse: (gU)^{g_0} = g_0^{-1}*(gU) = (g_0^{-1}g)U.

a4 := Group( (1,2,3), (2,3,4) );; SetName( a4, "a4" ); gap> k4 := Group( (1,2)(3,4), (1,3)(2,4) );; SetName( k4, "k4" ); gap> rc := RightCosets( a4, k4 ); [ RightCoset(k4,()), RightCoset(k4,(2,3,4)), RightCoset(k4,(2,4,3)) ] gap> lc := LeftCosets( a4, k4 ); [ LeftCoset((),k4), LeftCoset((2,4,3),k4), LeftCoset((2,3,4),k4) ] gap> AsSet( lc[2] ); [ (2,4,3), (1,2,3), (1,3,4), (1,4,2) ] gap> LeftCoset( (1,4,2), k4 ) = lc[2]; true gap> Representative( lc[2] ); (2,4,3) gap> ActingDomain( lc[2] ); k4 gap> (1,4,3) in lc[3]; true gap> (1,2,3)*lc[2] = lc[3]; true gap> lc[2]^(1,3,2) = lc[3]; true ]]> Inverse The inverse of the left coset gU is the right coset Ug^{-1}, and conversely. This is an abuse of the attribute Inverse, since the standard requirement, that x*x^{-1} is an identity, does not hold.

Inverse( rc[3] ) = lc[3]; true gap> Inverse( lc[2] ) = rc[2]; true ]]>

Functions for group homomorphisms This function has been transferred from package &RCWA;.

It constructs a group homomorphism which maps the generators of G to those of H. Its intended use is when G is a free group, and a warning is printed when this is not the case. Note that anything may happen if the resulting map is not a homomorphism!

G := Group( (1,2,3), (3,4,5), (5,6,7), (7,8,9) );; gap> phi := EpimorphismByGenerators( FreeGroup("a","b","c","d"), G ); [ a, b, c, d ] -> [ (1,2,3), (3,4,5), (5,6,7), (7,8,9) ] gap> PreImagesRepresentativeNC( phi, (1,2,3,4,5,6,7,8,9) ); d*c*b*a gap> a := G.1;; b := G.2;; c := G.3;; d := G.4;; gap> d*c*b*a; (1,2,3,4,5,6,7,8,9) gap> ## note that it is easy to produce nonsense: gap> epi := EpimorphismByGenerators( Group((1,2,3)), Group((8,9)) ); Warning: calling GroupHomomorphismByImagesNC without checks [ (1,2,3) ] -> [ (8,9) ] gap> IsGroupHomomorphism( epi ); true gap> Image( epi, (1,2,3) ); () gap> Image( epi, (1,3,2) ); (8,9) ]]> If \phi_1 : G_1 \to H and \phi_2 : G_2 \to H are two group homomorphisms with the same range, then their pullback is the subgroup of G_1 \times G_2 consisting of those elements (g_1,g_2) such that \phi_1 g_1 = \phi_2 g_2.

The attribute PullbackInfo of a pullback group P is similar to DirectProductInfo for a direct product of groups. Its value is a record with the following components:

directProduct the direct product G_1 \times G_2, and projections a list with the two projections onto G_1 and G_2. There are no embeddings in this record, but it is possible to use the embeddings into the direct product, see .

s4 := Group( (1,2),(2,3),(3,4) );; gap> s3 := Group( (5,6),(6,7) );; gap> c3 := Subgroup( s3, [ (5,6,7) ] );; gap> f := GroupHomomorphismByImages( s4, s3, > [(1,2),(2,3),(3,4)], [(5,6),(6,7),(5,6)] );; gap> i := GroupHomomorphismByImages( c3, s3, [(5,6,7)], [(5,6,7)] );; gap> Pfi := Pullback( f, i ); Group([ (2,3,4)(5,7,6), (1,2)(3,4) ]) gap> StructureDescription( Pfi ); "A4" gap> info := PullbackInfo( Pfi ); rec( directProduct := Group([ (1,2), (2,3), (3,4), (5,6,7) ]), projections := [ [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (2,3,4), (1,2)(3,4) ], [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (5,7,6), () ] ] ) gap> g := (1,2,3)(5,6,7);; gap> ImageElm( info!.projections[1], g ); (1,2,3) gap> ImageElm( info!.projections[2], g ); (5,6,7) gap> dp := info!.directProduct;; gap> a := ImageElm( Embedding( dp, 1 ), (1,4,3) );; gap> b := ImageElm( Embedding( dp, 2 ), (5,7,6) );; gap> a*b in Pfi; true ]]> This function was added by Thomas Breuer, following discussions with Hongyi Zhao (see https://github.com/gap-packages/hap/issues/73).

Let G1 and G2 be two groups, Z1 be a central subgroup of G1, and Phi be an isomorphism from Z1 to a central subgroup of G2. The central product defined by these arguments is the factor group of the direct product of G1 and G2 by the central subgroup \{ (z, (Phi(z))^{-1}) : z \in Z1 \}.

The attribute of a group G that has been created by is similar to for pullback groups. Its value is a record with the following components.

projection the epimorphism from the direct product of G1 and G2 to G, and phi the map Phi. Note that one can access the direct product as the value of the projection map, and one can access G1 and G2 as the two embeddings of this direct product, see . g1 := DihedralGroup( 8 ); gap> c1 := Centre( g1 ); Group([ f3 ]) gap> cp1 := CentralProduct( g1, g1, c1, IdentityMapping( c1 ) ); Group([ f1, f2, f5, f3, f4, f5 ]) gap> IdGroup( cp1 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) ); true gap> g2 := QuaternionGroup( 8 ); gap> c2 := Centre( g2 ); Group([ y2 ]) gap> cp2 := CentralProduct( g2, g2, c2, IdentityMapping( c2 ) ); Group([ f1, f2, f5, f3, f4, f5 ]) gap> IdGroup( cp2 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) ); true gap> info2 := CentralProductInfo( cp2 ); rec( phi := IdentityMapping( Group([ y2 ]) ), projection := [ f1, f2, f3, f4, f5, f6 ] -> [ f1, f2, f5, f3, f4, f5 ] ) gap> Source( Embedding( Source( info2.projection ), 1 ) ) = g2; true ]]> An endomorphism f\colon G \to G is idempotent if f^2 = f. It has an image R \leq G, is the identity map when restricted to R, and has a kernel N which has trivial intersection with R and has size |G|/|R|.

The operation IdempotentEndomorphismsWithImage(genG,R) returns a list of the images of the generating set genG of a group G under the idempotent endomorphisms with image R.

The attribute IdempotentEndomorphismsData(G) returns a record data with fields data.gens, a fixed generating set for G, and data.images a list of the non-empty outputs of IdempotentEndomorphismsWithImage(genG,R) obtained by iterating over all subgroups R of G.

The operation IdempotentEndomorphisms(G) returns the list of these mappings obtained using IdempotentEndomorphismsData(G). The first of these is the zero map, the last is the identity.

gens := [ (1,2,3,4), (1,2)(3,4) ];; gap> d8 := Group( gens );; gap> SetName( d8, "d8" ); gap> c2 := Subgroup( d8, [ (2,4) ] );; gap> SortedList( IdempotentEndomorphismsWithImage( gens, c2 ) ); [ [ (), (2,4) ], [ (2,4), () ] ] gap> data:= IdempotentEndomorphismsData( d8 );; gap> data.images[1]; [ [ (), () ] ] gap> List( data.images, Length ); [ 1, 2, 2, 2, 2, 1 ] gap> all:= IdempotentEndomorphisms( d8 );; gap> Length( all ); 10 gap> all[1]; [ (1,2,3,4), (1,2)(3,4) ] -> [ (), () ] gap> Size( Image( all[1] ) ); 1 gap> Last( all ) = IdentityMapping( d8 ); true ]]> The quaternion group q8 is an example of a group with a tail: there is only one subgroup in the lattice which covers the identity subgroup. The only idempotent isomorphisms of such groups are the identity mapping and the zero mapping because the only pairs N,R are the whole group and the identity subgroup. q8 := QuaternionGroup( 8 );; gap> IdempotentEndomorphisms( q8 ); [ [ x, y ] -> [ of ..., of ... ], [ x, y ] -> [ x, y ] ] ]]> Given group homomorphisms f_1 : G_1 \to G_2 and f_2 : H_1 \to H_2, this operation return the product homomorphism f_1 \times f_2 : G_1 \times G_2 \to H_1 \times H_2.

c4 := Group( (1,2,3,4) );; gap> c2 := Group( (5,6) );; gap> f1 := GroupHomomorphismByImages( c4, c2, [(1,2,3,4)], [(5,6)] );; gap> c3 := Group( (1,2,3) );; gap> c6 := Group( (1,2,3,4,5,6) );; gap> f2 := GroupHomomorphismByImages( c3, c6, [(1,2,3)], [(1,3,5)(2,4,6)] );; gap> c4c3 := DirectProduct( c4, c3 ); Group([ (1,2,3,4), (5,6,7) ]) gap> c2c6 := DirectProduct( c2, c6 ); Group([ (1,2), (3,4,5,6,7,8) ]) gap> f := DirectProductOfFunctions( c4c3, c2c6, f1, f2 ); [ (1,2,3,4), (5,6,7) ] -> [ (1,2), (3,5,7)(4,6,8) ] gap> ImageElm( f, (1,4,3,2)(5,7,6) ); (1,2)(3,7,5)(4,8,6) ]]> Let A_1,A_2 be groups of automorphism of groups G_1,G_2 respectively. The output of this function is a group A_1 \times A_2 of automorphisms of G_1 \times G_2.

c9 := Group( (1,2,3,4,5,6,7,8,9) );; gap> ac9 := AutomorphismGroup( c9 );; gap> q8 := QuaternionGroup( IsPermGroup, 8 );; gap> aq8 := AutomorphismGroup( q8 );; gap> A := DirectProductOfAutomorphismGroups( ac9, aq8 ); gap> genA := GeneratorsOfGroup( A );; gap> G := Source( genA[1] ); Group([ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13) (14,15,16,17) ]) gap> a := genA[1]*genA[5]; [ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13)(14,15,16,17) ] -> [ (1,3,5,7,9,2,4,6,8), (10,16,12,14)(11,15,13,17), (10,11,12,13)(14,15,16,17) ] gap> ImageElm( a, (1,9,8,7,6,5,4,3,2)(10,14,12,16)(11,17,13,15) ); (1,8,6,4,2,9,7,5,3)(10,16,12,14)(11,15,13,17) ]]>

utils-0.94/doc/gslp.xml0000644000000000000000000001403515174515600011777 0ustar00 Generalized Straight Line Programs The functions described in this chapter have been written by Thomas Breuer, they are available since Utils 0.94.

Generalized straight line programs (in the following abbreviated as gslps) are a generalization of the straight line programs that are described in the &GAP; library, see . Like the latter objects, gslps describe an efficient way for evaluating an abstract word at concrete generators. The difference is that gslps can be built from existing (generalized) straight line programs, whereas a straight line program is given by an explicit list of instructions (see ). So the advantages of using a gslp instead of constructing an equivalent straight line program (see ) are that

available objects (the building blocks of the gslp) are reused, the internal structure of the gslp is retained (one can access the building blocks if one wants), and in the evaluation of a gslp, the intermediate results that arise in a building block of the gslp can be garbage collected as soon as the evaluation of this building block has finished.

A gslp in &GAP; is represented by an object in the category . This object has exactly one of the following forms.

It is a straight line program, that is, it lies in the category , and evaluation at some group elements is defined by . It is of union kind, that is, the defining data are a nonempty list l of gslps, and evaluation at some group elements means to evaluate the gslps in l at these group elements, and to return the concatenation of the results. It is of compose kind, that is, the defining data are a nonempty list l of gslps, and evaluation at some group elements means to evaluate l[1] at these elements, then to evaluate l[2] at the result of the first evaluation, and so on, and to return the last result.

Here are two typical situations where gslps arise. In both cases, suppose that a list l of standard generators for a group G is given.

Suppose that we know a straight line program for computing generators l' of a maximal subgroup M of G from l. For example, these data may be taken from the ATLAS of Group Representations . If M is also a group for which the ATLAS of Group Representations contains generators and straight line programs, we may be interested in computing standard generators l'' for M from l'.

For that, a second straight line program may be needed, and it makes sense to encode the computation of l'' from l via a gslp of compose kind. Suppose that we are in fact interested in a downward extension H of G, and that \pi is the natural epimorphism from H to G, which maps a list L, say, of standard generators of H to l. Then the above gslp for G can be applied to L, but the result L' may generate a proper subgroup of \pi^{-1}(M) because some part of the kernel of \pi is missing.

A list K of generators of the kernel of \pi can be described by a straight line program that takes L as its input, and it makes sense to encode the computation of the concatenation of L' and K from L via a gslp of union kind.

Gslps can be constructed using .

Defining attributes for gslps are and . The probably most interesting operation for gslps is .

Currently we do not intend to provide methods applicable to generalized straight line programs for all operations that are defined for straight line programs. For example, there is no method for generalized straight line programs.

Special methods applicable to gslps are installed for the operations , , and .

Functions for Generalized Straight Line Programs <#Include Label="IsGeneralizedStraightLineProgram"> <#Include Label="GeneralizedStraightLineProgram"> <#Include Label="DataOfGeneralizedStraightLineProgram"> <#Include Label="NrInputsOfGeneralizedStraightLineProgram"> <#Include Label="NrOutputsOfGeneralizedStraightLineProgram"> <#Include Label="ResultOfGeneralizedStraightLineProgram"> <#Include Label="EquivalentStraightLineProgram"> <#Include Label="IsInternallyConsistent_gslp">
utils-0.94/doc/intro.xml0000644000000000000000000001164115174515600012165 0ustar00 Introduction The &Utils; package provides a space for utility functions from a variety of &GAP; packages to be collected together into a single package. In this way it is hoped that they will become more visible to other package authors. This package was first distributed as part of the &GAP; 4.8.2 distribution.

The package is loaded with the command LoadPackage( "utils" ); true ]]>

Functions have been transferred from the following packages: Conversion of a &GAP; group to a &Magma; output string, taken from various sources including other.gi in the main library.

Transfer is complete (for now) for functions from the following packages: &AutoDoc; (with function names changed); &ResClasses; ; &RCWA; ; &XMod; .

The package may be obtained either as a compressed .tar file or as a .zip file, utils-version_number.tar.gz, by ftp from one of the following sites: the &Utils; GitHub release site: https://gap-packages.github.io/utils/. any &GAP; archive, e.g. https://www.gap-system.org/Packages/packages.html; GitHub repository The package also has a GitHub repository at: https://github.com/gap-packages/utils.

Once the package is loaded, the manual doc/manual.pdf can be found in the documentation folder. The html versions, with or without &MathJax;, may be rebuilt as follows:

ReadPackage( "utils", "makedoc.g" ); ]]>

It is possible to check that the package has been installed correctly by running the test files (which terminates the &GAP; session):

ReadPackage( "utils", "tst/testall.g" ); Architecture: . . . . . testing: . . . . . . . . #I No errors detected while testing ]]>

Note that functions listed in this manual that are currently in the process of being transferred are only read from the source package &Home; (say), and so can only be used if &Home; has already been loaded. There are no such functions in transition at present.

Information for package authors A function (or collection of functions) is suitable for transfer from a package &Home; to &Utils; if the following conditions are satisfied. The function is sufficiently non-specialised so that it might be of use to other authors. The function does not depend on the remaining functions in &Home; The function does not do what can already be done with a &GAP; library function. Documentation of the function and test examples are available. When there is more than one active author of &Home;, they should all be aware (and content) that the transfer is taking place.

Authors of packages may be reluctant to let go of their utility functions. The following principles may help to reassure them. (Suggestions for more items here are welcome.) A function that has been transferred to &Utils; will not be changed without the approval of the original author. The current package maintainer has every intention of continuing to maintain &Utils;. In the event that this proves impossible, the &GAP; development team will surely find someone to take over. Function names will not be changed unless specifically requested by &Home;'s author(s) or unless they have the form HOME_FunctionName. In order to speed up the transfer process, only functions from one package will be in transition at any given time. Hopefully a week or two will suffice for most packages. Any package author who transfers a function to &Utils; will become an author of &Utils;. (In truth, &Utils; does not have authors, just a large number of contributors.)

The process for transferring utility functions from &Home; to &Utils; is described in Chapter .

utils-0.94/doc/iterator.xml0000644000000000000000000001231515174515600012662 0ustar00 Iterators
Some iterators for groups and their isomorphisms Iterators The motivation for adding these operations is partly to give a simple example of an iterator for a list that does not yet exist, and need not be created.

The main &GAP; library contains functions producing complete lists of group homomorphisms such as AllHomomorphisms; AllEndomorphisms and AllAutomorphisms. Here we add the missing AllIsomorphisms(G,H) for a list of isomorphisms from G to H. The method is simple -- find one isomorphism G \to H and compose this with all the automorphisms of G. In all these cases it may not be desirable to construct a list of homomorphisms, but just implement an iterator, and that is what is done here. The operation AllIsomorphismsNumber returns the number of isomorphisms iterated over (this is, of course, just the order of the automorphisms group). The operation AllIsomorphisms produces the list or isomorphisms.

G := SmallGroup( 6,1);; gap> iter := AllIsomorphismsIterator( G, s3 );; gap> NextIterator( iter ); [ f1, f2 ] -> [ (6,7), (5,6,7) ] gap> n := AllIsomorphismsNumber( G, s3 ); 6 gap> AllIsomorphisms( G, s3 ); [ [ f1, f2 ] -> [ (6,7), (5,6,7) ], [ f1, f2 ] -> [ (5,7), (5,6,7) ], [ f1, f2 ] -> [ (5,6), (5,7,6) ], [ f1, f2 ] -> [ (6,7), (5,7,6) ], [ f1, f2 ] -> [ (5,7), (5,7,6) ], [ f1, f2 ] -> [ (5,6), (5,6,7) ] ] gap> iter := AllIsomorphismsIterator( G, s3 );; gap> for h in iter do Print( ImageElm( h, G.1 ) = (6,7), ", " ); od; true, false, false, true, false, false, ]]> The manual entry for the operation AllSubgroups states that it is only intended to be used on small examples in a classroom situation. Access to all subgroups was required by the XMod package, so this iterator was introduced here. It used the operations LatticeSubgroups(G) and ConjugacyClassesSubgroups(lat), and then iterates over the entries in these classes.

c3c3 := Group( (1,2,3), (4,5,6) );; gap> iter := AllSubgroupsIterator( c3c3 ); gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od; Group( () ) Group( [ (4,5,6) ] ) Group( [ (1,2,3) ] ) Group( [ (1,2,3)(4,5,6) ] ) Group( [ (1,3,2)(4,5,6) ] ) Group( [ (4,5,6), (1,2,3) ] ) ]]>

Operations on iterators This section considers ways of producing an iterator from one or more iterators. It may be that operations equivalent to these are available elsewhere in the library -- if so, the ones here can be removed in due course. This iterator returns all pairs [x,y] where x is the output of a first iterator and y is the output of a second iterator.

it1 := Iterator( [ 1, 2, 3 ] );; gap> it2 := Iterator( [ 4, 5, 6 ] );; gap> iter := CartesianIterator( it1, it2 );; gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od; [ 1, 4 ] [ 1, 5 ] [ 1, 6 ] [ 2, 4 ] [ 2, 5 ] [ 2, 6 ] [ 3, 4 ] [ 3, 5 ] [ 3, 6 ] ]]> This operation returns pairs [x,y] where x,y are output from a given iterator iter. Unlike the output from CartesianIterator(iter,iter), unordered pairs are returned. In the case L = [1,2,3,\ldots] the pairs are ordered as [1,1],[1,2],[2,2],[1,3],[2,3],[3,3],\ldots.

L := [6,7,8,9];; gap> iterL := IteratorList( L );; gap> pairsL := UnorderedPairsIterator( iterL );; gap> while not IsDoneIterator(pairsL) do Print(NextIterator(pairsL),"\n"); od; [ 6, 6 ] [ 6, 7 ] [ 7, 7 ] [ 6, 8 ] [ 7, 8 ] [ 8, 8 ] [ 6, 9 ] [ 7, 9 ] [ 8, 9 ] [ 9, 9 ] gap> iter4 := IteratorList( [ 4 ] ); gap> pairs4 := UnorderedPairsIterator(iter4); gap> NextIterator( pairs4 ); [ 4, 4 ] gap> IsDoneIterator( pairs4 ); true ]]>

utils-0.94/doc/lefttoc.css0000644000000000000000000000047415174515600012464 0ustar00/* leftmenu.css Frank Lübeck */ /* Change default CSS to show section menu on left side */ body { padding-left: 28%; } body.chap0 { padding-left: 2%; } div.ChapSects div.ContSect:hover div.ContSSBlock { left: 15%; } div.ChapSects { left: 1%; width: 25%; } utils-0.94/doc/lists.xml0000644000000000000000000001645115174515600012174 0ustar00 Lists, Sets and Strings
Functions for lists This function has been transferred from package &ResClasses;.

It takes a list L of length n and outputs the list of length n-1 containing all the differences L[i]-L[i-1].

List( [1..12], n->n^3 ); [ 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728 ] gap> DifferencesList( last ); [ 7, 19, 37, 61, 91, 127, 169, 217, 271, 331, 397 ] gap> DifferencesList( last ); [ 12, 18, 24, 30, 36, 42, 48, 54, 60, 66 ] gap> DifferencesList( last ); [ 6, 6, 6, 6, 6, 6, 6, 6, 6 ] ]]> These functions have been transferred from package &ResClasses;.

They take a list L of length n and output the quotients L[i]/L[i-1] of consecutive entries in L. An error is returned if an entry is zero.

List( [0..10], n -> Factorial(n) ); [ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 ] gap> QuotientsList( last ); [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] gap> L := [ 1, 3, 5, -1, -3, -5 ];; gap> QuotientsList( L ); [ 3, 5/3, -1/5, 3, 5/3 ] gap> FloatQuotientsList( L ); [ 3., 1.66667, -0.2, 3., 1.66667 ] gap> QuotientsList( [ 2, 1, 0, -1, -2 ] ); [ 1/2, 0, fail, 2 ] gap> FloatQuotientsList( [1..10] ); [ 2., 1.5, 1.33333, 1.25, 1.2, 1.16667, 1.14286, 1.125, 1.11111 ] gap> Product( last ); 10. ]]> This function has been transferred from package &RCWA;.

SearchCycle is a tool to find likely cycles in lists. What, precisely, a cycle is, is deliberately fuzzy here, and may possibly even change. The idea is that the beginning of the list may be anything, following that the same pattern needs to be repeated several times in order to be recognized as a cycle.

L := [1..20];; L[1]:=13;; gap> for i in [1..19] do > if IsOddInt(L[i]) then L[i+1]:=3*L[i]+1; else L[i+1]:=L[i]/2; fi; > od; gap> L; [ 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4 ] gap> SearchCycle( L ); [ 1, 4, 2 ] gap> n := 1;; L := [n];; gap> for i in [1..100] do n:=(n^2+1) mod 1093; Add(L,n); od; gap> L; [ 1, 2, 5, 26, 677, 363, 610, 481, 739, 715, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004 ] gap> C := SearchCycle( L ); [ 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754 ] gap> P := Positions( L, 157 ); [ 14, 26, 38, 50, 62, 74, 86, 98 ] gap> Length( C ); DifferencesList( P ); 12 [ 12, 12, 12, 12, 12, 12, 12 ] ]]> This function has been transferred from package &ResClasses;.

It returns a random unordered k-tuple of distinct elements of a set S.

## "6 aus 49" is a common lottery in Germany gap> RandomCombination( [1..49], 6 ); [ 2, 16, 24, 26, 37, 47 ] ]]>

Distinct and Common Representatives distinct and common representatives These operations have been transferred from package &XMod;.

They deal with lists of subsets of [1 \ldots n] and construct systems of distinct and common representatives using simple, non-recursive, combinatorial algorithms.

When L is a set of n subsets of [1 \ldots n] and the Hall condition is satisfied (the union of any k subsets has at least k elements), a set of DistinctRepresentatives exists.

When J,K are both lists of n sets, the operation CommonRepresentatives returns two lists: the set of representatives, and a permutation of the subsets of the second list.

The operation CommonTransversal may be used to provide a common transversal for the sets of left and right cosets of a subgroup H of a group G, although a greedy algorithm is usually quicker.

J := [ [1,2,3], [3,4], [3,4], [1,2,4] ];; gap> DistinctRepresentatives( J ); [ 1, 3, 4, 2 ] gap> K := [ [3,4], [1,2], [2,3], [2,3,4] ];; gap> CommonRepresentatives( J, K ); [ [ 3, 3, 3, 1 ], [ 1, 3, 4, 2 ] ] gap> d16 := DihedralGroup( IsPermGroup, 16 ); Group([ (1,2,3,4,5,6,7,8), (2,8)(3,7)(4,6) ]) gap> SetName( d16, "d16" ); gap> c4 := Subgroup( d16, [ d16.1^2 ] ); Group([ (1,3,5,7)(2,4,6,8) ]) gap> SetName( c4, "c4" ); gap> RightCosets( d16, c4 ); [ RightCoset(c4,()), RightCoset(c4,(2,8)(3,7)(4,6)), RightCoset(c4,(1,8,7,6,5, 4,3,2)), RightCoset(c4,(1,8)(2,7)(3,6)(4,5)) ] gap> trans := CommonTransversal( d16, c4 ); [ (), (2,8)(3,7)(4,6), (1,2,3,4,5,6,7,8), (1,2)(3,8)(4,7)(5,6) ] gap> IsCommonTransversal( d16, c4, trans ); true ]]>

Functions for strings This function has been transferred from package &ResClasses;.

The result of BlankFreeString( obj ); is a composite of the functions String( obj ) and RemoveCharacters( obj, " " );.

gens := GeneratorsOfGroup( DihedralGroup(12) ); [ f1, f2, f3 ] gap> String( gens ); "[ f1, f2, f3 ]" gap> BlankFreeString( gens ); "[f1,f2,f3]" ]]>

utils-0.94/doc/manual.css0000644000000000000000000001575415174515600012310 0ustar00/* manual.css Frank Lübeck */ /* This is the default CSS style sheet for GAPDoc HTML manuals. */ /* basic settings, fonts, sizes, colors, ... */ body { position: relative; background: #ffffff; color: #000000; width: 70%; margin: 0pt; padding: 15pt; font-family: Helvetica,Verdana,Arial,sans-serif; text-align: justify; } /* no side toc on title page, bib and index */ body.chap0 { width: 95%; } body.chapBib { width: 95%; } body.chapInd { width: 95%; } h1 { font-size: 200%; } h2 { font-size: 160%; } h3 { font-size: 160%; } h4 { font-size: 130%; } h5 { font-size: 100%; } p.foot { font-size: 60%; font-style: normal; } a:link { color: #00008e; text-decoration: none; } a:visited { color: #00008e; text-decoration: none; } a:active { color: #000000; text-decoration: none; } a:hover { background: #eeeeee; } pre { font-family: "Courier New",Courier,monospace; font-size: 100%; color:#111111; } tt,code { font-family: "Courier New",Courier,monospace; font-size: 110%; color: #000000; } var { } /* general alignment classes */ .pcenter { text-align: center; } .pleft { text-align: left; } .pright { text-align: right; } /* layout for the definitions of functions, variables, ... */ div.func { background: #e0e0e0; margin: 0pt 0pt; } /* general and special table settings */ table { border-collapse: collapse; margin-left: auto; margin-right: auto; } td, th { border-style: none; } table.func { padding: 0pt 1ex; margin-left: 1ex; margin-right: 1ex; background: transparent; /* line-height: 1.1; */ width: 100%; } table.func td.tdright { padding-right: 2ex; } /* Example elements (for old converted manuals, now in div+pre */ table.example { background: #efefef; border-style: none; border-width: 0pt; padding: 0px; width: 100% } table.example td { border-style: none; border-width: 0pt; padding: 0ex 1ex; } /* becomes ... */ div.example { background: #efefef; padding: 0ex 1ex; /* overflow-x: auto; */ overflow: auto; } /* Links to chapters in all files at top and bottom. */ /* If there are too many chapters then use 'display: none' here. */ div.chlinktop { background: #dddddd; border-style: solid; border-width: thin; margin: 2px; text-align: center; } div.chlinktop a { margin: 3px; } div.chlinktop a:hover { background: #ffffff; } div.chlinkbot { background: #dddddd; border-style: solid; border-width: thin; margin: 2px; text-align: center; /* width: 100%; */ } div.chlinkbot a { margin: 3px; } span.chlink1 { } /* and this is for the "Top", "Prev", "Next" links */ div.chlinkprevnexttop { background: #dddddd; border-style: solid; border-width: thin; text-align: center; margin: 2px; } div.chlinkprevnexttop a:hover { background: #ffffff; } div.chlinkprevnextbot { background: #dddddd; border-style: solid; border-width: thin; text-align: center; margin: 2px; } div.chlinkprevnextbot a:hover { background: #ffffff; } /* table of contents, initially don't display subsections */ div.ContSSBlock { display: none; } div.ContSSBlock br { display: none; } /* format in separate lines */ span.tocline { display: block; width: 100%; } div.ContSSBlock a { display: block; } /* this is for the main table of contents */ div.ContChap { } div.ContChap div.ContSect:hover div.ContSSBlock { display: block; position: absolute; background: #eeeeee; border-style: solid; border-width: 1px 4px 4px 1px; border-color: #666666; padding-left: 0.5ex; color: #000000; left: 20%; width: 40%; z-index: 10000; } div.ContSSBlock a:hover { background: #ffffff; } /* and here for the side menu of contents in the chapter files */ div.ChapSects { } div.ChapSects a:hover { background: #eeeeee; } div.ChapSects a:hover { display: block; width: 100%; background: #eeeeee; color: #000000; } div.ChapSects div.ContSect:hover div.ContSSBlock { display: block; position: fixed; background: #eeeeee; border-style: solid; border-width: 1px 2px 2px 1px; border-color: #666666; padding-left: 0ex; padding-right: 0.5ex; color: #000000; left: 54%; width: 25%; z-index: 10000; } div.ChapSects div.ContSect:hover div.ContSSBlock a { display: block; margin-left: 3px; } div.ChapSects div.ContSect:hover div.ContSSBlock a:hover { display: block; background: #ffffff; } div.ContSect { text-align: left; margin-left: 1em; } div.ChapSects { position: fixed; left: 75%; font-size: 90%; overflow: auto; top: 10px; bottom: 0px; } /* Table elements */ table.GAPDocTable { border-collapse: collapse; border-style: none; border-color: black; } table.GAPDocTable td, table.GAPDocTable th { padding: 3pt; border-width: thin; border-style: solid; border-color: #555555; } caption.GAPDocTable { caption-side: bottom; width: 70%; margin-top: 1em; margin-left: auto; margin-right: auto; } td.tdleft { text-align: left; } table.GAPDocTablenoborder { border-collapse: collapse; border-style: none; border-color: black; } table.GAPDocTablenoborder td, table.GAPDocTable th { padding: 3pt; border-width: 0pt; border-style: solid; border-color: #555555; } caption.GAPDocTablenoborder { caption-side: bottom; width: 70%; margin-top: 1em; margin-left: auto; margin-right: auto; } td.tdleft { text-align: left; } td.tdright { text-align: right; } td.tdcenter { text-align: center; } /* Colors and fonts can be overwritten for some types of elements. */ /* Verb elements */ pre.normal { color: #000000; } /* Func-like elements and Ref to Func-like */ code.func { color: #000000; } /* K elements */ code.keyw { color: #770000; } /* F elements */ code.file { color: #8e4510; } /* C elements */ code.code { } /* Item elements */ code.i { } /* Button elements */ strong.button { } /* Headings */ span.Heading { } /* Arg elements */ var.Arg { color: #006600; } /* Example elements, is in tables, see above */ div.Example { } /* Package elements */ strong.pkg { } /* URL-like elements */ span.URL { } /* Mark elements */ strong.Mark { } /* Ref elements */ b.Ref { } span.Ref { } /* this contains the contents page */ div.contents { } /* this contains the index page */ div.index { } /* ignore some text for non-css layout */ span.nocss { display: none; } /* colors for ColorPrompt like examples */ span.GAPprompt { color: #000097; font-weight: normal; } span.GAPbrkprompt { color: #970000; font-weight: normal; } span.GAPinput { color: #970000; } /* Bib entries */ p.BibEntry { } span.BibKey { color: #005522; } span.BibKeyLink { } b.BibAuthor { } i.BibTitle { } i.BibBookTitle { } span.BibEditor { } span.BibJournal { } span.BibType { } span.BibPublisher { } span.BibSchool { } span.BibEdition { } span.BibVolume { } span.BibSeries { } span.BibNumber { } span.BibPages { } span.BibOrganization { } span.BibAddress { } span.BibYear { } span.BibPublisher { } span.BibNote { } span.BibHowpublished { } utils-0.94/doc/manual.js0000644000000000000000000001011315174515600012114 0ustar00/* manual.js Frank Lübeck */ /* This file contains a few javascript functions which allow to switch between display styles for GAPDoc HTML manuals. If javascript is switched off in a browser or this file in not available in a manual directory, this is no problem. Users just cannot switch between several styles and don't see the corresponding button. A style with name mystyle can be added by providing two files (or only one of them). mystyle.js: Additional javascript code for the style, it is read in the HTML pages after this current file. The additional code may adjust the preprocessing function jscontent() with is called onload of a file. This is done by appending functions to jscontentfuncs (jscontentfuncs.push(newfunc);). Make sure, that your style is still usable without javascript. mystyle.css: CSS configuration, read after manual.css (so it can just reconfigure a few details, or overwrite everything). Then adjust chooser.html such that users can switch on and off mystyle. A user can change the preferred style permanently by using the [Style] link and choosing one. Or one can append '?GAPDocStyle=mystyle' to the URL when loading any file of the manual (so the style can be configured in the GAP user preferences). */ /* generic helper function */ function deleteCookie(nam) { document.cookie = nam+"=;Path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT"; } /* read a value from a "nam1=val1;nam2=val2;..." string (e.g., the search part of an URL or a cookie */ function valueString(str,nam) { var cs = str.split(";"); for (var i=0; i < cs.length; i++) { var pos = cs[i].search(nam+"="); if (pos > -1) { pos = cs[i].indexOf("="); return cs[i].slice(pos+1); } } return 0; } /* when a non-default style is chosen via URL or a cookie, then the cookie is reset and the styles .js and .css files are read */ function overwriteStyle() { /* style in URL? */ var style = valueString(window.location.search, "GAPDocStyle"); /* otherwise check cookie */ if (style == 0) style = valueString(document.cookie, "GAPDocStyle"); if (style == 0) return; if (style == "default") deleteCookie("GAPDocStyle"); else { /* ok, we set the cookie for path "/" */ var path = "/"; /* or better like this ??? var here = window.location.pathname.split("/"); for (var i=0; i+3 < here.length; i++) path = path+"/"+here[i]; */ document.cookie = "GAPDocStyle="+style+";Path="+path; /* split into names of style files */ var stlist = style.split(","); /* read style's css and js files */ for (var i=0; i < stlist.length; i++) { document.writeln(''); document.writeln(''); } } } /* this adds a "[Style]" link next to the MathJax switcher */ function addStyleLink() { var line = document.getElementById("mathjaxlink"); var el = document.createElement("a"); var oncl = document.createAttribute("href"); var back = window.location.protocol+"//" if (window.location.protocol == "http:" || window.location.protocol == "https:") { back = back+window.location.host; if (window.location.port != "") { back = back+":"+window.location.port; } } back = back+window.location.pathname; oncl.nodeValue = "chooser.html?BACK="+back; el.setAttributeNode(oncl); var cont = document.createTextNode(" [Style]"); el.appendChild(cont); line.appendChild(el); } var jscontentfuncs = new Array(); jscontentfuncs.push(addStyleLink); /* the default jscontent() only adds the [Style] link to the page */ function jscontent () { for (var i=0; i < jscontentfuncs.length; i++) jscontentfuncs[i](); } utils-0.94/doc/manual.lab0000644000000000000000000002036415174515600012247 0ustar00\GAPDocLabFile{utils} \makelabel{utils:Title page}{}{X7D2C85EC87DD46E5} \makelabel{utils:Abstract}{}{X7AA6C5737B711C89} \makelabel{utils:Copyright}{}{X81488B807F2A1CF1} \makelabel{utils:Acknowledgements}{}{X82A988D47DFAFCFA} \makelabel{utils:Table of Contents}{}{X8537FEB07AF2BEC8} \makelabel{utils:Introduction}{1}{X7DFB63A97E67C0A1} \makelabel{utils:Information for package authors}{1.1}{X8508AD637B79CEE8} \makelabel{utils:Printing Lists and Iterators}{2}{X83686EE47E4D4F66} \makelabel{utils:Printing selected items}{2.1}{X7F6817927F86240F} \makelabel{utils:Lists, Sets and Strings}{3}{X7AE6EFC086C0EB3C} \makelabel{utils:Functions for lists}{3.1}{X7C3F1E7D878AAA65} \makelabel{utils:Distinct and Common Representatives}{3.2}{X82F443FF84B8FCE3} \makelabel{utils:Functions for strings}{3.3}{X8033A2FE80FC2F2A} \makelabel{utils:Number-theoretic functions}{4}{X86E71C1687F2D0AD} \makelabel{utils:Functions for integers}{4.1}{X7D33B5B17BF785CA} \makelabel{utils:Groups and homomorphisms}{5}{X8171DAF2833FF728} \makelabel{utils:Functions for groups}{5.1}{X7E21E6D285E6B12C} \makelabel{utils:Left Cosets for Groups}{5.2}{X7FE4848B7DE6B3FD} \makelabel{utils:Inverse}{5.2.2}{X793E48267EF5FD77} \makelabel{utils:Functions for group homomorphisms}{5.3}{X80A512877F515DE7} \makelabel{utils:Matrices}{6}{X812CCAB278643A59} \makelabel{utils:Some operations for matrices}{6.1}{X802118FB7C94D6BA} \makelabel{utils:Iterators}{7}{X85A3F00985453F95} \makelabel{utils:Some iterators for groups and their isomorphisms}{7.1}{X7BB5350081B27D17} \makelabel{utils:Operations on iterators}{7.2}{X85413EED812C6497} \makelabel{utils:Records}{8}{X7AA1073C7E943DD7} \makelabel{utils:Functions for records}{8.1}{X82B3D1D583CDF0E5} \makelabel{utils:Option records for functions}{8.2}{X7E6207B47B9AA30C} \makelabel{utils:Web Downloads}{9}{X815B0C4B7EBE6E1E} \makelabel{utils:Functions for downloading files from the web}{9.1}{X8758CB7F79EFB6ED} \makelabel{utils:User preference DownloadVerifyCertificate}{9.1.2}{X85182BA486E3C2AA} \makelabel{utils:User preference DownloadMaxTime}{9.1.3}{X79E10E5B83EF929F} \makelabel{utils:Generalized Straight Line Programs}{10}{X8314837E85D3D052} \makelabel{utils:Functions for Generalized Straight Line Programs}{10.1}{X7D1B00C979C8AEFD} \makelabel{utils:GeneralizedStraightLineProgram}{10.1.2}{X8503408985150E37} \makelabel{utils:Various other functions}{11}{X83EFC3178180D918} \makelabel{utils:File operations}{11.1}{X81A0A4FF842B039B} \makelabel{utils:LaTeX strings}{11.2}{X84D2922D87EDE9E9} \makelabel{utils:Conversion to Magma strings}{11.3}{X79F021B1830B68F6} \makelabel{utils:Obsolete functions}{12}{X7F561B1D803182FF} \makelabel{utils:Operations from AutoDoc}{12.1}{X7A6BB3D084912F35} \makelabel{utils:Functions for printing}{12.2}{X86F322FC7DECE36F} \makelabel{utils:Other obsolete functions}{12.3}{X84A4F0B281FA0F94} \makelabel{utils:Applicable Methods}{12.3.1}{X78B7D1A982BE9866} \makelabel{utils:ExponentOfPrime}{12.3.2}{X7C1AF2467FB55D79} \makelabel{utils:The transfer procedure}{13}{X84AC9613842F014C} \makelabel{utils:Bibliography}{Bib}{X7A6F98FD85F02BFE} \makelabel{utils:References}{Bib}{X7A6F98FD85F02BFE} \makelabel{utils:Index}{Ind}{X83A0356F839C696F} \makelabel{utils:GitHub repository}{1}{X7DFB63A97E67C0A1} \makelabel{utils:PrintSelection for a list of positions}{2.1.1}{X784638AC84D49870} \makelabel{utils:PrintSelection for a first item and a step}{2.1.1}{X784638AC84D49870} \makelabel{utils:DifferencesList}{3.1.1}{X78B7C92681D2F13C} \makelabel{utils:QuotientsList}{3.1.2}{X7975371E865B89BC} \makelabel{utils:FloatQuotientsList}{3.1.2}{X7975371E865B89BC} \makelabel{utils:SearchCycle}{3.1.3}{X86096E73858CFABD} \makelabel{utils:RandomCombination}{3.1.4}{X7EF06CAD7F35245D} \makelabel{utils:distinct and common representatives}{3.2}{X82F443FF84B8FCE3} \makelabel{utils:DistinctRepresentatives}{3.2.1}{X78105CAA847A888C} \makelabel{utils:CommonRepresentatives}{3.2.1}{X78105CAA847A888C} \makelabel{utils:CommonTransversal}{3.2.1}{X78105CAA847A888C} \makelabel{utils:IsCommonTransversal}{3.2.1}{X78105CAA847A888C} \makelabel{utils:BlankFreeString}{3.3.1}{X870C964E7804B266} \makelabel{utils:AllSmoothIntegers for two integers}{4.1.1}{X8191A031788AC7C0} \makelabel{utils:AllSmoothIntegers for a list and an integer}{4.1.1}{X8191A031788AC7C0} \makelabel{utils:smooth integer}{4.1.1}{X8191A031788AC7C0} \makelabel{utils:AllProducts}{4.1.2}{X78BE6B8B878D250D} \makelabel{utils:RestrictedPartitionsWithoutRepetitions}{4.1.3}{X845F46E579CEA43F} \makelabel{utils:NextProbablyPrimeInt}{4.1.4}{X81708BF4858505E8} \makelabel{utils:PrimeNumbersIterator}{4.1.5}{X8021EEE5787FCA37} \makelabel{utils:Comm}{5.1.1}{X80761843831B468E} \makelabel{utils:IsCommuting}{5.1.2}{X803A050C7A183CCC} \makelabel{utils:ListOfPowers}{5.1.3}{X87A8F01286548037} \makelabel{utils:GeneratorsAndInverses}{5.1.4}{X820B71307E41BEE5} \makelabel{utils:UpperFittingSeries}{5.1.5}{X84CF95227F9D562F} \makelabel{utils:LowerFittingSeries}{5.1.5}{X84CF95227F9D562F} \makelabel{utils:FittingLength}{5.1.5}{X84CF95227F9D562F} \makelabel{utils:Fitting series}{5.1.5}{X84CF95227F9D562F} \makelabel{utils:LeftCoset}{5.2.1}{X8340B4537F17DCD3} \makelabel{utils:EpimorphismByGenerators}{5.3.1}{X80C9A0B583FEA7B9} \makelabel{utils:Pullback}{5.3.2}{X7C705F2A79F8E43C} \makelabel{utils:PullbackInfo}{5.3.2}{X7C705F2A79F8E43C} \makelabel{utils:CentralProduct}{5.3.3}{X78DD2C617B992BE2} \makelabel{utils:CentralProductInfo}{5.3.3}{X78DD2C617B992BE2} \makelabel{utils:IdempotentEndomorphisms}{5.3.4}{X801038CB808FC956} \makelabel{utils:IdempotentEndomorphismsData}{5.3.4}{X801038CB808FC956} \makelabel{utils:IdempotentEndomorphismsWithImage}{5.3.4}{X801038CB808FC956} \makelabel{utils:DirectProductOfFunctions}{5.3.5}{X81FA9E6C7F3B9238} \makelabel{utils:DirectProductOfAutomorphismGroups}{5.3.6}{X7CB2D5F27F4182AF} \makelabel{utils:DirectSumDecompositionMatrices}{6.1.1}{X787B89237E1398B6} \makelabel{utils:Iterators}{7.1}{X7BB5350081B27D17} \makelabel{utils:AllIsomorphismsIterator}{7.1.1}{X7F8B54D1806C762D} \makelabel{utils:AllIsomorphismsNumber}{7.1.1}{X7F8B54D1806C762D} \makelabel{utils:AllIsomorphisms}{7.1.1}{X7F8B54D1806C762D} \makelabel{utils:AllSubgroupsIterator}{7.1.2}{X831DA5AE8437578F} \makelabel{utils:CartesianIterator}{7.2.1}{X87395A9181A35301} \makelabel{utils:UnorderedPairsIterator}{7.2.2}{X7C95E27987A812EA} \makelabel{utils:AssignGlobals}{8.1.1}{X84D82EB579B2ACCD} \makelabel{utils:OptionRecordWithDefaults}{8.2.1}{X8322B9377CC590D2} \makelabel{utils:Download}{9.1.1}{X7A7438AE8448635E} \makelabel{utils:DownloadVerifyCertificate}{9.1.2}{X85182BA486E3C2AA} \makelabel{utils:DownloadMaxTime}{9.1.3}{X79E10E5B83EF929F} \makelabel{utils:IsGeneralizedStraightLineProgram}{10.1.1}{X7D6F31797B8C3452} \makelabel{utils:GeneralizedStraightLineProgram for a list of lines (and the number of generators)}{10.1.2}{X8503408985150E37} \makelabel{utils:GeneralizedStraightLineProgram for kind and list}{10.1.2}{X8503408985150E37} \makelabel{utils:DataOfGeneralizedStraightLineProgram}{10.1.3}{X7C5BD3777DBBB390} \makelabel{utils:NrInputsOfGeneralizedStraightLineProgram}{10.1.4}{X7F47B79F7D7A51AC} \makelabel{utils:NrOutputsOfGeneralizedStraightLineProgram}{10.1.5}{X7EFDD9F07F3AF218} \makelabel{utils:ResultOfGeneralizedStraightLineProgram}{10.1.6}{X785C69E2789B3985} \makelabel{utils:EquivalentStraightLineProgram}{10.1.7}{X81E725087E481727} \makelabel{utils:IsInternallyConsistent for generalized straight line program}{10.1.8}{X85E5CF147DAD5FA3} \makelabel{utils:Log2HTML}{11.1.1}{X7B7ECADF85F748BE} \makelabel{utils:IntOrInfinityToLaTeX}{11.2.1}{X85F11FFA7F036669} \makelabel{utils:LaTeXStringFactorsInt}{11.2.2}{X7DC642B97CD02F4E} \makelabel{utils:ConvertToMagmaInputString}{11.3.1}{X8768D7707B4CBBD4} \makelabel{utils:PermGroupToMagmaFormat}{11.3.1}{X8768D7707B4CBBD4} \makelabel{utils:PcGroupToMagmaFormat}{11.3.1}{X8768D7707B4CBBD4} \makelabel{utils:MatrixGroupToMagmaFormat}{11.3.1}{X8768D7707B4CBBD4} \makelabel{utils:FindMatchingFiles}{12.1}{X7A6BB3D084912F35} \makelabel{utils:CreateDirIfMissing}{12.1}{X7A6BB3D084912F35} \makelabel{utils:StringDotSuffix}{12.1}{X7A6BB3D084912F35} \makelabel{utils:GetSuffix}{12.1}{X7A6BB3D084912F35} \makelabel{utils:SetIfMissing}{12.1}{X7A6BB3D084912F35} \makelabel{utils:PrintOneItemPerLine}{12.2}{X86F322FC7DECE36F} \makelabel{utils:PrintApplicableMethod}{12.3.1}{X78B7D1A982BE9866} \makelabel{utils:ExponentOfPrime}{12.3.2}{X7C1AF2467FB55D79} \makelabel{utils:OKtoReadFromUtils}{13}{X84AC9613842F014C} utils-0.94/doc/manual.pdf0000644000000000000000000113154615174515600012270 0ustar00%PDF-1.5 % 171 0 obj << /Length 427 /Filter /FlateDecode >> stream xuKo0M' %).‰a(wDS\MeAڥTcS8aW$K[]V tݺ80C< }9qR{??|mRe,A%XmZz2@VH!⟥ &c7STWU8(U=~II%]%*/!_';D OuֽO/ͫ endstream endobj 181 0 obj << /Length 753 /Filter /FlateDecode >> stream xVn0^En+K}HUt&$%Y`Je4e{=>.ʐ.z'I9C4xz(!87ȃ Q2E_(Jn}Ky.nlVP|..!H 2-I*-nav]EfYEȔ!j3W@x#CfNQED²mBҜ0oلc/hP2u*ڐ!0׋Vr!~8 kKU:B8iW̽)`RxhʌpQhp ./׿@fJ*TG9?9tuafN?,D58UX$e 5dȻ ٙ[ld~OʫmDC9Ya4eQ~%>z*+\UG:W-vJ;@_'Ϋiag,_r=VΖB1a9 i_s;~ B7jngبZ>ZI-%hX)YJJG#ٕmkRDg3rVq,F\j0IjII6rH5J-FP :[Mk}-*ِ>޺i{46h+`mPF;Y;k$.yKQ1)7hI[eɥ}l*~R7I;OKF+TSt0ER6h"ZжBW Y r+ endstream endobj 2 0 obj << /Type /ObjStm /N 100 /First 831 /Length 2215 /Filter /FlateDecode >> stream xZs۸~_?;;8inH%QCRq҇--QDɲ$.vXL0b,Bdz<8F3'=V1% 1e7)˂LA1IoDF!(;5X2-Q۸6 &SQ`J рaQ0㙊a4e֠1R<5seN2&w5 J%8t*TBj 豅>['b#0#bZPO"j$u0văk x0D'k#a#i Lc$Q@%aiMr`!c -sbܸf}3.ڈ~n f/j[{|6zxZxz)lzۈiTԤד_BI OEY ]s?֞:7]x[^7W K[&PjMM]lk a?avUp7WS1϶9er#jm9Tv?'ĭIbsYl;^Kr8a8drmםdunйUr! }K|wd-Ĝ[#g[)uxZ}-xX%ې^ڌ[b\sZ?63ƀׄyVbMnH()(jevçڽԧ/m{j?h!yi{_ )Zsi얾ly]\}ZRڷMߖ?b|lH>uM36顝_gYsn^6>M1n#x z3wu-8ڷťpk6H>]SkE6gNDžJB kr|܉~LR}Jzi'zt\Ljd'HlwӢ˨>M} W2%I9D`fy<'sn4ڡah9yn3B1v֠6DD{38;gUdvj| 5aj8όn] =zVYmg~VڊY-gLɳ3yv&ٙ<;g-1PDo6+uK>zdE) 15eJ9Nwn6:b`|W3DkG.( QT$QRy~_O6} |;BTjV%&[f]Κ!rR=oAqFI4<\`6=ioZ@YxpT ޡȕk,5nEܭ>EzezY?Uh:ՙ~OI9=o t`(.qH z>o38]B$`]t:=xLʔ', B 5qyE}65\ C80M.,Izg'^bVe(xT잹pg=`Y7><ot2C2iT9qKɓG8)qZyjc΂@ט[8IUK[~ endstream endobj 192 0 obj << /Length 1293 /Filter /FlateDecode >> stream xڝWn8+&)f6L"踫 YmhT}/_*mE 7CۛͫJJT$}B$ɶK>^},!ոh*pbnpP`e93ʂ$@+۝6iͤF5ɚRDY# v " >̘>@@jM+\"}VBoh^*e!%Hǡ5B8X"mNR_`O%ngok^.Pme.n9reqɚ@p18g-C:\V(_=@\a7lp'W;y}W;S$UX=-vL?Kz4G4r꬜w;\ݷp49同sg>,$bMPU?D*ffbLFTQ@ P_q~kP"g%_̝\toz-1sgl)qN5bE^պdeY*NUPP*p_qL+N0K'i4jyo#N*F7G`lrJqm+.ƮXN_Q:$s{2*nEb.6ejo,4ߨ*dJtV&y/r&[0ǝ ha$췌[SHK y1hYǝ5lshk_Vƍ7?Bgd Yi|Qp` ?т ?3²j~@NbBmcJPn쐬(!)ekWIT˽_?AT"Gjm.YԽ.v+axFeN76$;Sq:]WVO{w>x!zWMoYޏ^~VPVhnҳm[V `ž77'YUʅ`0a</u]W wo$ Nd(OCVpWTKϋ2HkcϻnEvY}TiX%4-ҺdY_ @߾#嬹sh(o]e6307Xݽ&Vqjx:Γĵ,˷ݨQl}g@7(Ntez27PW98hj\n;z-b-QVdP1wWXٮ4<)lQDۛႅ endstream endobj 232 0 obj << /Length 972 /Filter /FlateDecode >> stream xYn0+xJ\h.H ،,ԒIn~}NI@\ՔG3!H3o_/FB fw@8&xSj} Ft_((0zY+ЛDv|ٴaHDg"#dNAh4NY/h /eit\Sy_2H\HOYZh(YICl^y{Ti3D^JP*qPjW{^׆G JDj8b_mpBee C.o gsKo,╾/ue+'?'ڃh&r!Or册*_PlÇØiTOf,Bdv "N^NB6>@nRC'*&q('.yr3O~;-|U3ZOŌq#[>bb6)[q+oeNR6Taqɢ`T{W6JDjeF#?zu; c\3JPSh ;u⾩2= + aI=¥["USγd̬!9/0sN آI_hx)Jk\m jTcHJ?hS~SHGGy\ ܣ#)ϗ(:,з]o񐯊ا &F,qQ eQ4͚7J["Ďn"G0"Cp75չI~\bdY۵gKWKkJ!㭒;*E}S^&U28P7L` 7,Z endstream endobj 246 0 obj << /Length 600 /Filter /FlateDecode >> stream xWn0+xbXI-Z@ЃcӎG $2%YvB} bP-Ati,4R(BQ@L+LH S)W"~Q 1I̸vPٌH`'|ؤ..%\`-EJip&H =%16,+) adr{k&TFyxMTb.%c ˟}Z:7Oap?t/ ZX{֛BC-N)AKϛcRc̯kP(aD]3wu9a3p(UR]- IS #ڦyN}vY $Sټ!]@#ú4+M1]NbLc63:s\UU1z˛7y.ږlw%Ŏ"vą\rf7}qz 7\)z6nrsҷƮEr OP.DW?[ֹJ_җ2f¶fv @ϝ:`T-o>O)H{fs>Nxv endstream endobj 258 0 obj << /Length 2029 /Filter /FlateDecode >> stream xڽX[~_!4/.v$mv]ͱDWf2=G쑬ً>(Ï߹`_/% 8%Qep}BdD4f2/36r%46x I `$a%3i67u"`4JAB:8y>a)ISIټhܴ(.:ZU[=_Tv397p܇i7rcj7mѸo7)n\T~2ǔ0&{~@^ak܆+o^ B$A & Z6">4y-#Y޸wsFgޭϭ?ffzTl\h(ܿ^R;Y yz}N4m1W63u P gJyXhI's/tF*OY1~RH'w<$ xW .V6;hߗps/t4`=?iLLuy 6 ODw.eLd_tdʥ$x0!"U } @S_d=!Iz$A|+0i HEhVǫ ' 1uxzo/q݀Bq2Ty;$;Q|xLӞgw]s| Wxw1^eNswP<"i|4OnyBBr©! c3y!Z"d '֕ZU͍랦\h 8Ԁ7"`F!0%5'Ϝ$:wVu BpQ;>'`lȞupO֦9]$;NU: ~QRM &i:3%YV}QΩOTLeڿun/Xa "3S1I>ɫі*Uy$g>ɤKy=r!3 u XuIL_*PgcOtچ oXy;zҏ!b~ӯ G Ϯ~d/'gԽg3Um0g49bGݼ+T\>81WGm<9φwOo'g="X|d!5ՋYxhc+]5pT箺/rH m 8CXUO:bw :KT&>3߽tIv@ K7K.j2XDN$F>6{>1+J?d#}nǪ+ {I HyەӬօV>dTGfy\B޽0ffF'03wOUlDYGR&MDIe2A꒘zc$ÞGY*igF7GS)|QA)Srh{?d(RH `"ܽ]&62TU)bIHY/\L.eתrW^VP5RdpȰyLG] o)%ĿC*yM~!*rzO}`P8FR*dD]t5VNI ;lg8T 2pxmZ@ 9!^:a*@rN}^ (D:@ Hn]R}p[^ wiYg~ڀ8ߦ@POx4^Yi|Gŀu_5ỏuqE6! ʆ*+L]-{n%|Cgwz]3^x+e 0b*{:yBd\ 贛>̧| endstream endobj 267 0 obj << /Length 2335 /Filter /FlateDecode >> stream xڭY[~_!lv^$JJvM) Ymuuqtt}!ex2`s|y x/wW|%AҘn$f<-X*n|^ }Qv׿}U 8KyJfR%@Ӹ;~0z,RQ@>>ƒ >LIpowVHc]tO1LZj5NRE,~:J0㬤`BL؊OdiD¢PA:+KýoEN>b䍖lӔPxܰ\EMm}ћZ|Kfad6Mgq|jB WS3N\zBb#_E8atn\?@+&,t!-L6mG5 v~ŸE>E^К3`H?M! %Pifl8SXZ"jz0(hﳞFۡ;Eg'X_UVYyJ"k|h[S{iС&7]GfKK{۬^$.nf8ԖUZ8ҫmTFlak67xf35b"C5>4YB$J. N=`Vx qg5-];θvQ0f!D% kuD3+*jmLMvT: j?*lc6PXૻ,n Fu6< |(<`NwPKTT B=i|ތ=z{ %i-9$LqAAĉs V/G&ow0ǰ=e+L$|vCgk,ovq2Zx"xUN/ho~W,Fd|zb߻\ jgɺ+5{JvEԛbCcuJSO"H Gg)m %ˆyMBy%b]m%DLѲE&82t&Uۻl"<> XynD$v&ҿDtN9)TYQ>=/ !&c 9G/)z?z5wlڍlQA MXǘ)usO+T uC=)>ee͈idEifג~Dʊى2{oLP*K[ƔT5~Rm#/ ёo(F6.UɵJ 5wA{JZ훡8eIk/n` &Pzp5`Oo=$9ǎMbZ˘2@ۛ#n]ͱ*{>"riJ)^-99hiGw`C yڢ xg#'(_MyWKH|@8膟Ocz"ΖhSu$7eì3bʚ5 Y0f^N2z'qWq9F}Qll$δC2߿,4ix<,fq(طJ:LA{5C@ QJKZj`wLkZ :'ӚiX>^mv 9OvNbx4KsK1BhRLt?.* ($+]SC]o!`b9q[QBH9V R4d3'i0O@١ؖGRgK38E"|>0. }v'E_e@sP'~R'yr endstream endobj 274 0 obj << /Length 1646 /Filter /FlateDecode >> stream xڽYnF}WQ."1Z-S6 RI7Je;tݝ33gfi&490r1yYЄQ"%2Q.)pfr]mj6gN %46ٿr6M 4h~?loxVM/_fS^XPm )da[PHؖݒ9PJUh huO4OCMө|qty_.bS&Uqm wympMQhf07Y"N 7eNX{ۼ/y:qA|WRkp"n=Vw;QydE ~-H1" l1ѝq9Gm1cbolDvSu:@oNZ:jР6=m(z~UQUN`#egF* M%Vv Fsdms[WХE@ks(`rN٠u,GEa6VCձe}5 9P f`Y$CdFE;Ѯl.U${[5UsnxTMД6*0 8ِTn޹ny-b>%{loZNo&PED~ ᪫+TzI1!La:0#̓-&=y*C`_y%\o8Ha>; ҎA-WSv{#WXգw(q@-{?k ح%XI/XeUYm*&.&L`᎝4 JMn6[Hu:yp3טF6LUr>ӷhzɤcdVe _ޮ`ΰ/5; UyfA8wC=[D%>;ŮZ2c 6~ #7Yl?VW%Չ+0nV̈-qC8\(C_}[(gs,moq]0@⬧qĞ:D@k#Fk`5Q,c Ka~z&+? lί<^]w8Qi.vW%跳=;itN9)~ʣ,XG$ ϩZjr {Wj4.ŢU&6tBK)Bq1Zjr(pTD/UT]]{]pTuRZiYc*e%FEL*wU)G4-\r-9UPϩeJrCpOL0}(y)_ \-> stream xZo6~_G+Z`bE^--ʶQ$eӒ(V=!%QwǏϡmB#꯿\N$M%J1\L2Qg&I.oXNR&O.>(I[&{L5JTwgju}.kT-gA.F"'(-Jx:arÛ:\1RLM㺗_g)b ٸ("rY&J 5Z=%YqMZwq4ͯ %`T˰$ $yѴ)'{ѩ?| 5ߴr R 53qq7 3 ?(j+ܚ._o 2$f蟊yZfxd,2•HR ϔߪиʿLފq=e)1${LL 8' 2-KDQ>ؕ  6x .*~\Mݪ.`W'5zBjF9ԢhbFAEA4q\N5W}C &;P- ̷43 Yfk][aq#!8 7힃s^Y6XKFTS?6mx& I#49(P!e iֆasrR)XTW4P76mx%a(C5hŰY2tVR9{DmPŎ9Zq86 0q. xx`oޭ!aTƛXƘQ8#bͰE5+Pe";5 ),MSa> stream x[mo6_f z~p}%j6VZɻZC (r8!9Ý.ɿOyuЉBFa\-9b$JdOu.ՏИ%#kMD5mNNGXyH1(J4=\d~L0bF'5-lkZd|>#n m]ү&1H*Z$jJC]S4 0>TUZu}Y_K Kާ(4h$89!07σG8ڙЙ+$OsٰͶr7 DGk=0\%+LaRO)s@'n<==B9u70lhD kFX"Kx*$?ݤ҈RWmc!'gQ4BC%ERO")U}V%|Q }AD8rIYa>Oh Or$b OYx !e)%'!I% у-& -a"@ Z;`aX 41u"O@61N?tvu{n l^/N)?yƺgl7to:,= ScBmaHox^Ĥ W*[UoLx~i_PS9}oWWYY/*ٗ.w*~&{?]| 8F֍BN11R Yke\}t]UKWi9w_ŗS|}qt%5#l S4}\峢H}]GIHs@C7(j/45ϗŭ%äBQWO߾}3|٢Hr2vSؽ8FpXoYyUrW[̗j\$V]QEy窪VFSV63gxj¿9-pZgz|U2oZ*޹{;R<4 /ZUW&21ȜUwe-H|=Zҍ)~0##FH+dT$ãR{#Ôdzpqc/9^ "(UcQ+Ox_Oyq)y|Q8kr]㙲Z UQ8W/U;jp-DSGSj\A*3HBm ݇?.-I}i.^Y"@D MulnWrsyMC54̏w8CY|,CMQpj> d!cpc4E[< {f,gs*ӿ '<\P ^_NVj0!Tv,V0=mPdGn|BL4 ybNB^ "6%ZM̀'MqŒ@̗R3k7Ӹ W3DKJ7^C|.Us#{5aatWv3=l[0rՠD{[<M$$"QGEu~p~K~a2=3DeZqZX-F8iϞߙ1R/1V-̀,io[#j%q4%HX.}G1! %4(2|Da(`flX O9 |m@v.8 n;}RHU7@vN Ӱ8x 1K]8lt/xx(i4Z!Ao-.;m FR6awDfߑ*$@q>yaoAˬ#4"Zr謺673>ȫ|*k&ɕ&u TK\# ho2ڈi;1ZwO6ۥt'Bື|?cmUܭ@q5bbY#-RM endstream endobj 197 0 obj << /Type /ObjStm /N 100 /First 893 /Length 2467 /Filter /FlateDecode >> stream xڽZnG}Wc`{*6EkA ,"SÖV!%Aft*ਨ#E1;cq)R]Q2aTWkrV ')8B %J6cO(6fc6S &0Ah!r\jF am b).lߪ.V spĞLN@XN/ LjWt1<.~~4˽ ڛ/.!VVˏ/.q1sKk?-O#û9nLɳ{K}|y`IaX2.쎏'tg{կrCם}:XOϧO_`ˋҟ??O47$.P&GR]O8[~zo:uOٟp碻Zl&u۳\ڇR%0k隼PjIJcwt׮yfr>~b~̍G, ׊V*r|@CbCQ,W dd~  W?u95a~vWﶬUa"$^BuVH IVo 򺗗S ʼnLZލ;yJy ̾ϰ~dlc|tH6'*G>E8::K+X1R=8 :d|k0ʘ4&H aX!=z8h Qh2h =@^ xT-z)Q Fa`sI=ƏOK `AQ2pM[7r v$+ RoEn8km[pwmb8i @})@ uߏIUo6ڀjRF ũU8߯s"+;UGjyʤ{eRӞeRZV=meOƱc)s!+}aGP?X`#2AG䙺Yb1] V5RuĎ"X> stream xZYo~ /2 } ywg 1p$ZF<-^MY63l꯾:(\N2 !#FI$Av܍bY\~,!llʐ M#ιAO]?CDQ(duqw)C3:fbʾL>_MbTUAI&?Ӡ2iYr3!8h F7HT ,K9F #x ϒO7=aM‘4#u`19 .[H?iW[v6oeVXl!9m_ Zmam^ٿ>bNGco(ADPيL9+5ǶL?> -ҪS:cVuJؘǶL~NI_#yL-&EŵkMN'VphW3ɉiIՓZUpź{؅\͟.\wZp8;6;`JdAXzբ}Oƃa"͠$nAkn|>ݿo 9)mffq1ϦyqtG_>Ou'H(OJ8c5. 1RP6Up@_XO"HSz2מTr⎇;VQ+L TG6oK2*>|tƧ 1'rIsdm22vk:4^K=܁.5T`0]#aݯDh^ڀXY`'*y/wŅ(<.L $J9o= eõ+/>Xs;97[;F4o,š$1 svDžX'҆A'#p̺kbʞD D_)6ϖvV*y7_vXB7m?u endstream endobj 316 0 obj << /Length 900 /Filter /FlateDecode >> stream xڽWr0+4]%3XՕ,قf Cɮt&rH`s t,ѹW #+,z=/dFRSd^%Tp !!%5M=GcAQʹJP XƌKq"rH,$͔N EiՊ/g16-u1lRLj[#p+R: )Bw)&}M r~Lh GC=O[6g&w^Q@Wye4rƂ=AhN+BZ>yB#öYoPGR& Fѷ6&L!>\6fd)tF~8-RZ }!kWN[B( v|3703vR J'~j3(q<N5g 2 @H-݆[Ĩh.g#c֚J(^WQ[A/f-XX{J~0Ŭ*Ax,|c{܉t ]-q 'xX<ONw>=W~< NEdL¾{y}*yo} @o8dE#R`:RΎHdTKO% 4M}]l[y ݜ!BqtTAT qm8&oN!­F`x>!Ix& :\ endstream endobj 324 0 obj << /Length 2011 /Filter /FlateDecode >> stream xZ[o~ϯУ ,w8ڢbQl@(JwPX;^Ùo.Bo/hxpuI FRLWVDrY( 3[\דu[5t"7W?_PB<h1LXb{~<-?";1pirfIǪn`&U;?nyxI PJ8:yW\t&729NU[=T͘@,$aܦݏe]ff@'u.RA&!PbFEѨd4~m5:Y'P/"a$h/"\&jBiGiGE˜Ls*ʼnUypۉ["!L!a-+-'*M5|ǣXUڦ\mŠ^ѺT>T^bm0A'>).>)Ga':sBajo*ܾf+\ڭ }cL^rDqc:(3} -/E$j ͸=\,ĺ۹6NANdϘEI\U0&:?Epz08KUN[`?^>)wX [ [3Jd$.Žk!{m7eolXi4e] fߝŮp'Ln\ݍM eJbi}3l¾hlTW련?kvEͥDԮVm36m4Dqȁ>}R7@BoNw1M/7}@]WaYE_uhӦskԑl]cV!S-7UGIg X?60hj]A+mQ1yڢ9AemѯzpN)G ,7S>`s}BO'0Wg$v K~Jh8R<> stream xZYo~ {>dMb1q^h[rHjg6>UnJ`E42I nM22}L Qq JW@&ihw1^:&ʍʺxHXY>φz\R ܭmć*JK|k6SpLq4}$ZGsA Es}GS/G@Nh jN}-.jMy1[f,J䥇_ AJ]?jdX0ʶ, D b>g)ā-^.PA uXpc'WPQOpFDM}VVr^ewҢZVu^rlY=79 -'߼a:4^%鴭>ݼ^lԪm-Qrb# s$3Csd3wMo}h \|Z >]Z8&րqag<.k, oie*Ҽϊ"[ɗ!#3\€|~_[gkA`ٛKfx7{^h"akyCV Zm i'|њ*?QrP akfb5ζlJY)T=fv,whNo,svҌX`y.tY*Kؿe)˫}QC"D.'WxdC[NX"9۷Kw"ƀR4ꊝH,V5rK [&Jۍ1Cm ǘiY'-cwm_M8M<~CpwO=22rnRIW+ Ԟ!"D(AR7M:OX6'Gd~ξV Lݭ?V+OۼzݼbGAY:wIq 698IJf`5o2& S1Yb^ʯA)&-f0)XVOӼIAů칊7(Gƌ^ȟcTK;+TiA|>gtxJy+>ݬLS| ~lݗPPzclJ lȀnӑef2> stream xXM6WEB)?Eis( CдmB,ɕ8ɯPj{0Hș{Д %og?/f `5edqG 8#:a`$mm{,`PU7)7gFr2 &Q~Tvs\(o['QqNsH%PgK?ifEʩ5QZ&_neZzm& KnmZ.l" >7QU U]WeEl/mpZA\k`9C0>3/7SA 0b3ldM똙h~v TLE_x(m >%FGU-ϼ]wis2U09&ά갓YUGĻSJEЅbA oPB$M~{O(kȡY vGd#œh B$ 1FQ{eH H4wGxƷ7XtFIf|+Gt\z9 xGkX;KV,-qPbSTv=!=u~>ГQB@'ӏ2\E 1úZ~!̔g;&ќ2FOԙ͎=4y?CEkD|m$%NEh h endstream endobj 350 0 obj << /Length 1450 /Filter /FlateDecode >> stream xڽXKoFWE;uCH-$*$.)єlSbr5yGG=>}8IIE4DJ"D$Ah8nx gw=pTh:(HiERs4a^uzFt?yXg^e,Y|<[fVJ8b\ҠU( D^Zt{N0Q>OV$qi #Di D2Y.k_”` 6%7SwuM/A,mQѪK@Ux!"… aIpi._Fm8gh"L!l1*,m>KJaڕ_i&6MmүxjòfZpVz|cEe6N C)Fs@SçYu1aՏ3|qJ)`!áK Ny@ub^ˮF$yЖ}Ӡ>8-y:mYcŋE!#EFxcp w $K;l*"0}=ef&-{w8w1`c!QH("˧IAFRY b9g9!?za !k+>Ss: "`> zcTNk2$3jkm\ـF  *`BEkFNSD5TFlb9>?͖cTHj]'RNiͿ0`杪?z(bO'ȅLZWfypf7aĐn rpaQPfLi) +L7RT~L8BEh s2Je\ZF|fivugӵ\jb 9 :.$m¯ Ge2 ~8g~[vr0Ie{5>4m`}W6͕C7]s5< v"1C\f({#&NDcЃi\5F92HH&bɯ@o/2?7\$Q5/r݌27k1|g?Ϩk|ivڹ x8{+0؟]CF V)`@ t\F!/,D^&7 endstream endobj 363 0 obj << /Length 2241 /Filter /FlateDecode >> stream xZ[o6~ϯ^ L Z $}NXv:++s=/L9laƔrx|G,?n.~:S(LiF5GLI $$3֑8⚃kD!xp ]G' =)|۠#pa|h[xx5~R1+c^"ȗe-MHecTkLC~9™ TCd($n?l%È}$2"B~."fSYE21 $՘?~?y:2lHsЍj98@m+DC#4)hk +r8,kxH-x9~AKf#w]_vymظ Oh ScjKo !A %H#&[MDy4tH$"@8AIIU2'`6ˆTp񀉠2$t)pԶ9=g6@?=Z ۿ t?2$6KcX{x3x P0ؑ%1ELFOSoOm;7'R˯߻gt_^nU 0@gUV}_yF[X4},vm2`x $-M M0ƃ|iؼYN~^9|?7jv[rjgmfF[SdEo}&bf8R {05)kKDaݍo T! ?]"fFj$c,d]UƨZwe9/˙{m₺m$JZƭŠ(2]-OH6փyd=ٙ5bacn4|Ҋ׭2 C'[ Wpkq&x0 g;M%DɞcaSz:"T H$m|g.@S.ͽG|Y3[;kq8u!/*VSޟu-ENe-q9;XyVlʙH A-رQ*‰$2$ MM:E_k/~% y1?u3i&V`}|!XInX3yfx/gNFO>̏ M@l?dy$#F .Ixo.$cm ➗[6l]sF {rqKOv#⵬0cq3{ {+;Xt,֩ /*m:ψCc[ ,כˋ|>mNc*fŅޘBe*rCG_t:9{"j-#TI$Gd^0ˊAiavG*+$ 9؂ 1'<z^c헏EC]At;T)L#ߧ 6 ڤ+ɫ26^Mܻ,52؀NIp3y'-VCaj'A!3T -MfabKMӐ^9<HkX|bc׃H_01#sa|*]sa'+ /2w*ZPaw{bBrJ^38)3\!!XZWAj%+wݭۤj'5V诣`%vPQ;QF"H50{pZj5p7AKũ.#?m;L$"D7y1H)S6ޔ{mXpc(Rj"v-|q?o27<6 RS%_+f endstream endobj 371 0 obj << /Length 2634 /Filter /FlateDecode >> stream xڽZr8}WDmY N*[LRJ[EKCJN۸$EeF6!h>n,]I BqIpuP$$A14 lQn0 F14eHPeĈ2g)3Z"J4,nnq0g_XFrk!EpyFp ,h FRF}R0<0͒Z{~7cAEu=?ehLl5L,-Knpw_AN_pQ#1 yY#:Pn+lmb9]|}ncLιMzj/؇|Ȭ36Ixn8\!cP%\A0FA)"1@?R7="%L^ Wѓ7+jt[$1ro'm<{ds?Vm#$Ce)DjwEHmㇽ| y:zHSLJDI$&jy'6Õ B%qTb/Pwmy"^VAQ jV)X@^@tɍip5: ~\馰PmQ!䆢QYS 4X{3i1^7jqP [[mL1#N Le'?QDujM,۪fDYM <ɢ|r03#%"gU.jڮdCp]}og- Rh[y6{`"L&:wޜ#d9(<"˓O֫MٷE)C?N$#0Ӧx7]S"DA(s#D0&x< Hj$EmýIIMF_܍/;cκ"f}o5'b{7ӕWgAUVvbJJ'ʻ%@i'4+&3te-M2]u!&TYiB8:ک(R{ECRXKteo֛tjofˆe>S=L[&mCbM3 *9FDixqSAEJgNg S*P %0gV3СaT]w I|V;<)r>ъL-6:,fCwd~jjEz+rX=.6գo mZ"DeeS#IV 2[U}7a nWOc{o kn°CVQ2iSJ')٫!cNځPl5DN5 =Y_*th p}asf9ocF6p C,AGmg @#nm00퀶%5Ƈ29'{׆?Rf{JRE|M^ۆK&+[)$aɞҟzC*H wԷoj ND7Dž9TM6P^ڏKG9l b{|4%,ܑ̪<'` qzw:Ox9(e8D [X| cÇ3aEd*kAXADB<"V@YjhFz><)z#W! _Bޝv -!r66u endstream endobj 379 0 obj << /Length 2691 /Filter /FlateDecode >> stream xڽ[Ks8Wp2)%a$f6R٬@Kԣ"J~HɦR.R &:88zs{BiIp; QȐ Mxp; bʇ_o, ilʐ @N#̹ž8L2BP3yAT B^"C8(yUp7&M2x}H xcC<)"̱]CeIC80=,YxVG4 ~(50 i.WP <^.F{-R<^{E-ݜ"v)+ؘ2$hcLv$K_ ӈee2ݭcm X\Mݯ,{urbtBB\2;Bt%u DtjqY ,%dRLk).ea50Mc?)I wHWSdcWfl"H0R",I0Y_}qʹ ~ؙh4﭂]e&0hhsԈJ7r">uC|igH)v(Q9$J!LB8m=: Ȩfu5PT n( {ϣ>A)zw%iAE_C;MpL_O*{𛻬vCaJٽU6Hڃa] HP'"v8k%xomMB^M8w>77$+Mzm zx7ܤ7祴Ic8tEs[0" +=1 %d=m2)i<-܏y6$jn766(5-STfuYTYqj[#u+w['ȎC2pr&lO5/)\rD>t1/0Dt jӝY8mWc4RB h]%֙yF}"|gYa,KnMEs9fu^Jy?˔DIUBk4R7 A\Ĥ0J@nx9gnrp&wмv/@y6MY`j9Eôap>tV%k=e9KL8Esb* *w"8 B7j:9³,I tM&,Y&\,OBڻbQN(9Ύ024ñ|L|1CS=)ME262 Z)pOp*?q>Ӻ/.4"\\B!&X-r![^;lck-5$4wdDG$Q=f˅q1 GroLH`ܽ> 嶡 c~îRM[UPj DF5Sa_D/F/o;ƺ1Y[mVšs̡ǂwn_Nu._e=KUVai7Ⴃz v)?B矲f .7Jo`ڱG XZ+w$toElt:O3 }۲+>1) mZ>?a~MFFPKv!Hp;yT{mՅ0GÊ &.&aӑL)p"ש8BdgWL̝ݲG KI\0JN`Wgqzl >9YƛSeU-!2.ܝC'6刋|OfT!\~z}bxhZ5uAQ҇Í@[eH>0&x-?Kz/BɎ^n SrqR)sD:'vc:D>_VOKT)ñH\ۂ5d2AF&w4^ z9 y$Te!XmRN"B`9Nџ$3PI8GN(Tϼ-?HJO  BN֒WkjuM]tz,UYuHğ.!lII;SIg=0| ʁƩRu$J$u# `{3$ h4>`YNySnur^1u2nKˣ={D:YO0af'^b/ ŎB*RdC;lV/E*^VQ9odP(v\5wCT/ZMyt(ǐEj2xLp0}B˷a@h7mׁE nj>Z ƴA{kwfe^ykxe{}=h6V4z`([MPY3ouks}-vlb#ږF>~?%V'VKV 0bֳ~;kRᩢE7,q(̉vIB >/ N[Y[l &" $QtU6b`\/WQxib8"UgœZ\$ںפRW=-l`Fbמ>)7\0[ÜNq['*z&i.gj2M&MLzČuQͳj endstream endobj 393 0 obj << /Length 2654 /Filter /FlateDecode >> stream xڽ[K۸ϯIJIve;T='(YITD*G3*~A6qptwW#$_FTs($/1O6߁E# ŖWmDL -HŻyf":u#f u0woP2bD9GtkM# k=GW0,I`9{ xAz@6Qt0^ƕ\f0QǮ}gޙiȄZ^2Vfn+bm!!e #(A 6Ha賕UȖDo+u%Zٮsw||\_ .g"}>̊5L9憷rYHe-j(D!)ʮnf}Ĕ̖hqmFx|ĵYqkXM?~]t[~wa̱-\f!<~UOfdc;'[~YRkXp5 J !1ժ\>{s{G4j&0u6ɲ#\*vQ0$ ]fÚi?:6B"4A)G> stream x[ێ}PF\IfH^$ٙ0[MקJ]E@%X<<*iowWl`Hh( n%F32-m|J~"`4t gw?ٰL FxPj><.[_2Qv=Wtmbfsa2foLf 3lDI0PfN-xΠ?i-ten*ͣ8Mv2'dؖ?F\6J\ "m6Ǿ10ivhѢ]|'Sf'jΌyIHNI-ƺ;0Xnڔ땯c~a3$Z-Q7 17 'tx rBWJ?BPy g_{?!u/HzY<)iO Xl\@ ˎ`8J|P}0jdM&oWCPd W>`~( -au4lHB͵!B` _S,a:<WhG 8 aں&(!TBWSщ &A`Eu~6?8sU5LyחcHd:|_YwA|_trHҫfy0H}$FDFQX"da>$Et{2{tw(^I$ X*.4ATwx%qͯl06}xZ D`7I>1;݄NoD*Ć" MJ1[g7sݹ7 n}g٠d?w֨wƬ& #J.wp랗7卬^Eo$ V[ln6kj6"65_tϗ[ y]Qv09ӰPVkql=dk_q"Dm tuކ̌Bɉ)O . W7%FatV&~ K1jb1Gu3Go ݛ2($$֊˅ou@E+-'!#o.|xδ8(5F ﵯRǾT,N$ruHd[w| vq 9fL8dPp9I,Z0O].X4 s-v&;޳z؊̏b* Q~eha993Di9 K TrG a¸z>EuB( }ެ30W:*X9mW"앆V3htӫcz) 2XR9d_'hκFlfm<8%ZIxPC> ,ڍ2Jq>&Bje,KNY|>.C|D\ox78V+Q /3wEHfb׭:r<-9 {" Chg ȟbFY#[@ .f+n7z*Xʵ7j?NeCK0lr1=FU1($\5y ȥ_gFho&:qbDQ&$ݯ< K$1C1^*$N<3wS(vVQ[*X o]*NV[K{ZUEb_NW0,>X8I˰')Qp_;`⇼Y->?{՚=P0=)N)}օ9N}W-6Ęt\Tg58:,ǵn]9-W:&qMV%reݻkVj5Ǘnݡل_UY8Ԝ.q 6-U ]c׃LC_ j'*r2swS;aa0oV]e!7#oD ~a.0`Q=ZK;ǴnxϜ+= 8n8)O*LAL>Zf0vŪl[Fۦ/2u>h2=z^+l *VWvB>lkłIUYۼb@niۢԖժ`7A!'.Ryam@-ylҪ?oy1aCYm,>erUzOߊus> n?&O3DIavH J Ҷ5;a0%X*@~jZP/W=Wi;VM݋\mZw%Xm%h 0)00~u םOQ)]j5]9rif0TGVNw`DY\g(rB B9mO/F;GFk~-e6ϢAqn(OP)N)ۅmOA'ZQ2K\BeN8{=7 [f|6yQ' w08}|qSr<0ƞV/ [ctƯ?ps)Ce$@Q]q:Kfqeo?c8,OcTBV>qm$u[@wot* endstream endobj 405 0 obj << /Length 2308 /Filter /FlateDecode >> stream x[[s6~Q3Kۙt:d/m)K3$KTR$AK"Ekb$tp;7SۛnБBFa"9bDJdx-OЙE#MD(}nƾđqIOFkѯ7?`Bh'MdTZ H0&Ë\dS/]!%X}"~L?GycY&$Uq~^o7yC?N~Ώ] yzj l!l+!O8†_IƧAĕTgEùJDTT\]KpJāFPX3!L# )b#yPmȃ4F op}!rh9̂Vr=[11o{x">o}Z03ؙN޽-oG{iHA6cȵ8%x{r_|<3m8 D8_arh19᠕''y(݇ V:$B$TZ8rCzٷfX= AnK2 #=šΣ()EM -z%DCZM8u+L C\H0I<M>j^&Ԙio UVyym35/,vnċNGD&ϛ{=s/wΛ_v˒h±yzEw/vXyΚhB i`TNee=Wb:w*nwY6]1*M$ wW 6!}gB\l Slr`Vp75۵mziߥ,$ߝ#=gz.:՘er8/mT.Cmu^fɪ9 QHM԰<@H,inrmG"u+99 b א|(AD>Ck nJ_.Q(վU5W *۴/>J[KC@LT6T_i_Kp _{ޯl tG(bhAE޺q^GmWd/x}NGsșQKhOۊ;.2㐁P#~K %Yi&פbDbHn>WӅ[)OU3hPH^ y)UHb 76?)Aj!! n.FHmIH@s>?IKJf-Z3Y@5MːWzkP Me8ȓl|t2Ayit}<䵦)N!zֈg#Z. J@=oqJ/0F%$yAGh\Z6[v846]M ERz])[%b dL 0(B!gw(Jh.)3PN C I[STg16%t#=5$a W "d* #Y:H3HvItB T9TaA.L^6I-\*)U 'Uv3_vOIX НQ i~-fcx{FZdˏ*EzoZ|q8r|0uF;X0jJ mS[;5lcXp+{8q-)! =o䔺#"H~NNI:%X7a:o䡺Ck0H?Yjb/(_=[)6nwB9GX K9T!T::9O_O:6U;NAABE6fO6=1A MΐS l!ŏAJ>n'5X^n Hts xfmW}!226 h7; 1Q11H3}槉J"7*=p@Lu&wr戚+1ٞdhM{@Y QsneT+J Ct`(ȥ=$jA9[wi%9$v1HxSq^"ܺ{{y@>r 9C'cHS~Sٕz6@ A endstream endobj 413 0 obj << /Length 1278 /Filter /FlateDecode >> stream xڽs6+kѴӔ]7.4qHfB z+ɀÍޏvW)ad}OPg'"Rpb4+2'zݎ>$Q\GUALH/arW#} jR.n(7M֤ϩ:J&WԤz'vUkPQ!1{P' ߲du|Xo87Yyx|ZOrZ4QaZs*ultHVO={= ]K纣4^-֫H&¹B31&I_hlT. և Ԁ<1L-gEM@ 1Qkӡhf ŀ iGH|-dmBϥhh@7kGa c:[FG¨D(ƿLvjC3Jd͏lV-cX.o`DWbU8a= k`?@ٔ'0vѢVS%r:n-Ὅ8 ɸZ\/ǡ/o XHdJ щIlߊ06[^ib7Z "o8d`ӊ= '/ESե MVmx9 cq/i6YyRly]=lk]5@|$I6jwv!|FRs*[~zثAݘV88;¥NmLPe_.1-ms@UεQynkwl[ KJ i 7 ^ 2ͣ3@R3%0pb(8`1|;Kը^xI.RK'=n)HT㥻\E]~/XNT6fIr br[4GqUrQi8'[ހq,$R' ծ/YE\`GU# UB gx˔B9mcK:ecQrJ #(чd< b`FLĖlwU2SJok̷Dl1CsDD\QAp-Pҳ5#fI*^o4 {`6ɉ?]خ endstream endobj 306 0 obj << /Type /ObjStm /N 100 /First 874 /Length 1575 /Filter /FlateDecode >> stream xYn7}W1y( #mhkT2,MgVr\Z"}E.z8$w lD lEޭpe#\2y0ɹ d#M}MfLIx#B'U ͞Cp1^TQFC>ɘŪFteLx#ĨC^QMz?aH&0K+%ސB#c:D,h$@yavrٜPBA63h;v1Z5fYJbNzuxcɭòXDulg6yQc/^m^}vuduXc$['{ c̮9%mW`CVѱT;:eTau֒O6CJsn#kPt1ՈF\_x*:,Taq)*,Nhj ¥Jڮ\>Wd_HWjq~\ݼziH/pcR Ζ(gq۬)uP\-jTW;@=2G |ZMz4/77Hwؼi^?S#.`}M}&uK +Hl~?6b5[̛7j^~4ӹkqvehZ|/WWaF^膳I5SbW[/<ئ׻vs`,f\ޢަ1w˴ʆmzr_2ȣf'Nx4?,- hly~9mͷtP_/(6İ汵Y4ka uٷXb]([wK!/|u&MTW{*҅n(8 sn bVK;|lUvr`M9F?cOy,2]Wq endstream endobj 417 0 obj << /Length 1996 /Filter /FlateDecode >> stream xڽZmo6_2`|Y} 5,VbIv(d)AQ;&ч_O^8IIEt~)1jEtLni1Qc9~r"V)f MwllNR!1.#h{$"G|8q|S7Md=_Ose}?2SmVLl~m^fQ3,&"ley&XY]떌h%xX&$nvj-= <*DPt-$SA4'$XQD nXC ^ [`̘H x+v:~LfnŔٙ77?22,)NӅ{̼2uOڭ_ېfn]۔oW:lr^|$ "s,9g_sfLhp+Hݥւz'ن=TTv*ubQoZ!:k>V kZ@a]#J7MlWi6eu}ej% Lғq~ݢ EvmchGOv Sۊt+6=&nXe'k7.)HK˂AFkD&qXMp pw 5ITŎK,*8a**{]4nrdKM_rIpʮCka{>q>XuEa?}"ۻJrcEUtvk : 8eAJy|@u\e08HOt CC:C.C sTfd+p}װofhmu7vШ-\(gg߁}v0bǎ?qȔN3rٔzMLe&>NiC텡6z? z,sHjL|aiL*);XS[|zWT8lbU['q9sR9Y*\D: &8L|My<\s$N{s[[hf@FȚzE>ͰrVI :)'m"#q Yb(G?wq ˙kH~ (n>8Ay0.e(RT2%\}{a`]PhB qA)= z@96(|Kt.BA+=-JD\[;_xr{蠨ss#!XANe_6xI>}eP4.0P~; F>RP!dyrOz _/i\J]>rR EDHqd? t) endstream endobj 427 0 obj << /Length 1804 /Filter /FlateDecode >> stream xڽo6W{klhWhm[vbQTlS!"%MQǻ%g4xŏKib5e] Y#Av=nr n?ag1J,7D2Uu\4s2ӜP<//nni6k2J5SszRf_^E%VqߠD 7KewA^K۝N {WslvHfJ'ER&RbEY@`eDqDEQ!J9a&$KIu2?L)^e&dk6fz(O݆?'~wR}J`f7b||U_NZ1;j4 6sFfm'Ͼ|?_Oըt++Bc{. hF!fʼn2ZJE?-Qܯi\Wˍ?uVz}`t%qlʮΜ^ƫ1/7^r6_O|ڛVøX<.Wm.ѵ.}±ּykɋUmxW< ;C ³-EbYadV7]Їq]B$}%C GXqzZ++:/3ܵO~|Z0Ps٥Ĕ[w(RI]^y9kھ>>N1U-IQk֋SVQtFskȽF-ҕK+PIOc岨[VUa_bGswg! DA>s^*Yp,11to E Ӷ_B­> stream xZsF=i $3i'C&M|ss[t[ނ@ ŒO{۷M{zgԍ\Dk;hbDлeP'+׿QB/SIL`eJ IfQ]r4$Bj6),&CNnR*MÚǻsL#;|gT`h\Jcl9DNOI`:σl>Ɉw^N =|j,?@,EJ#T5P =OJ- 7Hy(F7 n9POɋjD^mhK@8k*!d [ه4̄KEUҭ6UH[`zTW9J?qU;5q̢aQ=X2K?NnrM=)m4̫\/иPxUsN[1,[#5};i*zx>oP )/Λ8~ ^8H3v>gM-VWKܶ(C`|kHlF'>ʭ[XaiS`'`C |"m/u{F3 '``؊XFN2 ^9ú8~aǛg3Pڭhq-@phK`DGY>Mfm1з>kF) X 1TAa\z7C4FYiP6,8ePRV.VJ?1Jn˄hBho_X/vtz]47ʢU*PN/mcgFv_ lG\ dFf^$Y(X\뤍4ѪgF8/C"yηgp,f~ېNUkO(䶆"H ׃/N endstream endobj 439 0 obj << /Length 2058 /Filter /FlateDecode >> stream xYKsFWr"ɼq7Q9Cd K2ֿO $H"$D{؃LOO==m\'89|OB' Ir~P$Q CxrI.&֋?1KFOMX92, @lxAdRM ߇pU۳Yr"u z^o7MVMYu~?lɊa^$U?F)Z dBn4n?:A tNE<8Teci@[ўlwiOvLYT~ u&'$%C@ yֺIǥ&oLVbdˋ&+65 rkX3A_+70 ׻tlAKkl v2tYoӺrg?Λ-VuV~ vFu x*+]tAEڛǿH7&]7ΖdheFv ܢNJU-iݍA/0"m5W4:; qN~ֹჷ3+! uuYgo_[f\{6m=VDT`wy0+ٯןOV~`o\]b٧ ,j$H$Hw8ώrPv6y7݇@ # ƤcIpFu $rtG|e'I .UpQ`yk۳ pV\px)ӛ+hu  *kf 7;{f==AӎȒo9循uLAX]DFxj:OM H1dO^| 9Š4|R%$Y\'r0 ׅA.$0=EhA`(4vtUJхcB 䕔L 1)uy E3~$h`)򸏍"i8Rkv0i"+ht9F ׅ+4viCcBS=E-Bؘp  7& endstream endobj 448 0 obj << /Length 1518 /Filter /FlateDecode >> stream xZMs6Wprf ߈&d24uOH5%w4Iвi3L6( XܥIJeGR63 Kƭ13̎zNNd!\($Sa~Έi2ː(l&X"x\,+Qv2C&_, ral<_7e>mBdX6 Em̉% (0Lp`|btc=w) v66d +B%hS6W ͺ\RF#r3aXB2j;qƕ%z)8_uٕg dQ D' ; `̷rJk*+GV$p!)߻Y8R#U99s+ 0 n1t%9]]b<g W'"TZ*$U*vZ@x}v˸!y+)f(=r:3f\rQ16?L&1=oOR8SNAoh %WץޗH[ $M_/H^OS>q(z,٧"dևPLo.G 衘{tR s ؃l }w]KÉk 'h=83 hܘuު@R.tx ꞅ{R7y1ZԿ6bP.e]~#޻v-=#L,x Zרּ y)n endstream endobj 454 0 obj << /Length 1796 /Filter /FlateDecode >> stream xY[o6~ϯd5˻umо !̓lӶ0G$iodYMdsȏ:߮^8IIEtb1et=yIw.3*$\}>G\GQь+]EQ.+'ȫb/1KDot=#ǻ|QgE^9WS*&׿d2AJ2(0JwUm1Oݍr*") <*Y?&9 S_n &N4)` ;0 d7K(F*v ՞W>aEˬ)`dJMB&sP]ye~EYܺ.]Xvi$A_]c\k*q,Lj80T}Si>lιk?X  <Ũ(XNچߵO,o>7 VoЪg93¡66pN'I=~ zvmDhu诳?ЀRJuc$)q3P}RuGبm?T¡Ay;%84"8!@l8'+u1J:q̬ Q{a47/IW;S?31 M\F{"#z+tF& طcf],햾g`rLp pXhgn,_A@mIu0lo8b=G0E9GJ kgyz|޴q3lxsB0?vWWg)f='cU,9nN\@Ά #('KW#TQP,7. (#?d0Q܄&N¾u2^wJGŔL"ąph»Mf9tYb }ј-/jExFeCiTCi92>k60*@|Ԥ;}yc(jRepξbLi#9rjH |'6dOKƲÖ\>lFV`HO|ߕ¸]Z>h#acP R8xHN ~Jmg_K \fQu/yzJz6=5zO2ߌ#fw7{MD75A)镺+MN6mGdM5g^Ru. -G S(Mz;}\-5Ipϻu>vI$ŵлmBzST^h/C3Dx wBXt#Wͪڵ:'%&eJ9nepyV̘ybesxw} Ѝ|Hx-wG~^u{w0ھMLjT??C! ?{p5  " JPjser*n^8޹,_(>6>> 2bqV+f#UPZFM{،vl?6<xT! Ԍ~oF) )d<3: endstream endobj 465 0 obj << /Length 2585 /Filter /FlateDecode >> stream x[Ks6Wp}d,&nMf8Z%mdKqoA(ٔif. Duq2Op\B' IruP$Q Cxr5KGj3:`d)C(׍a {f_CDQ'3xc3:yr=mo*gA$X5s-v3ME6ݽw\>60h\''  ,. IGZ5pJ1,fHtV#BB%/{z3cï%"JN&"m'"{ #8| "J"baKGwv?6jG6>i;'0dZ`%bzo[o7n]|jMyٝ !C1K!r&wu.B_0F:a8jutV0g@/"`" BI}LɈb50HqAjX;4S:6yvLJum0 `[y i1&zƴM,ǘp^`ޮ2\jbh}gj_hva lrv XiXS`]ɷtB > Dw21>f@|?*)jZ[ oto63 nӟ*ˡOڴL" $ CX٫E) )Uㆀ5&`"iHc Vi[A0M0`h7n%t{Z,w;lV٦[FRmH2çEDUOm2 !i>kB UٳR阂5KE;m64,k; B2>pNgvj3M:o% f>=x+H[B> ޸7{`g"4qMo|{5kFiq o|4`cyJ5ޡ 1"۸c-k_`of6+yDwm7R׺7hky}`ީG۞b/QHWl)8'SM0sPˌD9Q.AQB(ȤJ$xՄc3V}}W!/ 7aWޔ`> stream xڕXK6WHUEIl+)R{pR)J$R‡_h$8O|P Fˆo޾oh%ԛy&L+I`Ji!Z{nwR(+f4K ]L(m#s y?5[ǺjSGv Emg9ϽXL2W}=ISj7Ԑ\J3ƅ;iljP*Ik`zl˾67 Ṛo`"QYޠB{ YmE4\.C-,],6;1ms7DD38:7-} ܕDYNx$BL$䷾5ܤ`N*zItyWf꾣Sׁ ι K=ivN3D5RHל<#Ld{oojX%y>֫3ﲅ wאa `4f10G EEis*zv{_| sQu * Lu̘<*@x ;fj!i vy5R-KwC3Զ ]/Dp2ҘM[K"VuR`ynC[maB@@Hmc;yP&=ZI7Ʊ\XG;eA?ؖL_,idܭ! 5R*S8 qu3.Us(*Weq\. ͟)+0BR';й` 78HuXJk@\p)| fiLBcC54 8{9<"YmjbUDhNl?Ol oR͊y-MYԜAzsPfahp8ܜ$(;)璥Myk0<<8WHl-Rʵ6ާ5ph )>`[.*W>b {iۺ!:g= 3󈳗=)^|7;HAHUsG-\;;ʀɫx<~qƄ.%LjR{,sL>no7 6jl/Cvȁ"!Ӿ/2S2]dbky ~ 8:PbSB q`迠k뀗-gйӠeq@gY<}?ds;; wgsAT'_ ^8k}|Hްjf\iբ-TI1EMƢuZ_|%tf٠۬lF(ۧAJQesVae;l4[)GDK t{kP' Z%OThς3fk`AۯL0W|^P*,1qCMQѺB *K|5غ<$Ik2mwY螜N@R5s_TTW6 endstream endobj 483 0 obj << /Length 2601 /Filter /FlateDecode >> stream xZKs8WrYB @"Sͤ2U[;xg9$F"$;~H=h|@w4ZG4p۟eDE7g EbD$YF_C[l7d1J4n6D2 e s'~y"ZEs!I[OnDNvL OE4gqҏٜ3n_l݀Vmu(nF*MXmg:!0)yo3D 2R5~eݕ* /;~Zޘ%9OH*!U9ɲ JšNR*̪IJd~ڴS+[^Ҹk9ؘş~t5kLu7_fRƍ_ RN)_!TJQ'2Bp u;2+{eF|) 햮wvL);0^yAN"9Iηp}mV6bR%\h@<B`7oW3rqb%Xt;1"hUbM(RsJN†R9K3O*tQe y'΍X=JDϪvj`h9j?,K;ެ>_ FA*2R(G՗?h_~܁gJLq6|/ہKMNZ( $~}op l=`?색<@FhܘdžC"0.j0pqZJO@v(f.\T*߼%@w8KI6lv߼Yj[ӚAۢ\{iw7?03CbNfSy%M4,&š/ ΂<\ A|1>SJXT445M2^ 2,BRC|}W&|jMO_%x~?6?b}4'Tö=k-pWUܭLJN]l&Q/S*`IJu񮧌C*k)@(yC;ퟪ2ok߿+y<HBI+ RsrN1EQpBdmO9gג>y~Iϭ7uq%..] Dh^F(~\gx $s2gY,R"I8TXNm>%)#׫YG$%I>毞:): bct>cD}LA"!#EsᤌE f4 K7͵B/& 7I()먧Ԁ^gH2P%߮mU衮~T~Q1T`pI3A2%qS$˸&h=yEH USusΉO@806G$G/zepjq}I59¯q5p0^[_؋ :zy0Rۨ؃[S>W&W!޷Ҡ7F%Gݻ&/={ 2dM{H?-U52x׻yxYǖOtS,|w@]''nձ\-ڭ;uFx6c14xD㏥\Xݺ*|@ж tC&a}`V37"ݏ;'*vTWnIhx=\|S۲h.l0Å諪}C W99cOQ@e1o X%BallAc< T( .U/ΡhD \:|O PⅳY2suxGZL"\DE[ 6ux3Jitwbc6pWP:b|;0$듣~ݪ=sAS7OW. t*V˰a%K 1Tw:< KUX> stream xڭYK6W(UY'd+qykeϞ( H-A;Ӎ(ÙI99Lh~|N+zOo~EWǕ5LK2:cRwf+4_g|?pW;ӏ"Wln3W[Ut,_x6JUYtL37z}5jS>8]VD\n_dz휋GuUȏ}82^SnH[$pCN\veC]hWޡ?bzfi=ᆰ=CHV9mb-}[Ê"2 Aa־'yIp uD.BeF3nE3},<뱭jNVv`. }>SE}2-6]qu>M#Iȶr4?%[dJmXnb ,u{oGmd]Du^A<8+ҫx(VAw?~Xd*jו` Vҡk">fkS$хuֿm:E2YKLEItŵqNbm!$`l;0>D/ܾ& ,$ҬlϜ}嚞'KșB=tĪED'HA8}f}!3H o}zGT_vTamPh}aS'$Łmw0ܪc^h!dU>BrPD1m0o(AvLV!\lDN- |! 5ʈCߒwʀeӌ[Ns9DM(7BJibEfH @-tmy̼Ҵ|؄ Q5k (e ]Z =z 䩅6p!7"e1{?z}wzToO9(D̖$(4? J+hhߐH}^cEuʣS=399>14Ϧ"e υ{Oj4TZ3ekQCz#r>rn%58 0\b2y3|/712^6&~&m h`Wb1H%Cۍ뾽8vjw* P.dPJ{&tLt1 ![4竽!v7KSBECk5Z e"-:E; s/o xTKU1X^2aVPK:wV !qLu NBDpqe}KU2(34"gJTC \>^7|B& حkR=$b8{g{j`}O)aS{}{Et1S؄pr 9LЉsB'"<3B/S3cW|ij 8#ODJ?@(LOքj;f~f}?wMfI;Mr:~|uI{ɸ`C3u%PPQn'6 ڿR]UuՂ@D,7bOb1mlԛCcL?Y)UntI_OAT)'~~x;>Sw: endstream endobj 506 0 obj << /Length 3159 /Filter /FlateDecode >> stream xڽZ[w~ׯu*n Ms:Zu-ADBjd 0;,RAb\f@>_NvRn"]”kKE2ZLXV7Wj"8KyJbZT~Jp Oft:)͜4|d5~<|㦘gKzR.uYLJyZnf,jzQu@OYWg3kTblUBazmYT5TʤL9rL9e;rmH" W9 \̷Yy4ޭr]6JS֭x>'hx' ) ũ_O%-5`f2 13(z>k\,;za(v}Vtz+'Q)˴ {bw)Ou>פ Cu1Vo ԟiw; U%HkO:fml%}%B6DZvQ´:h$0}&юx2lYR <\d5 kGͩ> %-:m ÑlWB՛W6L[wM\k/.4*0Hc ʺA"59:l'q;t/\ў3rhh?D." 4ffz1n̆mK1)>4e-`{#,KՓ&:R|- T@✹455_àk$*C` x&eM #oCGQ:_PQR;8&zXf!,8 #%}d,>/;gx!,eNq $ P#U񎔏6W9yyͬ\E '*W隗{ ٘qySpԬ~)F_,23{ 5@$P燢\ i)D2-/sEr0܃_v4Dm&v䀿6c!C2wlRǜp7j<w74ܤ`Z7Í:JVJ.!o|dT)'~ތO` %QS]kFq YhP &ӣ4zˠ|ÈԼ n.Pfoxϱ\[tgK63l7Ontͮ37-mX87X'nZ D܁Wdl!m-uAP;{Aq ԃ4_{ 6a"mOĸC \qĤ-Tr%x ="dHgtۣs^ exs~YPLmLX Af|ʵ`!2s|7<<$!Oc86E|l [}(2ddp ڼ K4%xȂA1nm SQ= G] 9c ru\lD&cLy ts|T &m01?.npee N{dM1e3^ sV}2}TτF[M<ʷs{nTU!dL'@Lv ! $/>7t8W lTn*ZW5ljЁ 5MϸFQKie˂K1pZ8K8bZ%.&n Fw 5mEXE⓾ȼ>/?*򡅰NfJ'3 ?]bb?p1r֭0IzaSBTT7P4I3]9o>,'W5](Si?9 jD2DմQ| Ytd?ɒbov98Hv̈́Ž.[gt=㿔]z"R0s,z@H_o?6o? 3? 9CXKm wl<(lK_Fѹڲ@&Zox÷f E9(<' caәpIsKpX=X3' t>ēW'=A'`Y/ I=Nodπ4yя\[|o9<7 Q̀P2Y%M~teB KG۷}%908@4}ϙل=Ƭ:ޝ9ay"ȳ!z>mreXo|}㛳!1s<#R?ZfOn!|â tG:$r}- 4QL7鋨hy>Uc_&aF;(۴EB)=zO@_dOu6r#;8-2WǗ13zѫ>8Ry$$xWpyvs잊n0ysa#_ɬxœ_~:^^Mrdi endstream endobj 520 0 obj << /Length 2322 /Filter /FlateDecode >> stream xZKsWpf,OH,q&GmQ2T_s"EJ6%YB#|$>ODXMYt?Dpdt?m/XDK_Q HeB ޤ#ZHsNd£#fpaM[հR2_Ei#KlzyB(p[Wm6l!Jv3R+GOmQwGDcPH_zuT&]N,~6ix~̋쟛7=ms/,e \%֠ScR2>D9a"<]Gh+q'Oa$ ˼)k,Cp4@ 1V)\KK4syfL8UY6dD5߼+q 0$=X hGI$ ~KY}|oӽUS$Mq^^{* ,:Q1̑ 4iDeKPZS$<BF)-!S%RqHHHgd)?HwsB73ΛYLpċbz6݇zSvDh5p 5#3*&îjyX9Xv*47KN @Oau 'L.$s^,T4&W9`]|5=*i QiGyz] 5E]BVVi-~ ٥:[=`jgʎq[V_p$w|}~sZiY꧹S5cq"+@YeX)6~.pU3\oxvOʈM/O _7J$Q~4q eipFޜMOp2x@S}]>NJΙvc$Zuw^_yVpI/񱖻v"Q;Ašɪ(; ݃PI+j!̂k-;m ʹ`^ %{XsZ3H&ҤK)U6鍳b3o7)η[vC.ܘ]_aq\ԺvWĮnuWP0;ܷ/FZ~_">4ZO}U+DYĕTz~ gWƫo 5h 淋FwPX+GW@)"|⼮/5W6$1WB%t\Hʾ56o%ѼŅQ˳3HuBH#U q=]?ƚ9Aj2|`SFiUm 1+1BC6h &vqh ^ٵ苾.;8ԃH9/` cX6M;.n!V $w _TkyE7E׶ M߭~ 5z)ĊOY^,¬HycƼ1bzf'ܛхXSF>jC4K;H6P*8CX8MbPw-C y7Dv%plt" vQ_9Ɲ,o1@< a`e`FR@ϲ9zl]>VYYh~Z{[xq at > stream xڽY]o[7 }""EJ@PH7`ۂ>1+!Cwx {DQ!EIBRRG吙Z s`|4{ Lr Z.`/B6V(#5".Cer$<"")P"^ICo-K06t6"s0f"rJ fJ`BLh=!*!DЩ@@Jg]0y`MsR} @b0C)MCap\\N ,^mVb:bgx؈+C+՝ssɇMC.^ SWe&Y^;A STPm|tpxJd/x[@[ K Xڒf镚L`RP%+\`j;f:. LZnJ?I+0(&q0A@|!2>{ ,ch6ߋ0lryq Od6?Y\-o.WC\ ~]|:b%&(D !E3HJg(© A}qe&P]AbzE)~lnh' aptLjIUcM'07s'VOl=1xJd*lV(ovo.golyu_íiiQц weceOӶ%ځP##{o'Jv@c}S-QDԈ@DMDܶv(uj?uف%(FXۣ]X1ЬO_n J.jd<="(3Ş#[<=Gb<A.,{?IHr\Q##؁7eMU^݃erÒDk29{ZYb]6|*oRζK9mOO]tgl_0Bz?i) &}t>R}bV7Gf`azn`n>^"/6mb( w`*0L܅ج19ׇ*QoS)\y•(3CVx"JgS Ȏ~:Rdl\4=Λ>0* UUچSh}FjC%d6ŏѸE?wBkq#houak6[rhetWbdRurm׈-umؔ7?6(,%hӅCV[~8^،DKxhuۣށ-E쿜<(y"7Kһ#øhG}Һ.ARl$RM ‚5R3+ ,g׋?> stream xZ[o~ϯIbw]@ E[68nmɕ=M}gHJͱA`"h̐4ZG4t۫?|k(n#H"8f2ݮPo0YDKQ HiB+G ɀB(hg}~]RXP uOzzeg.M}Yt,Mwx-Jg?^?u8 UHn "zS]B " (bZ2EYv p2iu'k?7ӠQ+PE4ڝ&s,|z,ƙ' :ψDI՗ ASd a\vA'Ɔ@}ч-ۣ4%|Exn) (uge'[N2# 1{S !|b[_6˧i+5+yg@5ltuտp8(-wWw4Z%&W7s1`B|o}wbi k1K@Lwo5K7}0-DFX!,{ efe U,Or;~4!d `W l:#B[p`#0fq5}Vʳe44D ˰ϐG4[v}<;тRd >rجyaϖX}}%<9ncyOC U|*SMj x{wa -x!| a՚Khq*׾4Lbh3V 5|6EI )DRCX=~[2}Q{ڡ(<%S#' v 4Z'bAd:Bous™`uy@{=YV+jbYSDg# t9_'Ip1wQ<̣t+槨.Wx$¥-ӖW; SΖuppxx6&n^-<LJt,vɥ-6-(bw%l,y|NˡЈ.dP:wYBƻ;֥`!AQ> Q+NG b!KW`1e:aQ%zOF`UJ4@B߀w òm$ IAͪV"͹5v5&iHO ~(QG<_ Vpհwo:ض!C,v`f۴ .N~_~; endstream endobj 539 0 obj << /Length 1953 /Filter /FlateDecode >> stream xZ[sF~Ф/0_6&f:63:XI$u}L?r|{.`ǫ2 &#FI$AjL<^d{MDӘs.p% %<$r\]L8wb]@BB-:rd$Ū $oVР2X4,Q_3!8hD# ja 0Q?bypb5I8՛j) &cA`%٫|pL|$FHj4ɱco1 dLaMy4bU|%QZd?c6%NR;A9:ɋQ{C悮"LK*]ȕV&s}LtT~́#tBQ{iJU45牥T)_9Ukr&BR3.t]~HtŹ:HEq=м^d_-2)c\{⩹pi9yEQ?T'JlS{#!H9r_{:HٜbL'tZfyW &=7C zN*VP>B|1M.9z7o3x_ l@N zd%O4ѫ뿦D endstream endobj 544 0 obj << /Length 1020 /Filter /FlateDecode >> stream xXM6W9ɀ=H6h-=o^[k %Wm}G$%˖ a!>μy ~lNjp#ApFt2Ifk2UƋG4Qzk.@1rf6#ј0Jx*nc2 L"Dc%_!O#22Ji!rT/$Sh UqUT~bI?8T2l}DŦ\oo]b(r|c x׾x3Vߦ<njWur8k}񗒔F (kNh?'sF[5@N+SgY RWJVϴrW ¯AHvp6WsL endstream endobj 549 0 obj << /Length 1605 /Filter /FlateDecode >> stream xYYoF~ׯ DzE F&H69ZVUJY.r"Yq 738G8`xpTb$%x)1j4z_-M8&dn|_>ڷ/VVjш s '2NiV.v=)ٺpfBzBz%nEoFc?]Rox!s!9*e1wٜ2E $D#Md|;2D+`-I,#d*6SFIPH`BFJa7R8D3F a T`J;Ų覅[$~&MR'by:o٭$ߗ옥SDk/<7e\?8%$FMk^+OÐ8K/! 1Ń'9E%”U61]avW) XfMHY閒&MzI UK;mȶI=~ O8 .e[['[ty:)n(DrN-t]xU#mU|-M/T+Dh7vVM6AWWV_* ;&p8@n$#m^1 OuWAZh$ݔAE7ovE T1>\agyY%@]ɐ1-vk!My;&C̱Bz x:իW Lmlo媸fyxMiB:uV>.3.&oŶ&feRiU?,Bੂ?y)<{ A=XIF($}o8I*+m"?9,3 =* U  x$ޫ1 v]xyzaH=%uE{A"E/? p_5۷!: أqهVq$#!9ġ<( >")*c$%gb*-;UBQ-|w>LC? R%([H}u44= xP9]oV> C|A S/=fwF `a0.AbH?=iQKl\4 -¯+Z˯=a?ۏ$r?fGMo%ey7_8I~ܹ2[V0냟$aLfJ 9?iqJ"eŽu`&&-;p@fgc6_ͺK4G Hh;';#6x׈őʞ8-u`4j-wNG:?/1$I;fx;<%Vf L5bp 0ğVw{}`lU,J x1VzvM21v]8!KcShq izωggo ^ݗ+G;гhPARNWzhW{*G0v( ! endstream endobj 561 0 obj << /Length 2637 /Filter /FlateDecode >> stream xZmoF_A_;]k.vS$@h'hyH}DQrLYr9;̳C`˓B!BLI@G EjY5x f(‘MDa1' 8 F8#F21!@"r|wq\x:Ft.|z>b'uQV_YŐ5Xئ7Ti0* @k l&XaϷ dH"r},Ί? %!WGʊͪ #4 M<ǎ[1!0T'M$ֆ6L(S+k۞dPQUX69n*iU5 yNldtD+$ Ј&QFpV9$D `h0$7+f<mez0du:_ԕU\e vl/U \}M  )4mG, IMjeuK s48%⫝:*Ded^mnBolBadӋQZrh5 {չ,$ʛҌ5-63gt}bCiEϦ&åHtoJ@*} `(ҼBiRc۩:ne4i}ՆXL~~L嬶)2~&58$,Lv.mc1d>6l=!nM:n @51t Bl$|O}6!<8YOKnӭK6t\n612+./k!M4[uðx8 -HB,&*"8adS$1ҋs R 8m6L_?,Ɵ̖ QJ4ͶyBhAո<] ?>@sL4FoU-Ĉբ՞ `Oi 9#Ćq}:5t48-A"K[_@v4rɪ1&UɨY~;#Trd5/Ǹ&ש[Dz5y\Ө݂&l;jkp`3ڹERvUM6~..N,Xh4:U0B*8v Bq._lg +50~e(X=>iB!i l eW)kWNVɖ#O&M>^֟r6Y"ڳLfQ㱯y/ŗeR4erVr6ny@F)H0~!pl5>(6q,~]zUӣgٮp$gkAu}r̲d 97Ikj7 ֣Ek s=SmX[ C]~z, 1 9mDen6] Dpo|C &u^:@"`]zܣ¸7@]!cT c{qPm,7\s'M&ȧkl<*􆰳 G%$_KpN9 Gri07K<˯cԅQ+"VS& enOݷ8]t1ӍڝL `cz s4P]9A#8 I2,п1\t?],it]8X2d7ikM4}gax7L]IHwH1 \]X"}OHEVEiOعM9.2q9 endstream endobj 572 0 obj << /Length 999 /Filter /FlateDecode >> stream xڽW]o[7 }P'J>t^ib'(Vr=QJt) )N{o_O IoByZp!ïbԿ]./6%jk]UfKl($R`_Q!WAHr^ZDR! li`{N^BӓO$x Y|G] xVbi8WX  dQ]>JW͎?*. @HSXvdhD/ctԁ?y RB ALߧY#nfzqNj]rxQǛbUN-ʠ.hO6鱈-Pp9qžOt01g,%:Jsad81#< Y ݪ^ʔ&gGy#mR `4w`t  o/L}cS#hYΡ6!|jGw&惁{> stream xڽY[o6~ϯУ ,Wl@4Fɚ{hBi[-y4;)ٲdj>)|C{s{3잿ߟأIIw?1օC*O3W#' !W($ RJmIIn;l:"N|`"$ӕu>6EzN10`Bn!/±?aLՏ9//C+ J@R)2Nbe< RmMńDjWLd3ּtT8DnʐIu2a CBإGS:͵/C*>bDžc4@6/h; ,@,fq008CN%ⰳ$ 8+Jd):V4Eߕ.n3_NG-Ԏ\pXe ё8 <$  *pO` sЇ_FJp'AB%;\)>IKtq4 (-%@NdQtGKG1G!rD(Ǖ#"%v&ry1(!j:).2 媰1 j{EIMxQطk3{+}%e?r' ўsp/DžR$1*Tpl/ endstream endobj 584 0 obj << /Length 1760 /Filter /FlateDecode >> stream xێF}RH0 P$ v7$n8Bg9 AH 4ls=%T;71 έ7g{&2H*+R1&+`i|t0""ͷn\#18Ȁކ 'Q$(Yky{qu#d##2= k> 2aח/3~opmr9w'99wopsqR~p ]w_4,(qB(&x 8ҳ^5_Y#l'JMRZ"eQ׋a + *JHLHcgIk0Q]0FFɘC֡VE`Çڇ8>po dT3x}uy9}N.Z&4<$,)$! EΈ{ץ `nFCI8vc%^ByI)7WPA,Gڥ[( p qىUcySX}r8].;2Lf{.@)AOb6T ex6du9æuA"*֞<]eg[ӧIoWfmDGJ#rDGԧ0&(9h89F=@~pâ A%2~yyn\@`دꁰ'r=  Qw1ƐYZU>t4K6^+6mYNh1jE;̿l! endstream endobj 593 0 obj << /Length 2479 /Filter /FlateDecode >> stream xڽYK` xGTRR \ ( ^ywv*9bf{g+g$zv J-z5}[쇲_I#qn3;4Kq峫8gP̆hg"e:Qiwr‚ r{ZreilZmάgѰu{[GefcWCUWgGwhC֖z.IOHU2V)'~T'%R+!Xz3dC`X{mAhxv%'ysɣ?_[+c> P6CU45\ξk:jY U;!,[ΖšIq6U2ُA(cofm07Sj:Z)+N[kr/tl]knggSУ|^9.,V3y 5a+UEeLԓ9`ޗ/̉Km&1_\է@ן X_vޕd&IXhMRβlD=v؎xW n>uyqn+7ˢ/2f0g" M$RuUҖ%mI%$RVrl GjQK}bvC㰶H/Aԋ9K>z90/eW|U"aJ&(;*A%hkGeQxQxRlfCjԘwY;w+4QG\+n*Ϩ= lCTSM,Z_(sveu徤lR4+e ZD>o N EiH|H|ޑ ,>YsHժ0M|Ucjg;sY`dM.mBg1d.!q#v_vafJLc0jR町#,~S, |#aLTZ`B0!+2Z}C 2KGCa>߼{?C6Wf;NڄOOm*κSS? E_abQ EY6vT6u?Bޮ䢆KDbCMZxn}x:v:r۷7etZ\ܢ77@ƾF&85(w,XZJ?0IV7F}7#e/UO2g<}jD~M&6]]Qf Y>3қ nm6{VJXma>@ ;[A@-rTB/{Ni͎u%eR9Kg J<]X䥰ЧnABԒ|&h5~7g"2NPXl It?Am]70lNg/(kzhr=[.>|^c 9Ɛh짋bH˶W&^) iuz{9 1XMV]yo9_ KsN4ECUg;iJs diN޾ ݯ_#"=U?eE)]*jWA] v*Z+Enwk4S宬ˢ9ͭ{~$-1YԪ>jd(jw8 c+ endstream endobj 601 0 obj << /Length 2029 /Filter /FlateDecode >> stream xڽYKsF Wpr)5m]Τ3I)W6THrƓW @*w^^<{LI)K.w 713\0Tu5QSsAVL*y|&k4T"&S̨kEi'UKf(鏳 1©d_7Z WͶ>vJõ[twhC6~ۺ芸aҢ)I6䰷>PC5:R^)hjA%*$F&k=#mB9E6[nwC]tf}qyz& $fxr_4)uBMrH 3BN~G藓<3q!Z80Dr5o&+Z&UGTI(USJ1 hg;,3`g),1~? Y#22rF,w*_~lQ՚{.1۽}>q15u^qs&?_j-\-Ot)4*.5۶skp g8HTqЃZq& epЮ,uAsC>ED~dAdϑ^]Gn@*b_cԱ LT9Qbp[L5 h4 A$;@UjWqLoM ik[VL}3PA(q{I0l̛|«sPi;sp:[ ?99OKMhD.'t ];uNB"c+BK"VBLZ !:BH0bHu]Q >麡 |)@i@}\gҥ&ŅY8l1+; ko``yĭI u`[.5g[A4zp>oڮ} j'$>2]1`wvyw,F*#+@7oHL:y*GTy-C/|qֶQh)c~Z$\}XWF6UN tv(b'!f9?炊c)'T~F"=24 Z_h> ~6cE19#_}.nGeM8pXrs% W<d ? :BLs/];uMx V}h (LoE|WKhhۢ an Nzkij57Bqw]af1k$N"YPd(!lgh(׺˥n-B-`CTq&ujdXC &h) Ļ<4FoOm|qy> endstream endobj 627 0 obj << /Length 1864 /Filter /FlateDecode >> stream xڭIs6<7ŭNⱕ3IDK%Rå> %ʤ,[ - V^`jbr*G9RZov)1_&7I'")ϳ7:cHuQeJF7$βz!q0$xdlrMjfv$GLv8f0OH\?ɷ4ѫyYv$y;sNJٲ1Πw"`{g#?ؽW~%2 Jh$U+LyrTc9\"&T$y@ḳ1 ATw,^ĸ~s0vc a&3nmyeLmڵBؿ̑.% T0Cq۾ 9yB"0&3EzD4/{p&:H`qXe4gi)MNu!1{Pu|MTky)'f',d:\4HN2)e 6|9e9 Jǃ(231u'ifz$ÑH&]$aԧÝSp +0EW&z 7qз/*AMMM1)\[ʡ@r>" N0P`7IS"WI5R#ƾ̙^MMT .m߶:t;jFeSCB: YˤfH>m{;jj&…P*y΃up3(?5 )>OM{.'&M@#B)Ntv,5LhᣵBJ^ $fk;z=\( eI0H4Hbrww1QqWøY"Z&N8EuҜ7'&iL<  f_ Omc ^@ꈤPrkڀ$+7R4 {HL7;3u=<.]AN{'2:|/S>k~jחǗv-ޘgdVj E(>'_Sx.[pŪ+!aB@Η̇V?;!G$\DeĭuGn_jM)\(P*?>AEE;eSU8%^l(qe7ڽ|FLiR$sWs3}.ms*Nj/NNwyQّĻD#,ʤoqfUnUw7V/{fisYdYrЕA=p y\ATW05/'NjH`~GGVVkHFR8 I:{?Rp endstream endobj 525 0 obj << /Type /ObjStm /N 100 /First 885 /Length 1997 /Filter /FlateDecode >> stream xڽZMo9W89"YEra &@d5rem6$\GԖ4i}8lbUH}40ea_ VL& 27 `Dq$&hRlW|6%}C yKB'~!C !v"f8+9̀jFPN0CrI$`&t r=:7t~{DNW4sfAGTFRU,x.0gA@r., ɥ\Qc: d&v‰L0j!:j%Q4!~9 >/d<rWrJPLtg6vC 5&4dȊQǨS5&2\ pœ3 @,jQ6DЁTqJDR'p)сS2T18eCбCe,N(2:H-P\t\O3$ vI A Q xg/ēɤ 97u惩$b>~^9;3Յ:k)oi7 ~W@vD $Ns FO\ S}~R|E˰W Ti8 nx=R593FO \^u>אxd#UI4hpլyc4Uԓ}~~~Au`ROm%C(֑ҵX/ycz[ joGؒd$,g^@&DOR'eh]e_g7J)Zok:'"r-['lV`v%uhM;NTqP6b!#c!)c %Ib5Ƣ/6‘1d[b?ԑ!w] A̝vXfKf:D@Is% Cg{snX.>l=Z ww~ǼĂ X_ОM(Ժ`e$Vr ;|g[_[CNf 6s9rA|܂+/(G@vlSi[h6߾;i-w"mv[fہYGQEJ-WP^KEJ7ܑ;Q'RYFEˋVmZ j=Ҟ a!/sMŮ]vt^Q/D E;j[JF~uJU~]~zdɗJA[G_7i-Nߴ<"6߷T@b\=#Gqg-y[}n젾^?PrZ?7|J]V[G+>0Mv+% zx6J gMd*1BEo&"tIp4s:ۅFuv4Js=_O(zԎ>> stream xڽZr8}WhWcw=mR=D y@dIc066~肦չ.DBMfgzeqitͰ:P[cd"vt-Vڷќů?M]O:tOkԋ>G0^SI_Ynj >9¹T~HEo猪4Җ^w2Q㢺*.eV8[8uwXroQ5YVAOզ+A^?Yz9Kq#*= 0^E#$sY* _Ww];*ƒ(/E~H[>5j&zTyX_"ݣR~s{#ZވxZ̕#7;c @`H5^[xЛ6W{ضݲy ټ]rD{쯦 $:yN ܮ/Y\">ګ@9V(/wˡ$;?Qn #1QEA&7[>w%> stream xڵUMo@+R/M*QH !1jzYt ϼy AKDlpqg(2% 29(M(T= 7V ,ь㘺T01%G38Kb51T[+x_ d|XL+QDȝw-'`nT`W;To %̭U(*df+!4?(Z ͤQg6ּ>.'ܔs>PĘEl'b0.y̸*tPD P<:mTi((LDGu{:RU;0(L佫{5*뀵ܰ1Ì$/#/Y0wޫU aB乽#"Mֿzߔ L^*/XLrea?8u zslbPN.H虭%N^ԗBn˟umT M츸UMnZU* #`FTv)F,.o;wGcLkTeqTZRHL85ˎc䱮\)k/S0 ֊o> stream xڽ[]}YF$  6 (d:q}Ι{m0,0}nOuM}.j*)ԒbdkOn[>RՒj`de$-xZ34$5+~oYԛNMCZjxNX8?D>RxIj=8B4i%`T8 V;~GH&CKޓYZx-xNTIl[^ϋN䂗Z+0j$w於7Cn1s;Q' Z@VUj{un2%O} A0`  CpWvU(dr"FY@"U-Bj,& UYlaЈ gIg'zwp|﷗xp|_ox}w//=+pp||&=SLm.-ws컟K' }o~w(|5j-<ճ[,/qBxWnnxys>U~Wx*G8liY ;ݘ5rioiY!2C䊐p!gN{O^?fZzP!mxs , "?>zw%1=xO/I?4G0;pqyuQvfw/./o/_~5k["2&H L 1c>m}zUjsNz>瓞Ozuҫ^W':INzuҫ^Lz1Ť^Lz1Ť^Lz1M2IMzZO&6IOz}^'>IOz}ޘƤ7&1Mc| $+T,%vNT-{YM8dMp6(-é d;1DbČ&a"Z?΃؆( 7P kPRÄȄtE(k&H`f'&艊)7DAE6&7yh@(Č-| ؀&Ɩ8oA‘OV2udi!(Ӛd1Cs,mi¢в!>"Ђ`m'&P6DN<茚|$@8]Zn}CEKCP`ax}P$#KX.+Ҁ Qb },Aاq6~m;i]ͷi#NV[KC.+n[zCwUM 6 ٧)b@'; CP;bx]aBTd[ovʫS8B35Ȧj;6%ڐ9=Opnh^-,4щ:8;/Yoh=!"F]t^w [N< d ؖ1`e0j* bKdC0iTvBh< SFfi?r Ź83^N #}S.)\3?gҼp[ymi~bqfj~1kgjLM935m`f̙qis;vp\u6IO&=m:E|1 "N-.&"x`| q,n ZqqԶs(:gyӿlp2OA?}X`΍@~;)Y$CCȒ!5 4(k73cc%|}Oѕ't0KN#TQD}҇_oԇG%;O`!2LnGH\|'uXKZ A P)6 8kl8\MÛ;иI 'ejmۤ{dKҐ==y zMiC?~FZ$_ endstream endobj 724 0 obj << /Length 203 /Filter /FlateDecode >> stream xڵ1@%$x1D+ cmy`IAXgVYl^󓙟qA'!8Ci'  S ,x܎ 6@EB!-Q2pWSikI LաzDGi[ZK.x;SE S<U4GjmdP1 Xf\$ endstream endobj 725 0 obj << /Length 202 /Filter /FlateDecode >> stream xڵ10pDD'㤎]q@D&$:|I8G!>=:w.O>)U$$6Iz .ܭ3xnIe,D^!;h90Z pD m.CSBX[?`i`^m]aOcGVnihEOE^ endstream endobj 726 0 obj << /Length 105 /Filter /FlateDecode >> stream x31ӳP0P04Q04W01R02VH1*22(Aes<̹≠=}JJS ]  b<]?$`)( endstream endobj 731 0 obj << /Length 244 /Filter /FlateDecode >> stream xڭбN0 `:TG_ҖpCL &`J~> Uq,ĉ_]"hKZ_=n ; Z0+5RaK~5C%'>;*\ $U+u+}e'}^ܧ_"dj_V˿*'1S9}q2.Wl9ɒCТfeDE3vgZyٴfȅ endstream endobj 732 0 obj << /Length 200 /Filter /FlateDecode >> stream xڭб 0H-} LSZ N⤎Q;\Oh 䃻 jh1W/qz1pAf@Pki| }Qa|cpÖqA# KN2lɠw:RE99[CO#/Jǎmݐg'7ΐl9gXɣ endstream endobj 733 0 obj << /Length 213 /Filter /FlateDecode >> stream xڭб 0-}{O`@U8 kTfИXi${NRuZ:AW` D{JPhݯ=RO39ǰOX",@,scm$61/Vq?*{b\ Sg% nQ6Zi/Zt"Md!N r endstream endobj 734 0 obj << /Length 137 /Filter /FlateDecode >> stream x3532Q0P0bK3CCB.3 I$r9yr+q{E=}JJS|hCX.O@DH2` #d?# rzrrӄ endstream endobj 735 0 obj << /Length 204 /Filter /FlateDecode >> stream x}1@!$p,A+D ,ZZhQ8–[lXH42gƧQL!E4)tx81aHI4L d;d+#+t=Ȳ͂89\-<~H+O _* h ~[+"S'F־1ƦMOMW`HG>?-(RMǠS,p/Ҋ) endstream endobj 736 0 obj << /Length 225 /Filter /FlateDecode >> stream x}1n0 Ed0EG0/ ԡȔdР7 dPK#O'O *k!XnKVz>uөg^3e݋}N7Oo#XnkR 0,H"`nX,2d;F)ԃ"G ٦)eC$9َ}r9H>Gime2bֿɯꢻNǀf endstream endobj 737 0 obj << /Length 208 /Filter /FlateDecode >> stream xڕ;n14s5,r%[D ")S$"r4Gp`(RF}?i7> stream xڥ1N@Y478n- T)UL(ԛ,IdUq n#t-l#k&ĖH endstream endobj 739 0 obj << /Length 225 /Filter /FlateDecode >> stream xu1N0E49BM,)@T@"萒(9K. #3?pW=w<~(ё6[;ϝFOْSxϟ_dw7qB#h%^J"s-,&ï& M ugTi: d)ȧֿHee_3 Y}ETԼ4rs$jYh%t;#k} endstream endobj 740 0 obj << /Length 166 /Filter /FlateDecode >> stream xŎ1 @EH!%q1[ZYPUx!㎝Vd7<[W-SÉ@fޒYFLXr;)svdJ9{ %_@"-0*rࡐZ'pGb4"mz!IoMSK?7W endstream endobj 741 0 obj << /Length 141 /Filter /FlateDecode >> stream x3532Q0PbS3#CB.c3 I$r9yr+q{E=}JJS ]  b<]0000PX?Po?=``D xr "cn endstream endobj 742 0 obj << /Length 127 /Filter /FlateDecode >> stream x3532Q0P0b33CCB.cK I$r9yr+[r{E=}JJS|hCX.Oc`'\{0 ?0%\=Rm endstream endobj 743 0 obj << /Length 175 /Filter /FlateDecode >> stream x1@O75pD ,ZZh:JD<@J ˆbb%3򎃮i0f3c3n[6DM8eŠ8NDRrpEEVn4TKUT|(UBMҸHȿ(? endstream endobj 744 0 obj << /Length 170 /Filter /FlateDecode >> stream x1 P t*d |BB`A'qRGE> stream xڕ=@ #0e't$$RheaB5pJ 6&Wd^狔cy9ƹjzPRei.;-+RGN R[&U|H-+֤|Z3/PDx"_  {MءlQ5򃠳RkD0qM]Is Fk,Uel m*:9n endstream endobj 746 0 obj << /Length 172 /Filter /FlateDecode >> stream xڽα 0@εIG882:Ht>85g<G5oHYc\lːIN͌Od>"YJq&S"EE\-u׋p*X&.EZ7-}K7-^D_~417yi endstream endobj 747 0 obj << /Length 177 /Filter /FlateDecode >> stream xڭб 0+ 4%q- ftr'>#t =/u AIn(ƚ!kxB%N_C!Q-$Ft9_Ռ$h+3;tA|y=8ނM?`|ҋ-xI ,vQOzxE:Vv܄#Jsk|jVmx endstream endobj 748 0 obj << /Length 194 /Filter /FlateDecode >> stream xuʱ 0-yFcB`A'qRGE(} 1AX>%E4v+g$'txE 9ʵ5o3t > stream xen1 } p~r$7 1юZ(yc+ d/dj I8&,‚}bTl+bY\2L5N{Gs/Pܠ 1?3W-%_} endstream endobj 750 0 obj << /Length 251 /Filter /FlateDecode >> stream x]1N@б\D&Gع؎HT+  * ()@*>Vu,7O?_f竂RlSqAENObQ4xz|M=%&>ǤgL6aV[2(̭v 9LJt'XX=YjUI+.~ЉgPws+CF`CHeD%;#7R NJCwX}xU~ endstream endobj 756 0 obj << /Length 111 /Filter /FlateDecode >> stream x340Գ0Q0P04W01P0U05PH1*23aRɹ\N\ f\@q.}O_T.}gC.}hCX.OPeĀk\g endstream endobj 762 0 obj << /Length 171 /Filter /FlateDecode >> stream x31ӳP0P0PеP05Q03VH1*26(Bs<M=\ %E\N @BA,N؃$0z8Q'`& >`& `G${ ?Qr `E endstream endobj 763 0 obj << /Length 171 /Filter /FlateDecode >> stream x}1 @ a!s51VBVbnY-DM(HgjxD1alT+ Q9O=|1!w)ڠ) B T{@6\% .:Z@ Z|ae_U/b endstream endobj 764 0 obj << /Length 143 /Filter /FlateDecode >> stream x=1 @wn^Xbhi(m,-q#(|cYj9֌YJUT΢yךTN̖Y ƭx܎b*N7qDoRp, endstream endobj 765 0 obj << /Length 99 /Filter /FlateDecode >> stream x31ӳP0P0Ɔ )\\@$lIr p{IO_T.}g E!'E@!ncr h endstream endobj 766 0 obj << /Length 143 /Filter /FlateDecode >> stream x31ӳP0P04W06P01S05WH1*2(Cs<,=\ %E\N \. ц \. AA=ga{n@Cq `ar S< endstream endobj 767 0 obj << /Length 193 /Filter /FlateDecode >> stream xe̽0[x "~- &2`A+Zl+ z1xK7}`|8CQ'p7.h nv7Z͐1nc!孅+ ݗД>!uBG3%9mM5F4V.կf֚RFiHk7e0)#W^a> endstream endobj 768 0 obj << /Length 253 /Filter /FlateDecode >> stream xuнJ@ba;/@λ 8BQ7Q̣RZ,;n<9Gu|Z|XroKz)ssO놊+J*4LEsOwT/NXkj6 C"y`ECt>W Y3]>}vrÞ}ԩ:xAjmMcHo/OvjaOMbSjTt0q;٭'Kjiyq:<贡K~) endstream endobj 769 0 obj << /Length 186 /Filter /FlateDecode >> stream x}= 0-=B LMѩP+AAAh=Gpt{1b$#CHTا39nR؃Vȃ|Ai@.P+ix< S.ST+066kˉ $Di Qx7~qvy7+DDDCt> stream x31ӳP0P0a3S3CB.C I$r9yr+r{E=}JJS. @-\. ?000+ e8Iv!#!d>B2#dn?`c XYc%e0pzrreT endstream endobj 771 0 obj << /Length 262 /Filter /FlateDecode >> stream xuAJ@xAN`bP+.U҅"8EBxxq7@|/Ģ.oa7Jh+(*[$'eY1Ƨ|qqFwΏ)xN)%WX 0 A@'X!TW@ F-@\GaL@+?QowI Sji*ՕTj`t ^3@ #=ңuf'^^ endstream endobj 772 0 obj << /Length 215 /Filter /FlateDecode >> stream x}бn0n|OPBP:!T*CfeJ;fhծGQx (JXbٟtg4{y]SLK^+}&iƵq`Q=P}.rG?_h %htL(>a%ȽwGk]BrQN &Cv&̍A FȗF7"'1u&<کZ܆dT?s1ݭC&Vo} endstream endobj 773 0 obj << /Length 234 /Filter /FlateDecode >> stream x}бJA ,[ G.Νg5pVZZ(ډ;ba;$'XHglEQMaE%=!H4uB@)m=__S~Cۚ;l6-30sofs0GЩz*pR[3fK鯢ق:w#ĝhI;3Y:3]VKq4C;࿟y,mw%wfi_ x x endstream endobj 774 0 obj << /Length 262 /Filter /FlateDecode >> stream xu1N@E"4>Xq ,  * ()@ QaK\#Eg xyxԙ.rS/I9,/ݣkoK~<>H:Bn JQ 'PG>&f_S3 H#>%Xh:Y3ICE2%3ЁUmr88va;7;׫g*zɴ'H 8o3.7F>se弖k" endstream endobj 775 0 obj << /Length 222 /Filter /FlateDecode >> stream xmϱj03 |/m&CB=کCdА͏GK@כG)ŖRURղᴔv͇ۖ8lW96۷'lviv'Ncm6Qrő9n6S8iɷDEHȷDE5G%j`XI[B 6t OR%L@EaM-?ȀN endstream endobj 776 0 obj << /Length 217 /Filter /FlateDecode >> stream xuнj0/d%wМ+M$zSҩء% Rr =+:‘xq1^.4"Ngˇ4g6˻JqZݥSqVw7q6k,F116? amu-AcvD J+th%J/пOH='TOIi ^şܖ gv3 endstream endobj 777 0 obj << /Length 219 /Filter /FlateDecode >> stream xMϱJ1"0>Bt7BBGˣ#\yŒYC_„kJςƵƠoA{]VyfIc/ݝ]Íqh H<YNW͌!#|i~8-v:Q,b#X}n}Hْj`O:Aom"jAk1xp3YvG-m endstream endobj 778 0 obj << /Length 235 /Filter /FlateDecode >> stream xu=N0\X&G\hVE"T+*D49# '@|{SYO7-մ-3.ư١m--Z.sUwE/oXmϩjG;vd)3v(&_*r) ԗ(G^KoNP=:F#Ȑb0caߨ``u`;}!A%gyY$ქ<K~ endstream endobj 779 0 obj << /Length 210 /Filter /FlateDecode >> stream xڅ1N048feH-AK|%G2amCEg[|w[>]r-;mzM[.NGxSӜpϟ_{ ۇv}a@ZJhD2Ȅ$2c4dvJuNͨ (p7Rij/M)vAm+uӿ@"S endstream endobj 780 0 obj << /Length 232 /Filter /FlateDecode >> stream xmαN@ `W"yG8DJS:TD$02ʚY%AC:d) MܜSE-ԬiSTk> stream xU1N1Ei|kBR[ AEQA h.SD;&O͟7+nykzeayH={ɏ#~@~  ,FI# $Hy!p9sP SlQ S]BS3O?9Cz 5I[lIݐ\N+*iD=ktSn'-o endstream endobj 782 0 obj << /Length 190 /Filter /FlateDecode >> stream x};@%$p.$1q ,ZZhQ8%aaD)e3&SKp4C g0GgԂޠ1mx܎ cncv`3TJyĨJ6$(r&;;/Xy9pED]Kv6}zκOY8ˏywf.'+yWana Oq endstream endobj 783 0 obj << /Length 286 /Filter /FlateDecode >> stream xuJ@g"0y!SZYZZ(]-rvABs.ovI{F%t\tZSSc/ش\-iYqaqKM%ױ 9UXl订 d ybR.aa cX"`?5̆o,, ߫0Ȅg_RPg)$.z4/@ciJKJʓnyA u%>@+ +0@:ɝs<#Nz3b:%^txۺ endstream endobj 784 0 obj << /Length 207 /Filter /FlateDecode >> stream x}; @49 SZYZZ(f=Z"xSg7 ?2Aɥ ^H[]McajIj*UTNp>"՘VkQrtaQ d,ɹu|--"1^JBR̉*z&v:N{X5gS\Uo.Nb\ endstream endobj 785 0 obj << /Length 168 /Filter /FlateDecode >> stream xڕʱ 0+[| LBI Njh}x&A Ifz9mPkcaP,IkSע03:;|L EI+Er$ 4./ @'PE \b<<Iya9PpbpO)T< endstream endobj 786 0 obj << /Length 210 /Filter /FlateDecode >> stream xڕ; @YRxtJ +P,x4#XZH 6.W 34yP#PKkwFzV[s #cQ':t@>!-| 䪧䟘L=̿;w3'EP+l7jӯi=|:s+b-SJ}e GrQ3|d endstream endobj 787 0 obj << /Length 221 /Filter /FlateDecode >> stream x}Ͻ 0C>B Zt vtr'utPtS,GB1EAA1$$wKҬ`[43\%4}r`^jijD1w5ޤ l. 0Nߚ`gTj*YO8:uȱqJꂽSyXND!uаڻ7ԗ:1D&/e6 xE3~0)<|] endstream endobj 788 0 obj << /Length 159 /Filter /FlateDecode >> stream x31ӳP0P0b#S3CB.cS I$r9yr+r{E=}JJS ]  b<]``Q"? ?8 8{0u L?` .WO@.R_^ endstream endobj 789 0 obj << /Length 177 /Filter /FlateDecode >> stream x}ʱ 0J-}{B(u* ftr'utPt+G#t< pwxb1?p dsԍaw\XL@y B-r@) -=/4mVgu𤆚N-.Ѧt+.Jf{m?FN3w!ct1]a`/B' endstream endobj 790 0 obj << /Length 190 /Filter /FlateDecode >> stream xm1 P ,jEB`A'qRGE>֣<;B|?Ns42!Mgohu۶՞Lj-)tC*.G'}4!r8FJp-27sX;+YJ>!PDhxհ#qʩe#\Y.D*~ps endstream endobj 791 0 obj << /Length 217 /Filter /FlateDecode >> stream xe=n0 ^ !Ȕt"YkMG4z0R :]ށ"ħ=,\'7O>i:aAOtL}eÞܖ[V($FFUG"@'C;MBMIU (5[resKMSCЩAgC4jFV"j"kJh+bo endstream endobj 792 0 obj << /Length 247 /Filter /FlateDecode >> stream xuпN0/`<JUeTD$02G#d|P,'?.n\uۚPk^kozETkToj/ ׯԭ 6~9H$؀BzF{baIu=L1;> stream x}= 0 kI NEzbIJS$.(qfc.1xIjsq$Uj"ۯ1)Fy#ҜN&"Yy 2$P5sΚʮTz)z@=qQg5椳[o }6 dcq endstream endobj 794 0 obj << /Length 222 /Filter /FlateDecode >> stream xm=N0_4{2lXҲH@j D (GQr.L(4~sr>p>ܟq q<> stream xuϽ@ ^H.1::htG K6idP@ 5E5^0PጙAKaRݮzNi)أ F8/nO+y\җ1DgiP->Ձan,Oz౽R0ʞ^ endstream endobj 796 0 obj << /Length 187 /Filter /FlateDecode >> stream xe=@!$p? b"VJ--4ں{4 Fiͼ$)%)]"c0;9߰jP(PlL񺢨v+Pt(> stream xmͱ0# $'" b"NI4)h< бZ{upФMGlL%%c4g WfY endstream endobj 798 0 obj << /Length 198 /Filter /FlateDecode >> stream xu @ st(d#'ZzNZN⤎νGQ:v䔢|'$f4)یС39( 5 zSt5uEۂAJO:{OZ*3yWxasz Y:-FqD1G̢8p|)u䨍Fa58o endstream endobj 799 0 obj << /Length 179 /Filter /FlateDecode >> stream xm; @YL#8'p+U F0XٛQr)$㬈k ?S`O'QD4>&)"fwļD$E3\|=ɗS)bY LTUB3K2Pmr/*qOrZv_Ծ~bnJ\ \T endstream endobj 800 0 obj << /Length 244 /Filter /FlateDecode >> stream x]N0 @qK?j`Jc N'q@p%~J>a)ODiVkh)Y5a}[mpaxfV;x|ŰÖj?D˃yp̓gYYC;@!&_@b˔?ճGefoT8g~цv@Q6tozazkz4Ut_)ΔQMEјw>7x@ endstream endobj 808 0 obj << /Length 146 /Filter /FlateDecode >> stream x%1 @E/d y+p2dbBB`6;%XZ<\W%Rp9E^h1ӞjvȜj,0vEzP`K$%b$$T$E d+oѥ׭{/ endstream endobj 809 0 obj << /Length 197 /Filter /FlateDecode >> stream xڍ `4w/Pj)MPԚ>#46_Gth =(TWC# |=yrϭ3;/ft싳^l,N+=u-',]ƠBR"/ w]OJ Hѐ4MJ0?_9.6վэ-iN͋eVL endstream endobj 810 0 obj << /Length 196 /Filter /FlateDecode >> stream xڍ= @ GbVbh%GH"/Vef Ʃj?8$C(gbg(X]r;fwPL@ | ~nF <z/@:Mrp\3]8[FihHOҙAHVxuO endstream endobj 811 0 obj << /Length 110 /Filter /FlateDecode >> stream x31ӳP0P0TеP01Q03VH1*22(Bs<L=\ %E\N @BA,BQ? C GG\\\0oy endstream endobj 812 0 obj << /Length 112 /Filter /FlateDecode >> stream x31ӳP0P0VеP0P03VH1*22 (Bds<L=\ %E\N @BA,B@ C \\\HB endstream endobj 813 0 obj << /Length 179 /Filter /FlateDecode >> stream x31ӳP0P0UеP01R03VH1*26 (Bds<͸=\ %E\N @BA,B@0"00ԃ@D0 @a"W" ",XL/=  p ISp endstream endobj 814 0 obj << /Length 106 /Filter /FlateDecode >> stream x31ӳP0P0UеT01R5RH1*26 (C$s<͸=̹=}JJS ]  b<]L!W51 endstream endobj 815 0 obj << /Length 180 /Filter /FlateDecode >> stream xڍN; @n!swCM*!Fp A+ RK E;!/^`%mȸ 0Ј2 1> stream x31ӳP0P04S54V06R04TH1*24 (s< M=\ %E\N \. ц \. ?aC??@P`4,r endstream endobj 817 0 obj << /Length 96 /Filter /FlateDecode >> stream x31ӳP0P0@P!Ő H(`\.'O.pU()*Mw pV]zb<]\= endstream endobj 818 0 obj << /Length 162 /Filter /FlateDecode >> stream x31ӳP0P0UеP01R03VH1*26 (Bds<͸=\ %E\N @BA,<b@N ?8$D D`#2f2X3Iq,63 *@'W yK/ endstream endobj 819 0 obj << /Length 104 /Filter /FlateDecode >> stream x31ӳP0P0@dbUeh䃹`\.'O.pCC.}0BIQi*SPE!'EA0XA0Փ+ 9-I endstream endobj 820 0 obj << /Length 157 /Filter /FlateDecode >> stream xڅ0EkHO-DD'㤎]O:2bg'g/18ǂS WqY2˝jCHo mvx=7~ &ĈdDVvUr9+G^‹aUnF;~ZQ:?8 endstream endobj 821 0 obj << /Length 111 /Filter /FlateDecode >> stream x31ӳP0P0V04W01Q0PH1*21PA#CLr.'~PKW4K)YwQ6T0tQz ?*1pՓ+ JS endstream endobj 822 0 obj << /Length 102 /Filter /FlateDecode >> stream x31ӳP0PP04W0T02VH1*26PA3Dr.'~BIQi*S!BA,B?ĸ\=E:( endstream endobj 823 0 obj << /Length 118 /Filter /FlateDecode >> stream x31ӳP0P04P0"sSsCB.#39T*9ɓK?\ȌK(ΥPRTʥ`ȥm``P !\`߀ Apzrr]7 endstream endobj 824 0 obj << /Length 190 /Filter /FlateDecode >> stream x31ӳP0P0bSSsCB.1s<L=\ %E\N \. ц \. P߀ J2~~d|"N`%값 hL F'y,$33oAYՓ+ H06 endstream endobj 825 0 obj << /Length 198 /Filter /FlateDecode >> stream x}ϱ 0 [|TkI Nj}>JcҘ 4蠄|4;.ˇ)Jq)+di#  3 bnA5o3bDTYk[z^DyÒ1 <§QSHhUsjD0N/QG<T]KDbh@C63K[xGj endstream endobj 826 0 obj << /Length 230 /Filter /FlateDecode >> stream xڥбJ@/L i +PysQ%o镶={[r\/䶷\C#;"L E(JdG)23!_#2C[{GE{ʐ :Z2 fFb֘9e)QSFO?V2C鎾?9ru endstream endobj 827 0 obj << /Length 197 /Filter /FlateDecode >> stream x31ӳP0P0bS3CB.C I$r9yr+r{E=}JJS. @-\. 700& @Y4$)&?H L2A :0Y&q RbbH.C _@|A! HC, !݈I endstream endobj 828 0 obj << /Length 149 /Filter /FlateDecode >> stream x31ӳP0P0bSS3CB.C I$r9yr+r{E=}JJS. @-\. $BփI uD6`D2JOĥj2|$(47Ae\=WD endstream endobj 829 0 obj << /Length 141 /Filter /FlateDecode >> stream x31ӳP0P0bS3CB.rAɹ\N\ &\@Q.}O_T.}gC.}hCX.O$3``'Lȁ|DAjD  \\\, endstream endobj 830 0 obj << /Length 230 /Filter /FlateDecode >> stream xڕN0/?BՅv`b@Lб $R_.jKŊ-}oﳻͦTИJr&7R+Ly?ocv~K*^d`dPɑaDZN{8;@Ά:0GdzT 3#'d!Q M4 >15Ȏ×t*ć5 endstream endobj 831 0 obj << /Length 114 /Filter /FlateDecode >> stream x31ӳP0P0bSS3CB.1s<L=\ %E\N \. ц \. p,~BĄ'W NP endstream endobj 832 0 obj << /Length 105 /Filter /FlateDecode >> stream x31ӳP0P0bS3CB.c# I$r9yr+q{E=}JJS ]  b<] 0 %\\\6Qg? endstream endobj 833 0 obj << /Length 231 /Filter /FlateDecode >> stream x]ϱn0` n#' v D$:1NClf1t#4Cd?Ka@?>ό/x7e`+/l2 .|w9be;U:.Jp΂Zг j@AR&B n ~x)[yF^}lEƪ# `"P0~? endstream endobj 834 0 obj << /Length 126 /Filter /FlateDecode >> stream x31ӳP0P0bS3CB.rAɹ\N\ &\@Q.}O_T.}gC.}hCX.O``'!P:'`b\=jo endstream endobj 835 0 obj << /Length 201 /Filter /FlateDecode >> stream xڭ1 @4 \kP1),J--!9D,,T]S[̃3nQ*9zK5.sWj9!!qSdaV o,cP$nPPBz@Q(>Zll/5.K=&Mإ(o9)[-_m0v`fs8 endstream endobj 836 0 obj << /Length 199 /Filter /FlateDecode >> stream xe1 0-wӖZtP*AAAQPPRo7iqpT I( 8{~B&6}\9Ol[L,7@g@GEq;>:@8w^@8@X&as!eV^zH4 6Q25> stream x͐=@XL #V &naRK (҂.C l}/N竌BJh&)^PF ] 厹Fq(Eu1 }C$QtQZۂgmJ9Հe 7Fд?oaF k ,|_F&h endstream endobj 838 0 obj << /Length 182 /Filter /FlateDecode >> stream xڭϱ 0H^{ӐZZ+AAA(}$]8N KM9&xg,\Od+ f.S0~ ,Ђ)qo19/"jB.P;UuDF 'aybhF4j-iMːO*"`a oƅt endstream endobj 839 0 obj << /Length 217 /Filter /FlateDecode >> stream x1n@Џ(,M#\j%C* *I"Zo+M|k7c܀?WgiG^,#orI^/*J{rϒ._t<.^7!-i<Pqj,Q?vtDQ[ ba~WJ!IdGSI;% endstream endobj 840 0 obj << /Length 218 /Filter /FlateDecode >> stream xڝн 1 Y|;? N⤎磝"b/Y>Jڤu)&cjiɈZ=qYh>&xޡG*hɘR. eى/".Ҭt ҪwVhO/o2C xBbMn7ݥ| "Ԁ3ï>$$J endstream endobj 841 0 obj << /Length 250 /Filter /FlateDecode >> stream xu1N@E'rai=1IL,  DѶ. (ig?lncQiں'Tl=yE&lk\FZ,6KNZa| 9|t5iûH Jbz<rd'0 (9qp&8 %?cFi=H^Q #t)g/pxLkDυ3zA endstream endobj 842 0 obj << /Length 127 /Filter /FlateDecode >> stream x31ӳP0P0bSS3CB.1s<L=\ %E\N \. ц \. D?`OY$$ ;R?$XՓ+ VX endstream endobj 843 0 obj << /Length 174 /Filter /FlateDecode >> stream x1 @ ) fa n!he!Vjih-GL2 +7&.&RY S2sjOƠZKFe7?/4#ڂJ"nݯ;QO7ZB؈U$fMYD@ ϝf+;|WW endstream endobj 844 0 obj << /Length 197 /Filter /FlateDecode >> stream x} @\|jU$A:uNձCQWQ /mU%v?,Ŝlriz mgCsb ۓ"[YyAm }$E'}2FZ_V7W?Wei f )XP>V*5yMg9V/zVJAf9'*LCx8 endstream endobj 845 0 obj << /Length 210 /Filter /FlateDecode >> stream xڍϱj@_pK@{98Sj@-48 -rpnA0f#VX܏]і1ey8%dIL2~Ar<"9hM锳AitJweB# LX6vs`RaF$i4 ;QWytExݭ'{gk~϶,O*$=t %~ endstream endobj 846 0 obj << /Length 242 /Filter /FlateDecode >> stream xmбn@ P#$/ "L :vhծgO@@$2Dv."PtO h"+4}ih//hMм.tI?hfs ,hRtA אLZ5;: Gk?ޱR/R7ux;xl;3{gߺjmkxN|סuޔΚv:T-tjO;Q d,ŲZ8ݎ[+R endstream endobj 847 0 obj << /Length 220 /Filter /FlateDecode >> stream xu=N@ _b%79 H" * D[n&"ymafYy.\O:/wa\gVVOK{Ǵý~~|m]=(k}fϋ kEm&fhF hrá +'2ʉ3q4|PY؁0e齳s5\@e'XreSU4Q~MQd endstream endobj 848 0 obj << /Length 206 /Filter /FlateDecode >> stream xڥϽ 0+->Z+S*AAAѹ}>b$*.bBz:ԥVDJQܣmT;fiTTf3:; :Yc6\;lhkb⍹/N-Z6*p|ZX?4>usn tn N2\KKv endstream endobj 849 0 obj << /Length 205 /Filter /FlateDecode >> stream xڍn1 ]1%o )$n@S ZYG!i _ϲ=gzp;:٨T6{hh.DmyءQvF0`80cf̱b9)zA}T$"'S|_Q((M I +TPGey?4dѸYz1_ S endstream endobj 850 0 obj << /Length 220 /Filter /FlateDecode >> stream xڝ; @ )isJE"b=A aS~] endstream endobj 851 0 obj << /Length 216 /Filter /FlateDecode >> stream xu1N0E*ir ,-D $(VT@Iv(>–)VAaYO??V=ϝz`U6]oX?ݕvⷺ}qE XXͨ̎p[P0LhB M 4ESDiDf( DETHIc %)>/~Œ\r/_})oG endstream endobj 852 0 obj << /Length 164 /Filter /FlateDecode >> stream x31ӳP0P0bSsCB.c3 I$r9yr+q{E=}JJS ]  b<]300? C=`cf ?F%5Ƅ@.N%\=CSt endstream endobj 853 0 obj << /Length 275 /Filter /FlateDecode >> stream xڅ=N@ M_(E"T+*AD \%7!H9Ec{BHLid=RI'tT%=VjIM}h=<|ŕԱh UXiSQy :!1{.g t<A9Nt¿ɽ`n [Y'(3@ ~sPoi5E,b6y0ɬ1$V ٺ[Lz #h&;ij$^MR} ^x?m endstream endobj 854 0 obj << /Length 165 /Filter /FlateDecode >> stream xɱ @ : Y k 7:9utPt>ZpcҘ(@>?1t>C1I0IF*x܂ڡA ʮv@F G` t>'C/fH= b賚'b6l Q"Di endstream endobj 855 0 obj << /Length 137 /Filter /FlateDecode >> stream x31ӳP0P0bCSsCB.cc I$r9yr+s{E=}JJS ]  b<](B` D00 aDHpzrrȧYA endstream endobj 856 0 obj << /Length 168 /Filter /FlateDecode >> stream x1@!&p,`EVJ--4ͣ(-!5W? 9ER?֔$4hqF=`iP(QͤGet>]ń4֚ | f!N^ :^]寸3 lnO(N . k7 endstream endobj 857 0 obj << /Length 217 /Filter /FlateDecode >> stream xڭνn0pH' Q" vP+ċekdUGk?>48^iƏ%Ii?1B4,Ⱦr'd Wwc'/kL8TEk%t:u=|?Q ;DN d~U7 S[v0ؼ?bjv? k1N\*7V*=4#S endstream endobj 858 0 obj << /Length 123 /Filter /FlateDecode >> stream x31ӳP0P0b#S3CB.c3 I$r9yr+q{E=}JJS ]  b<]``? ×0? 'W g endstream endobj 859 0 obj << /Length 161 /Filter /FlateDecode >> stream x31ӳP0C CB.sD"9ɓK?\ĜK(ʥPRTʥ`ȥm`C}?  Yo`*?!*9=g!@d\= endstream endobj 860 0 obj << /Length 159 /Filter /FlateDecode >> stream x1 @бa1[ZYZZ(ZoG 2΢]> stream xڍ1@E #0eV$&ZY+h+{4(- 㲘ڼOϛ$ͦ񄇚1'O6MvV6&U~{I7 ֤rkT dR" "/x"o"x Aā, Ң~~5oU9qNȩ9IR 3,hK` endstream endobj 862 0 obj << /Length 221 /Filter /FlateDecode >> stream xڭбn0bt @Y"QPNt@hycs U.ɺϿm˧ > stream xڭϱJA?lq0= %*#xE@+ I-SD5_,9 ,9nsckc_ťc?f5ySǣZhZ}dl5.dj0r DW@`D$  F]67@Hmtt9OYw억g߹٫e&ڥOM&7ۊ` endstream endobj 864 0 obj << /Length 172 /Filter /FlateDecode >> stream xڵ1 A i832VºSZYZZ(ZXYz#llXZO7荆d/9C;GtVibs0W,lQ9O=l1!洖}N)!0Z2-ygg"(.0P5tŷAUɲ+Y0\%-nYW endstream endobj 865 0 obj << /Length 218 /Filter /FlateDecode >> stream xM1J`b`w.~7hXW0VbZ * vnUra!,ǔK-tgQ ->Gy劲p3%WtpK-Ϗ kxzX 33䎅rCF40@:b #LɂY.dČ 曶AȺ lB{,Zxώ`1K{+orSN~o' endstream endobj 866 0 obj << /Length 160 /Filter /FlateDecode >> stream x31ӳP0P0R5T01P05PH1*26 \.'O.pcs.}0BIQi*Sm` $?` #$`'0   Sd.WO@.] endstream endobj 867 0 obj << /Length 159 /Filter /FlateDecode >> stream x31ӳP0P0R5T01U0TH1*21 (@es<L=\ %E\N \. ц \. `,dF }H<00g?`G"?\=kqt endstream endobj 868 0 obj << /Length 174 /Filter /FlateDecode >> stream x31ӳP0P0bScKCB.1s<L=\ %E\N \. ц \. 7P& eJ``$? @cg@%4*PFF2?F2~~F2?N7 H{ r V endstream endobj 869 0 obj << /Length 195 /Filter /FlateDecode >> stream xuν @ > stream xmν 0C(vAAAѵͣ7Q|AwݤGr6&آt&=>'|z zzBQvi z0b zoU YUX)է-ؽFF'{DžyVJtlH!r&u]Ŋ;7RCSQ񋦠iwH>ʳh endstream endobj 871 0 obj << /Length 237 /Filter /FlateDecode >> stream xeαN02D%{pҊ.TD$: &73Ea+RősƂ)eTQS9mr|IJҌ.kk* C秗{˫3Q&l [f۲cvӨh+켍 R PPÛLm55wۃQ?ڋ_"|v։&Ԋ*Z IM ]4O`9kb{0D>7k endstream endobj 872 0 obj << /Length 171 /Filter /FlateDecode >> stream xڍ1 @ aM@ Fp A+ RK EۉG(2E:/u ͧB"IIR9|c#ʅgݺ+Kٕr%:/%!ԕIDeoKhѰj#0#0?Y` ` `]ГnS^yi endstream endobj 873 0 obj << /Length 218 /Filter /FlateDecode >> stream xڥ1n@E?@#\ ^ c)ʅ*q"QQ8%Ŋ2[$r~y.9R3.#OcE_/T_ܙt_?g~)O)'o6`Pv*;k . , UPC< èzDNe{Υ]ɷ~+| 2%E_Iqhҁ x endstream endobj 874 0 obj << /Length 143 /Filter /FlateDecode >> stream x31ӳP0PbSsCB.crAɹ\N\ \@Q.}O_T.}gC.}hCX.O@l``z 灸C??P szrrRZ endstream endobj 875 0 obj << /Length 232 /Filter /FlateDecode >> stream xmN0Kxe' 0Y*E"L vd(~wH`O,+¯.wZt7j='(IB??v7ϭo^x# `0#,yB=:F0A.O= {řs2t 9FtJ:ZTTwHsͪTU!,)b")3t#}wo endstream endobj 876 0 obj << /Length 239 /Filter /FlateDecode >> stream xMбN@ `G"yv~%-a H0u@LбCQn館?I}LeC-c%H00cRbL5hR"&\/d /N^J+Jx#jC(^ Nw6d`NV?1F3:=0+(-aO"{|ldy endstream endobj 877 0 obj << /Length 217 /Filter /FlateDecode >> stream xڭα@4;/@NYYZZ(ښWG#Lq:q5_1xD1 P)> stream xm1N0E'ris v7,eHV ()@&9#L<| Q`ɯ9JrZ\\Q<^ W7(s W+:C-GnB"LdT@.ëGHF316 6P9n\ Pbf4RuYHq_#B}!\0gܜ!TFIAC$yDE}H#A _|o_ endstream endobj 879 0 obj << /Length 187 /Filter /FlateDecode >> stream xڕ1 @49s݄$@Vbz%GHbQgq80 qL) (#r(SjEAjgTzNe*]LG'o:+x*Pd܂H.'oR(@RB)`na \# endstream endobj 880 0 obj << /Length 232 /Filter /FlateDecode >> stream xu=N@"4>`m Z) HPQ *HIh{=KV)yl/[.᳊Rsut_iۑ%e-o﮸"NJ'v\8I@/#2DR9LKp)Lz OnPY]D 5ň>Lr>AʍpgWi9ԫo0ZTj~]wtO endstream endobj 881 0 obj << /Length 261 /Filter /FlateDecode >> stream xmбJ@ )yŻgp` ,J--m/Zy/0`0h#eg?|%3Yq-SYc/> stream x%; 1F;]]hL!he!Vjih7eIY@5`NKnn;[.>Yʬz8nQuĥ>W#D*L"QCĶ5e" ьwO)B endstream endobj 887 0 obj << /Length 132 /Filter /FlateDecode >> stream x313T0P0S01T0P05TH1*26 (Bes< =\ %E\N @QhX.O 27??~0?P`G( endstream endobj 888 0 obj << /Length 192 /Filter /FlateDecode >> stream xڅ1PDPl Ċ1D+ cmq@IA;WL0 v xlagnEt4'g'Ty!n{> stream xڅO; Pl {I*L!he!Vj)h-G,-$q̃T;LNuihuɗV'/2O4Ĭxq7 $$M | ,G\W{F9^ـ"J[|rY"ֱ4nT?pGrjݬc_e*[M* endstream endobj 890 0 obj << /Length 167 /Filter /FlateDecode >> stream x313T0P0U0Q0T01SH1*26(%s<=\ %E\N \. ц \. L@$AD=$? ?@P&VV̌...SG;&.WO@.n= endstream endobj 891 0 obj << /Length 96 /Filter /FlateDecode >> stream x313T0P0T5W02S0PH1*2 (Bes≮=\ %E\N \. ц \. (\\\&Q# endstream endobj 892 0 obj << /Length 162 /Filter /FlateDecode >> stream x] 0->KNZ N⤎>cbMN8>] y GGbO%T2[0YFK&pOdLSAZZFHW 2"L}Tߩoﻭ "Іֺ? endstream endobj 893 0 obj << /Length 114 /Filter /FlateDecode >> stream x313T0P04W5W01T0PH1*22(Bs<=\ %E\N \. ц \. a`?r 5ez endstream endobj 894 0 obj << /Length 116 /Filter /FlateDecode >> stream x313T0P0V5W02W0PH1*22 (Bds<=\ %E\N \. ц \. c``pzrrlI endstream endobj 895 0 obj << /Length 152 /Filter /FlateDecode >> stream x313T0P0U5W0T0PH1*26 (Bds<=\ %E\N \. ц \.  @N5 D؁{! ?8$ &> F0Tta*`gr W: endstream endobj 896 0 obj << /Length 175 /Filter /FlateDecode >> stream xڵ 0DQXK'2҆  * D h%##6HWYM0p sf؜Tz2{XKf1)Kd*rdGR/RA-%a|ݠЂV$QoeUG+O;a endstream endobj 897 0 obj << /Length 171 /Filter /FlateDecode >> stream xڵ 0EQ  miCp  (0 i~ϧ{~37 <& ~9JϓJu }s7&xܟnKœ(4^Jq^.JNQr?)F#PQ1H)3R;;J~.؆xC?ZOYb endstream endobj 898 0 obj << /Length 113 /Filter /FlateDecode >> stream x313T0P04F F )\\@ IrW04 s{*r;8+E]zb<] P\=AQ@ endstream endobj 899 0 obj << /Length 148 /Filter /FlateDecode >> stream x313T0P04U02R06P05TH1*24(YBs< M=\ %E\N \. ц \. ? 0`77g.`r j'. endstream endobj 900 0 obj << /Length 171 /Filter /FlateDecode >> stream x313T0P0S0W0P01VH1*26(%s< =\ %E\N @QhX.OXǏ?1 ɁԀԂ2} pzrrxS endstream endobj 901 0 obj << /Length 116 /Filter /FlateDecode >> stream x313T0P0V0S01T01QH1*26E-ɹ\N\ \@Q.}O_T.}gC.}hCX.O A-4v@ ù\=emH endstream endobj 902 0 obj << /Length 136 /Filter /FlateDecode >> stream x313T0P04U54R0 R M F0\.'O.pC.}BIQi*S!BA,???PP'W ,5 endstream endobj 903 0 obj << /Length 99 /Filter /FlateDecode >> stream x313T0P04F )\\@$lIr p{IO_T.}g E!'EA0XAՓ+ ; endstream endobj 904 0 obj << /Length 157 /Filter /FlateDecode >> stream x313T0P0U5W0T0PH1*26 (Bds<=\ %E\N \. ц \. @#HD؁:Q'@&> f0d82>3 df Dpzrr@: endstream endobj 905 0 obj << /Length 107 /Filter /FlateDecode >> stream x313T0P04F f )\\@ IrW04 s{*r;8+E]zb<]:\={-= endstream endobj 906 0 obj << /Length 155 /Filter /FlateDecode >> stream x313T0P04U54R06P06SH1*24 (Xs< M=\ %E\N \. ц \. A# ?0` @.WO@.8 endstream endobj 907 0 obj << /Length 110 /Filter /FlateDecode >> stream x313T0P0V04S01T06QH1*26 (Z@ds<͹=\ %E\N \. ц \.  \\\A endstream endobj 908 0 obj << /Length 145 /Filter /FlateDecode >> stream x313T0P04Q0P0T05WH1* !P"ɥr{Ź=}JJS ]  b<],j0a||=CC apzrr/ endstream endobj 909 0 obj << /Length 103 /Filter /FlateDecode >> stream x313T0P0W04S06W02TH1*2 (B$s<,=L=}JJS ]  b<]0 szrr$~ endstream endobj 910 0 obj << /Length 117 /Filter /FlateDecode >> stream x313T0PT02W06U05RH1*22 ()Lr.'~8PKLz*r;8+r(D*ry(01l;cNJ l r \+ endstream endobj 911 0 obj << /Length 168 /Filter /FlateDecode >> stream x313T0P0bCSCCB.cs I$r9yr+s{E=}JJS|hCX.Ov;: PNF01`u@Qf f2J~ 񀿁;'W Ǟs endstream endobj 912 0 obj << /Length 239 /Filter /FlateDecode >> stream xڍ1N0Dg"o|$Q6ZZHPQ *!p!eU8i=opZ-uC玝|H?Я\~4wJ3޻MÍ?ε/2"P<> ufA@5ã`cO4s1d1gʮɧ:eP~Kٜ-˺QvOh9X܅H$% RM Zlmb dr)}A!> stream xm=` .߁1D'㤎]ċ8p n #~$(}L> stream x}0K:#pO`i1NI4 Kd0FMj\ijx@½%\PPGL2P[2;|=7P~K<Ls 9y|9#l K#vӜ_[ZCN _CF,a8[NXTQ endstream endobj 915 0 obj << /Length 218 /Filter /FlateDecode >> stream xڝ1N@4QY AT (Ar 3AzWJ_kN|y9H/vI'Zun8-)\ؙBwoVWg)6r}Gݚ3J~ ZTMa.)- o̤/`tR27V֯ifhh`+-RN]dvg9 endstream endobj 916 0 obj << /Length 183 /Filter /FlateDecode >> stream x313T0P0bCSCCB.c I$r9yr+[p{E=}JJS|hCX.OD|?b0 AD}&> f0H0b!On%rv?s?>  `szrrǁG endstream endobj 917 0 obj << /Length 147 /Filter /FlateDecode >> stream x313T0P0b#SCCB.c HrW0r{*r;8+. ц \.    `|$lthvb)،6 Q .WO@.̌r endstream endobj 918 0 obj << /Length 145 /Filter /FlateDecode >> stream x313T0P0bCSCCB.c I$r9yr+[p{E=}JJS|hCX.OH" $`@CLmQD !( ,x endstream endobj 919 0 obj << /Length 227 /Filter /FlateDecode >> stream xڍ=N@\4PY AT(PR$ގk 7eUI"Q|{;5袥aC]8> stream x313T0P0b#SCCB.c HrW0r{*r;8+. ц \. ?c4 N%'W  endstream endobj 921 0 obj << /Length 108 /Filter /FlateDecode >> stream x313T0P0bc SCCB.crAɹ\N\ \@Q.}O_T.}g E!P E >Փ+ HX~ endstream endobj 922 0 obj << /Length 156 /Filter /FlateDecode >> stream x313T0P0U5T0҆ )\\&@A "ɥ`l¥U()*Mw pV0wQ6T0tQ``HX`'$@DD?`AH?` @OjhPՓ+ UX endstream endobj 923 0 obj << /Length 218 /Filter /FlateDecode >> stream xE=n@E.,MvNm M,#EPR%)SB9QPr.]lȢOLt&c&FRf1K~|U.k9s endstream endobj 924 0 obj << /Length 123 /Filter /FlateDecode >> stream x313T0P0bCSCCB.cs I$r9yr+s{E=}JJS|hCX.OLŘN|? ?*f endstream endobj 925 0 obj << /Length 177 /Filter /FlateDecode >> stream x313T0P0b#SCCB.c HrW0r{*r;8+. ц \.  B`W${1y 01h͇q|Fa  l?`!'W , endstream endobj 926 0 obj << /Length 194 /Filter /FlateDecode >> stream xU-@%&c 迨 P$u[GEev K1h8&nL؃-;CFXA_>pi ?!&+R"c(ɉ(N+ƵGSroW\"Ϡ+tIߣmśh5| dXB]/qs| endstream endobj 927 0 obj << /Length 170 /Filter /FlateDecode >> stream xŐ1 @ERxt)R-n!he!VB9EqW7seϨxAƘxң3U5ݮr 쀾"h `,T'uID x/H 9 Zpqol endstream endobj 928 0 obj << /Length 174 /Filter /FlateDecode >> stream x313T0P0bSCCB.cs I$r9yr+s{E=}JJS|hCX.O0"370`H؃@`?#^^Q`Cƃ-Y  f $700 F"b\\\wN endstream endobj 929 0 obj << /Length 209 /Filter /FlateDecode >> stream x1n0/ʀ! &HYj کC @9j1CNjKޠ{iˊs.y^,V\.x_ЉۜWH[KEԯ|9_do\g ƃHLd pLi'Ai ?NI i&tZ0^gȅX{cY701<5  endstream endobj 930 0 obj << /Length 197 /Filter /FlateDecode >> stream xڕС0jrf{::"#a e0XvtmCOh)T^ aLiOvG ֤FscT,r0ʖSiNfEN`Y9Q3pqNN3O0n ZJ4&}5ty+A -ؼ+ԀW2>z endstream endobj 931 0 obj << /Length 236 /Filter /FlateDecode >> stream xu1N@ E"a|$H" * DH$*\!G2HQwmT 娔DJsՠg?x#Um<>r\Iq+wn˜24wC0MLNLtA 9a=tC68yF̛aO2/a<&E>oxv endstream endobj 932 0 obj << /Length 124 /Filter /FlateDecode >> stream x313T0P0b#SCCB.c HrW0r{*r;8+. ц \. @†H0 z(QՓ+ +T endstream endobj 933 0 obj << /Length 167 /Filter /FlateDecode >> stream x1@G(LtYY +D ,ZZhq@IaGhf'_Ϭgɂ#}SqblF.b27+e=Z3bÏB&.ْ`9:Rs)U*H]J^w¤%HRQC/~*hGo8 endstream endobj 934 0 obj << /Length 189 /Filter /FlateDecode >> stream xe;@!$p,1q ,ZZh.F5\5o2s? q98^}G|9^0vV2#kgdfAYL{NELi iww?>, ʐ ] xBi LHʛ1VL0JRaVuZ-Vi endstream endobj 935 0 obj << /Length 197 /Filter /FlateDecode >> stream xڍϯ P#)>tœ &5m.b_CYN wzto,NvE69Wh .-rZeD/@sL@56Mo%n} :}v%$@FTiXz[V!zyM-+_X=Ey>J3CN.{K endstream endobj 936 0 obj << /Length 226 /Filter /FlateDecode >> stream xE1n@б\ M<'m JHqT)"*L(iRZt)GLᏱEW23ɢ}ɟ\YV>>xUs&Ւg9pzy^Jz-NS={kg`g?EJEAJ>.dt &JI0r熻qM 5.M_f[݆{GZ>_?WKq{ endstream endobj 937 0 obj << /Length 182 /Filter /FlateDecode >> stream xڥϱ @ Y| j;:9::(}{{3!HŔĔ'tIio _Q[z>^WnEWtL(>a]Q3-c'4a|` BAI=EzNGKC8e  p&ȕ5 l endstream endobj 938 0 obj << /Length 191 /Filter /FlateDecode >> stream xm= @ x Ղ?` A+ RK E[)S,;h%Xfh< }:ex\T:8^pVQ>EmqF;)C}FE$ sXBט^Hȃ@?|bezYETZ_q-`R!a~K<.Kj/\ endstream endobj 939 0 obj << /Length 187 /Filter /FlateDecode >> stream xڝ= @g"#Xraˀ!N;GYg!BR@[]/w%ܔ|q&?,Lƹ+x"ҡ@yRx -0遍~*?umֽr!0e] EӐ`%Ж*sz endstream endobj 940 0 obj << /Length 182 /Filter /FlateDecode >> stream xڍ1 @EIk9 n!he!Vjihh%GL2Φօ}g?ofǜlS>'t#k5?;2{Zd܆L]rBC\"iJzD=[5/jLAOQ~ߏ@B_Zh4J5Ϋ^RMuZ9uEJ endstream endobj 941 0 obj << /Length 193 /Filter /FlateDecode >> stream xڕα@ .<} L &`qRG;[pqᾤ 5)+H+9s<^&|XLפ*L,r0S⺡MNMC $z11wx!"><Zi&N?>cH RaH'c ˁ:ѴmO, YK endstream endobj 942 0 obj << /Length 201 /Filter /FlateDecode >> stream xmPE4K BBrmM>}}V́;ܹiԥS=T'u9&a+NFF⻥OK+ VZ[( f#2;܃J>PDCv@Z }•cC 7'* 4u.7mp b2rcZI_ endstream endobj 943 0 obj << /Length 154 /Filter /FlateDecode >> stream x313T0P0asSCCB.c1s<=\ %E\N @BA,@Az H?*;&p4Aka[~ `1.WO@.^ endstream endobj 944 0 obj << /Length 253 /Filter /FlateDecode >> stream x}J@#E`}!k.p` A+ RK E#U(y[,gǰzqꜟJz`;볟 Z.(wk~x|ws%{/xv4lnfxYDdItSn\#7@efd=`El6X4jB*`f}E_h0bj1SL̀,x>v*!*:MƢ:?-y%ۧF@-7> endstream endobj 945 0 obj << /Length 161 /Filter /FlateDecode >> stream x313T0P0bcSCCB.1s<L =\ %E\N @B4Pe,B @d ?  B~oAd $?HzI8'W z endstream endobj 946 0 obj << /Length 132 /Filter /FlateDecode >> stream x313T0P0bcKS#CB.cC I$r9yr+r{E=}JJS. @-\.  @x@@?C1;}pA|.WO@.O) endstream endobj 947 0 obj << /Length 169 /Filter /FlateDecode >> stream x͏= @_#d.͟ B Fp !VbnxK q\`eW񊉣~2c!GOj .mO1dXV|-M -X endstream endobj 948 0 obj << /Length 198 /Filter /FlateDecode >> stream xڝ;@%$p.H)L0VjiVW(x[_~0E_cƃ=2b4gA ΄Sp)-8lsQy endstream endobj 949 0 obj << /Length 115 /Filter /FlateDecode >> stream x313T0P0b ebUel䃹 \.'O.pc.}(BIQi*Sm`Pz<7,{\W endstream endobj 950 0 obj << /Length 171 /Filter /FlateDecode >> stream xڽ= @[&G\@7!Q1#X^,7[n8ȃW3r9Al&]'-\,cx܎` s0 n ==Cbq1 SeKvI'mr/)T8R`5zf endstream endobj 951 0 obj << /Length 155 /Filter /FlateDecode >> stream x313T0P0bcc3CB.1s<L =\ %E\N @QhX.O$$PD2`$ȃ@H&?:7 q.WO@.ll endstream endobj 952 0 obj << /Length 183 /Filter /FlateDecode >> stream x}=@XLvNBLH0XF[٣Q8ab^2}KJ)*%Kw4 +@@)juE]VQzB[_P :9o.A@9(dq%7@'a/=ߵG.^Tyh p A!\\[>P: endstream endobj 953 0 obj << /Length 200 /Filter /FlateDecode >> stream xڥ= @g fI"SZYZZ(ښͣ[.(wS|7q4HRYs_8 LWCNv?$#(%p:lHj&5pGٌs V,S*7;(&A]t, -GT@8=F> $_ȥF<5ޯ endstream endobj 954 0 obj << /Length 211 /Filter /FlateDecode >> stream xڭ= @ 4 وVVb&7J{ Lig Z 6_B޼q;QH1.#ܡ$ )ѯO-3 # ƒcM?n0O$!Wɾb|31P_6rilxz+=Տ>jO=]quBVŴ~[)D\|kse8'vG endstream endobj 955 0 obj << /Length 158 /Filter /FlateDecode >> stream xڭ1 @ПJuj!Fp A+ RKAEh9JAqc![̃I`4-ØԈmjw쎜{Vky\Y\/|9êe_Hx+5C8#$RC\B"xo<Iw endstream endobj 956 0 obj << /Length 185 /Filter /FlateDecode >> stream xM1 @4!s7q5@T0XErr,,2ԎgDM&rv=pr^ًYMyaoY!RrGB7 }KD#"eZSW!("PB Ca}96A=> stream x313T0P0bc 3CB.cS I$r9yr+r{E=}JJS ]  b<] @AH2`h AA~[@ Lx:B endstream endobj 958 0 obj << /Length 148 /Filter /FlateDecode >> stream x313T0P0bcc3CB.1s<L =\ %E\N @QhX.O` $0()D? d=H2cģd> endstream endobj 959 0 obj << /Length 186 /Filter /FlateDecode >> stream x5= 0W:oN`B`A'qRGE7^̭ ء4ؔ? ,&Q@>0[}pb*Q)QzܟvI>>yG:J^]S |-,ZHZX:^<r[C准qzb&gaQ$L endstream endobj 960 0 obj << /Length 174 /Filter /FlateDecode >> stream x313T0P0bcc3CB.1s<L =\ %E\N @QhX.O `?aC00~ @2?Dv`N2~+ߎ #ȏߏ`` ?G#g``?A6 H@RՓ+ ɝm endstream endobj 961 0 obj << /Length 202 /Filter /FlateDecode >> stream xE; PEoH!LUBBBN!۲t @!L@,a̻{ې lfOÄܒZrɌOp>ܘW!kJ/LnRQ;H(+p{h/ O.ok> 44W&F&R$}xY& endstream endobj 962 0 obj << /Length 237 /Filter /FlateDecode >> stream xEαj@ dz)CB=ҩCɔdnvj:t&=$%p!:d-"zX!ZnhyxDQd}LKႲ)ֳ[{vȭ+OPy5 @U-G[;z[*lB;v\ɼHer;SHR Z88 ~Ka{ endstream endobj 963 0 obj << /Length 176 /Filter /FlateDecode >> stream x}1 P S2Y<9*BV N⤎G(Ϥc|?!?'S3>gt#͔+^wr~ÏB.9#W!H"Px+"B I / >i`$f_$hj(D{{-ӎ~b endstream endobj 964 0 obj << /Length 203 /Filter /FlateDecode >> stream xڝ= @_L#8MLRL!he!Vjih'({!q-6߲`}t!'<8 91 ũ piNfqJf)c2ot=̜w{@^m W÷x: dTLdO_'X`*w]!WҢqz9KU" }}d endstream endobj 965 0 obj << /Length 141 /Filter /FlateDecode >> stream x313T0Pac S#CB.# I$r9yr+Yp{E=}JJS ]  b<] X큸7001;j?0FJ endstream endobj 966 0 obj << /Length 222 /Filter /FlateDecode >> stream xe1N1E*i| .-V Ab $(UAݣ(>B,?kWEwk.i;O%/$=iI^>$nF6x0ڄʬ ͎X⌾T~fGvlgOȠ<|HTGǂ+ˇD5WTL3*=2,<8h endstream endobj 967 0 obj << /Length 226 /Filter /FlateDecode >> stream xEнN0 J^ @ZHHCL @>ZlDZTe}9W|Qps}ů}PYkP|N#5[ Sj~??ScNzDDFM&4=:4WL hLVښQ5A1;,wKi sęǐ dw;-y"ͧ\ۼ>[z3Vc4 endstream endobj 968 0 obj << /Length 181 /Filter /FlateDecode >> stream xڕ=@!$p. b&ZY+h pJLh$%^5Y (xTHN)74 U[QcL uMĄB9ƛG3a(if M( /#`cV2OZ˿Z;5t endstream endobj 969 0 obj << /Length 207 /Filter /FlateDecode >> stream xڥ= @4{t&)!BBB,xxqFE惝}ov)ZRGk;Sʱڬ)Nюe6aܠOi(Zb>$\Cǹ.5Tº)7 P \)'ߘ'-,e$9ґ i `AY ֚ G9-c endstream endobj 970 0 obj << /Length 241 /Filter /FlateDecode >> stream xm1N0E"4 @TE"Th+)S ͓=3uE5w|pWs/ 5gFGn{n5j+UknS=6@! `dHp糢0g0p \ύF<'"DMbLz[Zj6]*7DE??(jALP5ˠGԡ(OY*G@BR栛 5pI endstream endobj 971 0 obj << /Length 183 /Filter /FlateDecode >> stream xڕͽ 0+- h NB`A'qRGE(}zWEq _~3#)';#I~C"cQ8|Q iT5t] '`010%p1 iBt*Rt 2;nB)4_T+~Ѭ.:\M endstream endobj 972 0 obj << /Length 213 /Filter /FlateDecode >> stream x}O @`qM>!zI 0XɧSW؈p w3s3Y:'sÄ1P{~s8Ӵ$4'tcot=w {* (D`D:y#jAԠBQSQ]9h@9׆mƠ3/"-PIoәn ժ?|R3{6nR}Zn endstream endobj 973 0 obj << /Length 245 /Filter /FlateDecode >> stream xm1N@ Ema|HBbE"Tj`&GkH 4أnv+4rVISJ{!Orݢ~9^ꖋknR*.PI^((`)3Sژ1+-:%8p'?, \%ᔀ^ÊH"4)MP9%7Hi/! GdL!n&{| JMc_u|_!r endstream endobj 978 0 obj << /Length 100 /Filter /FlateDecode >> stream x3337T0P04P02R05T0TH1*21PAsLr.'~9BIQi*S!B4РX.O e\=3 endstream endobj 985 0 obj << /Length1 1460 /Length2 6185 /Length3 0 /Length 7176 /Filter /FlateDecode >> stream xڍwT[5ҤXIP@{Ej! I ^+P(U#E;_P}[Y+yΞ=sf9 ;}}^95L@--50 @pNn`(000)Bpx P`aq8"0E PG!aX v Dr90p( ЂaN@p )iáŁ@WWW>pz0,  І8G0cQ8W8]!m`~w&@ C&k&9w?_(儆 H;-(kp9~( ԇbh G<?f% a)Sc`P4rEz#ml˰y"Ώ`j8xDED0g j< e=(4_n Pxb!.0(` XHa5:dW p@-uU=-?%mGO)7sdC4wUc¹"I1W3啖p |S MPpup7qBxy8 }@d=[k zlr3dV)a AvNnT K_:a@]Au 6;.JBO~J7' :ɁNǛi{=[yriĨᏖi%,^6u nj\tDvSv8HK-R~d|bϾdo 12leH]a1md9>CY^!d?{bmo XX| &e#;;?&3cL|;<,+BnmPj,~jrHQ@}ߎZ=~C`.co)r4nIň0ZZAm͵1[Fd+j =b| b\Q=AQXwю9,"~x7A(-I֮Lu7x&G.\j\W߇Fe(eI~P94e17P}否9\\[PM#D=Lš3UYlY}%ls ~pB{=5.47uGf]!KHæA *@X5ۦzQ#lvm'6sTN S)=]cEFe)OxZh% -3Tsx#AB_Yik9{Q\F)oÚ6(+Lnҹ}k[x|[w0g{N7ӵ72A }}3t l`4QA+9-1ZCq6ϵ׃͡p֙[L  { W̶?^cZ]"@FemaHK-jw 3~o wKJ'E>MGSwi׸kUM"+\h^^]TeKnMYᨨg鹲ؙHM+X6B*x=[3u ǝne7D_eC[Y1*)g8EqAAH Aطfö:d3 b#qB; ԍ}$41z,У:iQjj]1O{b +wZCU^{z'̰(G< `2gT..3z4Mks$2$eb=Cj){$~j!> 90STzW=QUpNZ':WT;Ov˫Bd^Dž!ӜeD)K/#$0ǔcj6ʗ&- {gTu8IxFZWPb1 =6i rzsOJ5WTN8x{tebznh+/k7.OH'^~ti;k+l#^Y a}a )ltꛓ:Lz9?ޤss^nz3vH^RpüWgLHd2d[r]' ^m|BN_$;Mwc@+3DX`c;4*j*z*df'#H<3[D#͓a!wc /ᭅ^6FR& }ZM[NN\rNH%-#|_VRSV+˪=2~SH uiiajtC̖\SF-aTJWq B_*ˆ?Au Qi*mK |ҥ]^ -öm_32zbгO-03dDL4|ݹ_2i)SNrumn@9&!0,x<`| c 0kGYE'=[ĹCڱESVwc [NӲ3rw??li!Ǧ#wU4%*lD(JI`*^DIΗ bVmۋ>7I[ѳ-T kϮh\.L.77ce $A&԰PV|Dd64Co{k.^</W>p< xiXbҜKavqV*Bq~ \JT*u݉k>dhe0bYD7X,[FOOlTlJU#fo f6#BAގ>C_ܯ"iQbq˱" N.j=/rDvu^P ʴS-/cl3MVbmj?9B*d˳ľւ7);oup<=Byi6YɛGz0K|3Z 1UƛIvA[r9,T̵?P_%ݝ+IBL{.Ŵ]l!Gvm~)о |bE61i@E~cE \9Ub悬X8k LV3blzգ.=C ^!x mB m/ZKj9 t̽1Ƽ2ZVhNෘgs2JV&L׌JT}48cgּܠ k(Kkm&g-(\ՉSz]>cobe}arK4?sfPZsZ–3SjHé~9摆e!bxy*yjD[m5f~6+,ordZK%O8xrGT㧛g[XblJ);~2+<.JDZǷ`|U+Bcʎag"*vQM)oůK\ٳ~-A8vsu՟V*wظgO2?HN?# ^/tW=w;XQPF5b}|v,c T&cFᮄΎAEڹTss6sn앤zB 1v՞}K矦/s 8t˔2b,ĽPq(FRX֯-(]3CkN./:q?ӠTU q85Afz⃍TKߪ.dsaVsN'Uos(56|*CX)m&$q+JJ8Tv5~R[:2Ŀ v7M/)DY(̇TJMcb6i3em0LP Wa48i'EdV}X4d59jxB0fll"nhV&OKI r0g{re=]n4e]c,Rgk@B/6..S+5 2Gd%[]2蔠4Rj;E=V?$]t2.g9KrVZ@ ؗ|r/}y$% $lOBwqC n[;<t",u%o]:Mj&DŽm`Tm"KzÒ=(y3\BUzW4}nWt2,LKZ0 v3(V6V2"tHC=2D!?`0\FKSYly"3,I*xg`ns7ťHFםa.}V|W)^PM*Zb>Ԅg A"e*<#f֤ɸ9 DJD}InC$e^R^US.C7.t8DB4lT־J5pD+o&wLP?@ LؔQ)=?}򑴻(f vwlaBJgAZ>]u%nX1 qcssB3jA#}Ni wP 8jۣ@?\Ըg8Yx܀3sAiaڦfGt?,YW~`"'Zf2!n+zZŗ:|OHSVnUo4lwCWY(cw5m;R3xy:){$4ije~19TcZ5N*۝02VEbpj@v.‹ Zn'=-5e^p6E86 )p31ga%wj5u@?4Jx'PGWN'=EQmt\gs@%)N͒@XB.}QFbV7v=r?qvq-;3M/9XރH0r1|~i]ڃZcV%3puOk(,-puEmOu ^ӈ,&>,4I ^ԅh͗m$V>Zzy'z3uPoh`TM>*%cFZj-߽)ZF*;%<]YD> 8>nտc?~lhs/1b1uÙ]nJǜp QDB]>n^lD&5Dgvײ;Vx؋8 {O[ oII{]pyY]bxŬ:lf5Z9j^ekU*w ѵ!!91_gCAŋ;XcYԽj=f? V1Wcbݫ A=@/BnPj clM޿-[e1 =qVCW]d_#8-)7OJnVfZ_~rTuB~: ]/93ѧztb񪲼ݢ)$ endstream endobj 987 0 obj << /Length1 1478 /Length2 6403 /Length3 0 /Length 7390 /Filter /FlateDecode >> stream xڍtT>H( R3tww30 /!ҭ04ҡtҠt|ck}ߚ~sγgVc~E'D GRe]# B&P &0 =8(#!`S0~8@  @bR q)  J@JTP'@ xs(#PW昿nGHRRW8@ :]09 #?Rp˸PR>>>`7OEE 7 0@L` #Q>`$`PGw ƚ:}wo>@J'g"(W0A.g( W@`OG0{0W`!!#~Rs˪p'e$Y  q\>#|6PON^pDS "7AD@0: Loe1 g H#{C($(? @'# q‰C1GB}V@@߿V6y9!0ꯠ!o))!|"@()2q"i ?eG&]- B5PRS, 5/엙1ݠ0?z0]!Vro& E _TB (Gj21@xB>+~Lkˆ-LJ#_&fry*sĄD`$Gi2f' af KA8 `H`LJi bQ#e c? uyy F_/ q$G8J? o WnW)Iv! 4 l?"͸5#cm]SocXˬ`֯E:jҢq8DN։吴Y+ySŪiƊ.VO]&a +c^z<9KBlu<YKlhoDkbϳ}s %wbWϲX'uh+n_. asxLq;kYf2!e߈@X55_6ūAśZxSZXZ(4g{8S ⻡f-ccwc?TpaS}oX~0XxAB2dL&3XHz-mt2cuo>'|kau۷)4$v}9xVϛ%| dD@cL'XdbuAHm/W4Se, }Z֦%W4SJ0Wb Z7y;k3 kDASKSԠߍn2h =}Egg5`a}aN9ﰜSbG$i0dkYm8{^X1x30Ƃ{ȟ޴mv?U=Jwx=+J_I'[*+i^qw_z %ub9Qղٍdj lٺ/{_CIa5C; Y /C/ޝ)C9=`ު!bDCB/N= 5;/.Wnվf~?oeD⵻A+Y&SdbdgRI/vjxr2vR{\$5P/j4V-vΈt~˷dX7>da+l/NWoηJo],kz|2JRZ=LY>kbSoaZ! civX0;iېp㱁xO(l.Rf-޳­ϑjXH3l"8D|(a$kB滔>s][l)?S|e3 }fm=,Ԅf?~VpdkViaN^[<(u| Y~crX1HZ{SĄ'jD ~6#oJ_$dzO7jbԞ=&[8)V][E?v>1 шȡF`~Q%=T4U&ܘa}RL4~T`ǘȯ09v.A>Ae{@ o2z.MXebjE[U_7lIB']7g/JxͲ#R{;9z=bqf:ATf4>|Dz\4(.UpuTQkJR꫐󇒚ߓ3p?_RNPzrG֖v{Z37[- 7v̐1qO)nhEk .]i`by3te:/E^˧c}::n? Vu2S]~~Uh+X[QՎ{I>pb1"-={CwRAncD^/m3AC1=]&==$t7^'=3Ƌai>;hSsSzv4D:%@ź1רصaKLCi߻OXYnopԢ >_d0!C}m7,fVۄ2OqDͷsդoqqQBc+ [54FțHm+LҮ][+d4.68שԸ&L3ck7 #WJ=Ē$R6z'8lM~}ueE>V]ok|iV`,ERuwT-1Mk# ^3rc$ihF& wM{V2q "~,}Q}-A´0̇lυ2ǨԢӃuѮ$2:$bmue@kUA:cUƔ1R!1m» {$BVj&/2g028nMӅ\B5? u+#bZʮY">?74Eax켌i#yG# mY%cQȓw,w.&_Vl; g+|ߜlP%/GR"K- e #9i/4 F?`[]dh0槟3/4^5/SDsut̞ѾS0o-g޶\1T+mRjYt;&Ui9]W '+wb;#{|UqPv_h6.~/V IRwu:4P4lתjs^&\?u?F,RnѕPKJ Hħ>ÑGj؀ϣ}_O*F!|=]/b:t9M9hN64c'˅i^qKGcJnhT [Q5fB<b]iIM3A9]쁱Â5c{,m_^s[D.7[*\xcܒPrDC3_U/q_j;v4?Ī7|<l佷X=p7m0e_}2)wb\;ǦZ+-iChg@fi/snNN0cl'2*_ wtGrc M.FRF83T7.Ney,Ay RpJR9l0Grԥ +Vv4I@opw:-e.ҝgρʥX{օX6&ǝCZUFe> stream xڍwT]6" ͍t )5C3 !H ) ~SZ߷澯\5LZ\26p+"r꺺 H'_v,&} C F[:;@nb<js*p$wv#o`fxEE9275N. Az+=" vFp8O(Ё nWˀgkXL=CnA[C܆l nꀮAV 9/7  ;aP` ujH/$'"x%. (hauA"P_=Js 093D`Owo?l0_mظ\B EC,?Bap@jo鯊=;VAַ?gWU]o?v:yɸ;vᷣoU@ݝ۫ "^-(akҜ0u\ n@܊ r;=^Rf 5f|B  {;62xapmp۞` wu/HQ"߈v$xFxBx~Uov;Ŀv_xA&F!! ge %ѸiD8jdJMf䮧5}*{$:]i9mBDOU3z^ MS@a<+nC1gvq7Oֆw)7kwj_bR<%oA-hu ziYu }_>AW4F%NƆ/ >,#V8˞Ie~J#@TuyC./Ass.-c~HPqY9[Uu5Q/ rzML+;TСK,pj{$4_( 5)@VK|س>Я\&ܥW}s)_y-#ҍMo/8=&&+I:lLaqq[1 ((>;V9nck(&T |q t3"C2~SO nk,aM/.$)E<хO[@5UD!ӖbRZ>{Z!5G);!RqeITyjʛ'fz, Ĵ 4tCP_Tf<6O<3.z Jn`"FKtZ gױoIܺeA^8[I=}v(#L]wW7G`[?MV6Hw BWfg@3Zp)흅Vi(ը;ܪ!=_v#Gqg>mg\lqk_4Ybl560Ms{v ĖyOXLSW$rȰ~'a3uXI.k{s+7C)ۢyQ0[ K/X*JzUx(|emyzhE 7aevN!U!^tY!,fwz-kzRsDxhJXk:ْ.L)B)>²ȁKܪ`*Ew %{мlK=eh!{m`XvT<ę=*źeuGƂڞ\eQMY-.#r||Kv=mj-2LV)z;(ue$1y*zɈ9$=e}?kxH[|DlӢ!;OaF} ~Xľ&byQlWO$~~$K5soݟAe!'45|*Ʈ27ߵ(O[9ԐieV>}pX=*qmٳ- t.GdT'I Uay_bzilJ^KP m/|zzUY>El4}ŜCXc'2<>AbtDYW%:;zGH`= zK 3Y{hU:)ywBЏ{fl?ȼg6m;e3H.HGYrߞL%~? T3BSG'A0~ka\ 0b\KP:4C7 a|^>ѪmVǽIF6絫yds&s5kG/.Qoܩq8gVO=]3(rn{ f+8{Z~kXja;Yw-O'Ù.x/ڲN.=eؗ0U'h͜%֋JR7H c3 ^<\FbxMC\s4x@4*`&]ۅC2_JQɈ$[YwNQXYBJ6z3 F'zMLoƪ򉏌,|X C zqkdG̤7ESf*- pBYE("ղwŤbkд- Iy6XCxTULYO]Yvj%8&oIυPT~v~1m.;5Hcb :[q_psڞlCeզĶYxi9V6 ͕.VC,bSٙ !)AY-E{R\HK}MR[.|ӣ\z9 ;ݦS&3ܭ#R%ivʜo^*~aЉ;̎,-1yI({`'W;K>k6no-;8(q~{Ҏ/)Xv̽}%~-D ރ,Y񤵨J1^,I3:0x<&MSEnS}PLT&C:/ Y>1.er^$b!sPp!mW`Oasb8EpWƛ*,Wzv}2~Ɂkk^ZNdzM]+ .tm9рbH0|@|I׋{`yR/ QEGkL9K#_f/Nw+]!tV Sg8D}zz1 DY{:rO%5qU,#cBF6}M=xKߗJ1D&Y>Yĩ1n1crrײ?ZN ΣT)u+`dFmcmVvF-ƀ_?Yyw􌳁 cO:Y^|ԶW'wk!3х?29Ǵ3Z_{L+A&sA1t1ѼzCyӺP2z}f{_Aw{/Cc5̻@ L }P jaKG{h-U*[(RuF9ھcD1sAZ~z.f`ķЎ(Ȭm$?s5vx^0+*Yж1g;(P︞;1Qo󭙛-/c"No`9h !{I:gșO{ܟś"ayF;K$n:SxIMȻ,n(Z1G;gHiѴoR+2S{GaV~e~v0ўku&3٤0 o!zfVnrg^LR'ΰK.2g?_P]w8" sy?iH'dm^v+v!-!7M-n^ɩ?ԯٿÂzs^Ƭ\ڸex|¼G0@2DX+pbъL6ij؎TSI޵WT@k|J02L 0SGfL 0R 0>1ͷՎ>>?[ hUuREy?O8]{6-w)m2m9[bI*b1: Hx8컭 ZGz1 0 \JН:p$BARÍk]_E5lgKK|z"( K -sK9}O4\w] 07gYsTb0o7d ~QoBfS:Bp0;4׊Zp44Ho8idzYi$W`u6c_s*Ts{:{0zoONo! ڙ3CєD sPFqNV8sEt^"J#9 1[W=UWJJ'\, 5Tzlp) 7n"3,LwDɸXgWelt%(5yGdOCʞ$YTC@YTafGaJwC9S>zTV>&PSEw_sUdeT]3{wux%8Yfbu.MY#"""*H^X''ϲ_QTZ^NZ{aQي-zwf/7BJz6۶[.߼ifEr0EYgTNةxȲ]u8\H'g^w7'ɬ}R};ȭ'?9CYΐ'ip^*V啭+7~"t2j~n$OOW3ᙫʐ&^}wkLs]~L4fRb+'Pf. La/Wik8sH/`M9b,Gx 'WB CZpk{jkaZun#0UH*36 endstream endobj 991 0 obj << /Length1 1414 /Length2 6457 /Length3 0 /Length 7423 /Filter /FlateDecode >> stream xڍwTS6";^[ @J@TA@HUzUHMz. ( ze4=]B"!1)!q)  J D /#D!(v%; stB_-ˁ $));A@pq^ 0B8 h?Jp8R 7(~ A&@0v !hov pu' AWih!6 $ r'n 8w@a W:[T ̇r@(׌\o ps(_)Ð}9\8_c=a ?k}4@J 1A_rGyAh'?``q ] e_?^Oם5+G,lg>?~1a@R\ .*g}Oj_^o{}pYKqM\</BgNWݑ8_'rb 뉾Z BR tt-6R@0_|\ap>l uM!ȵz %3aQ1a\ ] McN\"T\ ے@"A0%nD^+7M-{@0=pu m8P_j3EsLf9iJSh.K֟* xDdz{6cՒ9IKcEq?Q#uOX!{n@bgyӒ3txzٗ&Ժ 9ٴu#ʜm knEiipF٩bC4ẘΎdr0 J_M̾.34kQX'JqE'nL" -xLv˟Xl;sz"Sx`v"4e ,K2(iTĜjk8M?#D+KqU&SޥOOWD-)2L#BaɌ#A-cj,R`vڋceocS*PvW[._2(Gkj[?{2lT6 n]jDX6IV&=Fs…z q@On":u(mlS!'~mm6 .>鬯ZMI.յC|uAK[>~7bg*[ ~wV #=S2v:$ Ħ33?⦆9NYqLO 9̳q$r0T 6e8|pQ2t"h:ZMxVKIdu#6Wx=L[ld$p ,&s+9iWfᥧ3놗C8ŞÖ3BKHx+F­6-7ٹiʫ3u+}s-?|t՘Y06;>;"tv#nGuZElHk*p^&4lpwI,JQ Ň49w!jV<Օ^fߗ)@tRi(s[aCB_?Z7eMFǪiD-elLt&jek쨦k{8~G" [q9J lZ>soa6i %])VsnS<*^-I~ӝ(MQ<TzU}my4fbrQg&{h{Scϊ6E ~ʽY3gK d46Ҹn@yS˩F ͗?$owE|f,O]tt+)Y5lJżkmG29Aլ -}~$ehqJ(;դP:|˽ۆs'h 7sِ%g8cNEsJ'] F@^ϧuڱޛNymJMO=n koct7~G~PU^&!MO~O9<y"fKGEaa ِUT'¬;aψwp¬X´ +^/v\ߐ//_sAyi+.|5ss3~q{X%g^IjcǤ{!:7d8oǖЁ͒?Mؽɳ.wR?Q|tYFkUaSGU&zkx,[dtu3:+SnMѩthB\Y۴[^% T.8,R9{A$֝:9fx¤otH}̰m%P4Wv]X}J"qg.EԴ[.;vGu)| :J@@J9%=-bS{"Oy\Dv1/#aB6s)8 %>1HP5e|m̕RYs^wnC,C]bG--- ^4/UF?iHBY +d "hir }Vq?OԾϾ,syШfI!`)h`:Ĩj{z 6v(*ycz|/i,1^>jV9M:#EMdB5UQ:Y~W.EMl O="X&ӳy B7Ŵ|KF %m'bNԈ@-2Kede,iHעAuކCk}#.<,=PcO>U/mGfBz+;6?Bw\cdDM8Ct_]9 xɾc'@Ei,?J^!=&LjnPꑺ]cJ9::jb]'HXV X}Htn/ϵBEf1Rqf:q"MbEGC'o&S7#RoR%Z}X {4י$!02)* oiqyXS7LZ=7,A{>+ikH"-KK]=s-#j{c{垺;7kCc0Nxjb8'_o4 :o1>ѩB[%>=AUAXKLG-;q\³Ēs+qU\V1x4iJ=yE-;d ןɛwwX0q{;x.88w]3S秝7ώ B陦g^.}+YQv ~!N0a`UtE +K +{f7vl;dHuE{e v,8͵.5/K+ NY U$|ahI6ȅv"K^Ps0}*SV F'W,s}-GJe3%[SKmEq]ɕ(ghxKkuec+\}p޴*򔪸y4*sg{OW>]So8( 0s>U33~Cѐ/$ 5mi bԴU&Ҭ|:Lf|xx?=dL`{tXrP*AWME mD뀾ѷ#cSHd~-;X7QJd c_ˠi63QIYxB*rnpn[=цNq|v'D̂: H6},4׭ ;mIcs%br+n|L1Wrܧ.:JX"Vfu=T^%8-l\,ScR!)F{RWmd4B|:s 㗸Z, Ol1ܰwqbݖp(4 8J+DF_˟픓qsBLzlȃ 5\qu]9JW[dLhoK CLı\>EIq"u_oɾ[Sc#Ï\$*\6 %Bzht EflUػ 4pƾJ\"dV:f9OkEvķnM<5n3aՔbYgԖv~3h9nˀ*ŷT.&b?ӹ$<@%FMDz|'䫏 "|*Dy\YS.7m$;-f:P]n؊HpǴX{P3"o%.b}{[ҹDT$xx .PHuy}U}vu?hZ5 =Pޟ<9lqg_H|Cu<'6XgdtB–`X8G;fx@`-h+1Sa:J۠G荷R~}Mf!ij8Cy(嵈Ї\4˩>Ql`i(jPfS9zz-c(|!FcSa}pO氰(ܮF~VGi3mۤ\1{i ,a yo򉱸&|L7%Ղ kJ]ІuQ6Sg]zqe?g9'"3Q/mԵVoD'D-=!<3%#@? f=?+ٶ˨OXcW6^6cٺwHș)_4Iaj/#9x"NG_?ʤy{ƤCw%RO{OH3/IEOd"boYWF$S5 9Ⱥz[|'Ѩq{d ~~e6DST\SLΰЖ]V$0!@t|8fH&=VG#Wґb\ u6ruY ]{̡?ȪK?X,,,w7g$tGacȃ{:v>Oچ9{^&HtŲ'.$֜30=wrhui- XOApqxILB4LhB 5ߋ"xK/"ܟ[c'*;>L] |\)%w0C[@z~!#5+(3Anr&Q6>U<7bATZҖ{'RSN:֒fuDVj=8u#-qutۜNR0gcia2+&{8|^dҽ\(ۧ>Ƞ|#_"vB,KYM;.F 7iZ*=G}L)X?)3 H%Õcp킔V0,SUmk endstream endobj 993 0 obj << /Length1 1592 /Length2 7547 /Length3 0 /Length 8611 /Filter /FlateDecode >> stream xڍT}7N( 81`06`CA:[A@@ZRBJ:z^/7//?.!2`T4A6$h@*juO','" [.P0(ˤsq;8"q~|bb"r. w0 вA8\6 !|Upqs8^`#@{Jh۸* `^6  (ijWN_q/_6@ :@GY@~)@0 bcT @YN`@w+ C~ JP; O"p0/'{0Wvo8y,)W,/tP@Uɼn-|5Uߞ4 蠭r_'cG=LhF*gF<ʖG Fy;̣H~/9Lm);0L8$>~4)Wº:a{k4 56ӪcNRg-:zad!{wՄ?+ #4faVl y SAy]*Od f 5P2GO8Ӿ^R*E*M471~a}<8]OKYঽmyɐc|[ +ϯo5G?ĤvO[H?aN-oƟ$C* Őʦ6~#~͎Mg?_HnZn7j^U+ X"֫0D)}%Ƴo 埁r87n@d4 Tq=>}DVG}x^,z+TG0počF1T+Lp4,acұ rj.$.Kw; #Zlԓք)+L#;ADh|lTpDA.-%ş{XqzO8(s\@dٗ-ZTDn~kT Nӫݏ{3j>ѭbD"Y$S^`#\AO:ƨ.D$ȕTI//) 3>{'ԧ>Hͭ^ _/zP)-bBS_!m#WO J֊3o|8ә=dKNR>k>NmPיx!}H;o0dVo1Z>xp8bVQp.a̼jEI@v/K5,2XrY%^ Ϥi~GR-=WpOY Ϻ|u"d!czQH^ITX[x^I&{*~&"9=$Rt\<(ZOޝ >oϢp과Vk5z구N4J-FU#ZYGRv\\҅)=[)_ |kgSX{,c3s($-a'qm͒-p} )jx*yHCDvڵ%A IBO,uꬄr Atg7@QW/~x(GL;yU"Ѝ*ㅍсnlmih'HJ#pҝNgU)zD%Žw4$럤owoxщ9?!'oTMqV]8Q压[T-(00Gn3~mn6xn؎w~>ӷnE.5Oj⋎=>mΣUhjX<;mc1h7^Kb1ƚK놆,wnaP6XD`'TgJAfYۤ|@}s^օ1K9&B^4}vQKl~ fYux GGEtṢ'kTӒ!"ЯUAّ ;ڇ[ *J, (ƥroղnO[U)jӘ.[H]0TGjJX){"|y}'5{( rXU:pm~bTn`5 '*\FjNnT0>UH*O(/Br^Tc)K3<= e䥝 i5wnwK9f?m4vJVAa*4hm[6/far{D`[R_f$f) C,}lZY̩@۩'%-_̛ozr GzOB.tNq,>%~\HH oEt? i[t{`m(SNBFGa' }^zK]s,ICgb_=4 riNس)7a T:gZD]#P}cqLy"0JB]]k+˾-gzLٍBE&khMſwmItd,kڣ<'KfIv#k獺6 [bуٸwG9{ӆDY5GWNv,e7%p-=H~砤?!dg?apq=/u=#ۋ VJŽK*YNߩ_Ha0T$ƌA;s5cfe~58\#p [DYƨ%(z^Z?I$۳{駔L6T+dj5xuˑ{h!WCq o)YCخa.{2|z%<De׬ 22Sӗ Sܺ'D1n划{$z ]4}%$B\N"r_}ca'q3 6D $iOxpd]ZkV /}X3-Uw2W[+9ݟ)#&t4>{)\];Y @u:i&vՇY;y vV31];jHn򕉨 pZDځ Ś6W6js\GDluӬ?ski6և{27 ](l h4i>{z%;j/uqp./0zQR]c42cҬ $B"[ɚvlpp{Gjƕ~Pzl8x뗫f|)k~-^afT/>*ΟS˸`Ld.3)K Gaϟh:j7` YF+.Oۺ'9wj-VVQgY]bпE,hMپ.""psu,H㳉_Բlr&TD#31M$0%ߋ)5%I]Uɧ7,poYlK0,66=X !#Uɾbh׉裑s+4]]>=|V,@{Jh8.N@q\p42yB>N\{1$U襽R!x#k5K,3>`9V^U•Av8˝?V Y۞5Nkr_J0Bƍ:W R!O&4 OZȽ3}*PnYd dPJo {yth8eq BeP0vzR{K"xcEЎ!-;H9Haua7 ݊t:TsXd,K{wY xVXyďaa%R99>cӌ Bvr֬}~R>&?j|dݵB/XGVBv)[( ˮsS A,CdҟxSv~J6׬Z3PΣh>3/y񤵎 HDk]SYwû1eZed{@o_ eBzb_3цm\.Ͽ`oT% ]r>9a!k-e6Z q8ߩHEIBMT 6|z\isd?I$E#a# Q)6h䋞@Эg2LD U7 Zi|877F+'BjFp~xSN:Ɠ+s16kݠs0ݎXQPڊdP1ȭ tR^Jr][R0w۶|}[qIk/W!Izg窙4ϗb#NoinU] `_wE*VmҋOtJ^Ǧص)Ow I8Ouq_U8gxu=eދxm `gHz[7Us4.7KEÑV:wĵGEãU\!v]M?f2n_aQ1H3`$\i]H⤛O8; Y9ZZҟc Pz}1޷k8+ň՛lIIUOٜ4e9]}w(aFhV-}`$3{+N R;( n h3t L@բ) x8z /M'}5H3+8hJTosO>^:&Y~t dٜlr%!neukdfiѶnDEտJzu?@.HDlsyr擠RCIA9 %oHtNd򛈡*}TVLcT[l 5(Zb.XǭٶW":s9X?_sV&˒)kp6ؔZ,m ia14CtlYm\_D8コ}ܲHqBv 2 W|T#sw 2hs``2A`ګ~r[.hC0 ϴ+Y;|}ܼo\8uPIվXQZCY=|=بUgIRH"5+>EPrO(TssCO=J|pYF㩨mˊ=uz+nlMlsc#yw9b/j4QovX"jְ>BV6i9k>ȁ))y>_pWJ1Pxa=c2KecR 0Ǭrl}Em[Kt/[\THFZpu eblU#S\vO,@\oϱ$M'-(=2t_:lm7CUCFMI:n}0otD+ZR'+~jlm^.ɧ|bBye9-咘4L^URtla$Пv-fK!z?SE7қWt:>*3KNON7mFgm{6Vռ֒h"5D'kEe#x"*Xp ȉgGBYR}o V3{'ӫt<͸Mm/sa/?Aq +; 3;V_7b.o&~khk4֡&& ;hkૼ9 {umn(c d(L@^~$:y뛯&(L2Jff;~Wlܲ'T+a-#lƫiz-Ucc}CpAZDke,VKÌ2j#sק᭔qUsLSL~ ܝH3K(32[R2X(p>kX$Dƶ(I Qcn+gD2GvuR[ez&MV'ң"Ý'≏upJ3r=ey># Zu{jᤧES"vk[q|u7y> stream xڍt4\ڶK-D7z !E2D޻(QDF'HH({y}ku ~-D0o9c(C72e08DBB@ @@J0@KCQDJ'$- e mPp"aV`8@ :D;@+\h%@q`h[>EB!_%? q la 5 n0+(uc@#MX/OsBBr#1 {6k)vGp/ a`U=?0'4JsU/77mVCP8E+?ejuw?õ#^߬ap2 .Np ̍2( @Pw+[_ <75x9!7e@}`Л .PTF$$K No7b_#aS _ϿN7 OR**"^~Qnx ]0OanHM77ąs3%foy_y88s`G_(FпU 8| pRC!0_,-ސ*p+זH$؃xCa11:AY#7&'$51QB .7a7A# y+yߋ CgV2vՁg n['9^r{#\.+2> Oo-mp\.5Fuҳӛ1aPOpz)&z/͹7ZIye/RR\-#¡I&чX;u/0I#jOδ9F!y=#Ӷxz4P}Ȥnޜ7+pr36YT=7`.r,/Q=ПrU䀆#븱g3Vl$= be$eI*\X5z ,e!rҎBЫ"%TF?y4C1Ff|Hx}[Lq#z AV3||'sD-q me_;=@N[ Z% ,3%ouG!J֜(#ػ"dK16}ՅIٙa7 {b= 7K3ɓsOJ%~-2vL=jK_k1"_!T h?2q((mwo϶S\Ơ}J;rZ8ؿKne^ymsgWTAqר7?C|Ryn-kt3(6.IC&\p2a^ `:v3{msigJgRZylxd B# ;'I5 z3q:RB%I=b` K+ .,"Fվˎ,!N^#ϞS9ѻ2o4V D>*1>,a:KZ،Gr<2;5$~yLjWmB&_p|m}͎zꩭ#'1ǃh2oq1|v/@6J,,1P>/>$,81Pn9{adOC.:;i<{ư%q{_ :( "BNx(tޗh*v%(o^7*ڹ6y}&+aN+|sg,}XyN ~QduUֆ,D:]'CއLmhД5 6| L{U9_?̰妶\$~riH>6C9nIҲcE%RY}I(ۼ7`0#ayTbeQ" Qo`R⚅W xG Zq]@$xqi㈚l%yx'Be cRv{;bfj"/xZw h%!m2#y*+" DZA *׾L6C4NQRoa0t)k\t|sҼ  }C}},)[qL7^-]S;D{ZTm2w"Hy7jGc DwG] .3ͧjCDŽf6ﭼd9}"A|{Z&Lb}^x=p`X([%'<om't+R$G¡oU ˶씱ٳ|" ىՌqFo'5eۆ4]7*n('B*d?ajl=;l6Mh^IZ6u\)~![xYgsia{={]2^ܳNjSIe0/̧Köp>GI%9.wq { Si^t_#StMl%amD T#{UZ#WAF-E:C KYa'tx$I^|Yp.}0aF$;n*nz6b >۾Zv $V}0[?/Y^v^]޷W0"E`B~D&_oZ‘P.GPlJr擩3w~.hp \E4SU/O/J4cOvDD?|}ԹơU7C믯]O.}ikVc Kq|YYC J{s_~uMnq%DʥJj3݉C1SvSn V oR5)En2݊ K</|+9r+Y v]v&vwcљ4f4*zVaczSؠ,zT-5/"DNDDC& a\6 TY(뺙7LcWkA`Nmwo ӬmߦvqMe숍n2 A6Ij>q$\v?еL}Ec~ yZnʱ+v'pOep7Ӌ `/Hwt#; y?U$eMo*C= B^X7:h?-4^N2~pRMMJHrA1T&+ŴžuXjAѨa;\[1"vCw]2Z8rVj uq)dgs/lq(='q6vt(5[);-Ӳ <^ĻјQqIr2aqez{Q.AEpyŷ}<ܘo5 M\بM-B_2KbbKFefI֣-:a""Xl 6:vG^=>vŠJbxctyެpS[Ȁuy)Kvj{<]E=Xꇣo^ g%lەzMxvw<3s{Q/dP_0W3V5tur!sf=JnI7XۑC؜tuzW>umڽb>-D2Eo;\ T0Q֒%% "CBݏ=Ck'/,p~RRj,9e@ip%bTr;0(GS.TIOGJ*'ˌF`g-?(7zS0eQv;a u7WUOXA]}p1!Ş``U8NVie4Ԋ^JnfK=D\HĤ̷3ضhvr L'+7nM&TC'*+S '&E|Les3٨Y|*JX-U=^qfݲsִ!7ω^ ݴ5Sq [*VpJ?`H=I ~~196uw_-]cH;d!K֢.52MY}𬂎[Nt[x.f֒ vt؍['ICSC WB,T8ξI:흭S1]|bhݵ3\uqzku"[9E.Ač>4#RF;Hex?*AUDz"%OKz'&U6\ *|(eMKٸI)"x׉nb8K-a⭏E!+Gu)AC~4?>2IbkԢvu V}IڟGC7ҰwN- q[4s8{`&hOمpxFvDXfj3rl4GOlK2'"v-_3y; 2Og翁?&zwƹAT*zbY{@EFeC IA(ao v0y2ٜXcLDKN!>Q wudξR`&[> stream xڭT{ 'Gd! h`! 043/`mnꉀl2h oڄ(j3W&R{⏁L Z9af㊊n;ha8d큝9rJłFⶃsJ/7r[G]:htE`3waxHGD>-uY$}wD#Oz[.f^:9+_?͒NVQ_qElU噱:g7tޘlV5?"m *ƞח /ڜZU}WѵǷٕeHD/WfF uMbڦK w2^yUޱ| ͡nj$c7RSBt~7Whhmkn{=ɬkIY7Lt粠ֹ'c!v?)˖)v%upF7xK\ g|е3B;b2S!ҢdRĹ$*#˓s&}XayO/)R~d̴xW+l8αCq5+ BꄃdS^J%:ZCʈR(kmQWuHWׅL9JP8]=JU5̽sw!|V~]z.kHYGDՐ%盱"֒ =?b mh%QKl`#,o]-vJYVb솟|׎Q\Nct.˼*u%F 4GڽeK#N)ʔպu:ԒjSa}aHP+zOD XzNJg2`dC9~P\0 gc>6ʟ+(KbvN(ԫz2eFq8v_eN#?h\^g2[St(},W`(ݘ8P3ƪq2r''Dsnj'RNVM!*~KP35.Hl&ܨyf+6v7[kkՙf3g{sPV+M)gKiɥ~ޜ (5*~/^v2 jp /ne%ߡzv,<889\#;zVGTS ˴#ma1SY+xUm伝|04ƘxoW.)i4VDZtf,p| ee/y%z+%%C o'Z8f?qtr:*-f}yn 4C5卭sz/I *So&ͨ4!g(W`PF ,nfg[? = 0|h  D>WF|=HJeUWXh%z䩸}X,uI?v{Rz`끡悕~<"_3KPӓ[d]˛i'V)hck Gm#ψ]ӻڦ֚O$Ȑgz,- !zqϨ_PHk?[H(V9wSغ\޸%gHs]_c>~P0T)qYbԉP#Mם}1M&@Be&c1hJ}R^^ n5}r]NM/ֆJ^ endstream endobj 999 0 obj << /Length1 1144 /Length2 5549 /Length3 0 /Length 6305 /Filter /FlateDecode >> stream xuUu\ۺAi:D;$Dabf V))A$S@w}>?]~=cEG=H E ezw{4#`' PFPTu˛8v0(,#,%#] C w/! [JvAQh8 r4!ah)p?ap<22o(-- 0u3J mюc T!xQ(t " mPGeo$@ ۦ|97W( GKh#( T[o BąEE YwJ8:apqݾv _wD@ ؃- rskB@‚@_+ uA|׳sL-LtgRRJ %"RNU+& ۉU'u!]I8<䉰?n_jC G<6 v7rf?}h PۿAAAu,@(g qp[AH u9B`1vi4q;?._{'m 7ȁhz RrV%:$%}W Vk R*+-u1#TKzJ+ SQSaiD1n }'CO3r ŘKjC٧Gc^ىCA*؝@?9e~8X\]vځ)k"uDꫀ"v˾ʋ-z޷$'q@+lK+tҝnn̪SMFV C@XUr~_C~z|b:[jH`[eBva=Ck.\~n) iNA< )=d]$jCIn O@nkU;$zb́*y(}`˨8> <Mpy+coK1gQḾAϰI0 ֯+vJp?& bዊ镯ɺӓZVط>CNo@۔&j a$8P>!\*&uBoSG>77IDg#ڢ$TIF:*R%7xʿs]q j)Ƞ"CBF ,Y5iD̶uH7Ilo"%L/,}mS8_\42+MnT, Ֆ3CGG'$+|ѥe3S(YV@N~eQEhE u M̰VŴ+{aIRh:x,U(WcAsg]`Aiʅ/? d^(GOZbn_]Lb75nbd9-qWWcyE<5-gl˧82] vimX?Fdc| 1ƻ.i ejNR.N>ghQ4$SٯV*R6_Swee.~)z1S!H!TLk6K8]m$"F"ZcгFrի7ZHɶ TƬS:Kfr,hI~AP:pP-m(G"~E$UD~ZESѠeL↔W@c*Ia58&ճ8s٢??j$$ 7b߼?0Oc`@$"*Cp𘫵eP %&z,1MbCB>ZH?y+wTJKVfA6Գ)Old;*0(_V E5?n2Xx\4˵E;K69P>+܋ wuQSdkj*}GFR沌'_|ewpT4r?\f:ѷQ}gL!>$syeǟzY:2mW ^Z7D*EOڮ` &;x@yk?Re[v?!dیDY&l?ѼTXQihݙKcwqZvb5`mN#[13.OwS3"<F '52w0խ0NFbd/"]29JV}>YTi!aO!BeH\א$Q̮4Ø Ύ\cas`inF>J+'jSLm}D.e w|1܊&ՅtƆ֚ V*8q у%*W GwX7xΞaZ3ăcG~jz~2D=J EjKZvYѡe?wVY2kWL9‚6W) ~8ۢ1ۥyS;QkTCa%wxG_0c{F^~fEng‒.&ry,@5b1|Td܏!ñĬq! P&\Fq'>swPǒj*[bgP+ú1t: "Òc|0Hн>)n0g}LVeۣqjlM~aOC[.ٯvo~jݻ4\EPl%_@969J+&Ϛ/w?4Kix(>ִ%vј_}~`-]~kbA+F[tM;Zk)=_CE;񳏤mFBlj)$,US0M, GGX(ZP48|ker8Z[sq ǜV<WuR ܓt䖜1+A ='ox`y0%sn`+VɻY,| Qr̳&Lj^nyPAhXuD\oϵA냙UT !c^_$hvOtiސtzfXtJ4hDH^(I/T>"kݶ|vQdn(eLiiL@ߠ6EP7#Eh^L˫dUD_rF$c2y=|n/Coih+6=lJ,8QXFDKQ| *Luv5U5y.bD fD&6:iX%)uR܅d&}/<IeФ `phs.c Z?7,J!fK> Mļ 2= endstream endobj 1001 0 obj << /Length1 1630 /Length2 1222 /Length3 0 /Length 2041 /Filter /FlateDecode >> stream xڭT{\M.i"C?i|Jv{'.]H*ݓjoWֲ[> 1n9Qˈ\ E8ɥT:teD|{7.sp~?{}y/~B=q:o/@Q8!j? M8‹OД7C7*W@)E@$ -ͨY"V΃B >#GӼB AB5+X_HA#A2$B6@F;)M&iN<9R]*)d4` 8bY!xT]HF ! 9)K0<@Q} yT By8CNp QlDư6 %GP2,E␐ tC1!۴}AR&09HKPEh q%KA iT hE֟$,~9?1 fQd@Ҿ{zbh)R/`$1?DHTC ?C*VD{#K,D?"W$p,Bs"Ī 5~43))kq3XSx4$ДP9pP4F/lfEBG IdY4ڗuY0n-u_kO|zG^X!;5.Iٵ8wcnRz6}TY:*ܦ,{xۦ49Fmo7s7=:7x7LLf ڻmRSGNb&KwlUZZ7ޔZ$\\ˡ?Ւs+ubTtb*uȍ{=CGRfQi>8mAf֚Icׄ367h:Tն^3^qG,׭/sVٵӣN| ڐ{ş.MɦG@Cq8J|rI6?Z9>s6S`xUs}-V)_M-iqIv欆^[> stream xڬeT\%kpw]@c4N` ;<;wgUY4 34&@ 7suQ+@vn$/S0 i ,%H4_@@+k09##Z !7L9/n;=:Q [-v/*zr22Z2М\hpp0[} 79Xiͅ/ )#7 apDpNt!r6uDt0s_%_A#\.@G0ߪ 6SMi2wM.`Zfr tOL+Sg ;_L?$ߺ7utW6_QdAb[]sn>7D0%ajr$X"*Kߩ'-&BK)]1S "?'h_uf+>9ߑ;XF4` [[׿Zg;௮)93;iZm.WgUWPc?< T`MOǿg+J uFBAG%P_@yV2;= ?OFdhM,n26wuv+.߮<H+ s Ԍ4p-^ฤAo7;`cIfa5/5lOM0K{©۾n\;dE7*| 6^ƃ@V3Hy-}6택q5u?p$m Tn)18g Ǐt#C]װ=D14xI`Ow7^GWG}/,qMJU2XtYvjn핒 #%%\kgd`H b)`_b0#HӼlܬ򜕵Xuc8`&)UN* 3V#b~9?KZ F3[--B&jl[rş MP_6Jńgэ6.z,#\=}j艄7 \]N;Lֽd&XN2 I<_4xN.Ph|*%LRBQsoMn` 7ԃ׷ -JI=OI=!g ~UR.b&iz gtJg7UH2ڲ kw@yB;3)(6. 4:G4ڈM1l.k3 m!I(R-gluI+ _><86bC׸ʼ~]\Ofl͖% vdh}u`wˮaVǔQ⻆{ f VZ+y\Ū Y;;Nn/4NZ\r_i, Iy){ ZUBj_]'.َ%~_=9 4S Azo/Ћ o{]F[Mn' Sؠ?R% 2ne+ΈRbIH%*+8L= -0G.BJ*c,+3W~. OzK<|Q2#$,Z"kFTH J/! VqqBz!xYxf~ie¯*@,=.ɧݭνUoQm(mKfT{~hOG@k P5OSVB3AϠPH&OczxxRCq&~$GI8OM zu?Y "ȓ8F@z0rlB^IGƅ5r1sk}v폧W,ߍ+/=$An3gX [w#;3M٬U {\c&'Ób`!C:7Mxt`ܚ1 T] Jݢ;@  V=jX9ijy.֪cp, tOΝ蘠7lҺ|ZA<D04SdGbҟ"BVzUEJ?Wv\Fwo,@o,k#ƕ4faRPs)[M~^uU:?Si?bu2IirB\# KUlRݨǸ,J١N_z&Z~&[ vIl;1,28;M޵OS%;ܣc2wݺBwVZxd46kܜ) Y"iFvL7:m-_Qm?yOǼ/ n)l,.`qQnRYɯ 8w?FBkEOI Wy7 7}$N/)\:,Civ %eNʘچ5=ǟPfqrm٪ eeQ;%^I-1.5A}_}B7T[hX~*X (<6[@/m@ڶQaਲ਼Ɠ5Jƴ-ye:S( ќ _u/r]DҴgŗl%`cnR~tHߔ?E[L"kSƺMIH`lJ,0~ǦJt^ʣqşiUtQ XVuυ։Ʉ(硊GQH (H0 ߚv,GC_=6󥕖ҳPnƅoE{!>~".J)t?3ErdRWUU1-cαې[l+Dm;,E'k2췛]F?Y8A)%OHTx)i_ 54 hCa Yl5/|Սw6` r"`PBuE Fh`uiXe/sJl\G`E{"_ynFt2=fڮrt A^cͿ֐c vlS0մ,wSHjaw̌Ha=' 0+Xg@CCBW#B bם)[84Lb/C f(;EߨȱM$>ii'q}c, ԣ^2t_,2150*\o[am \ ](/8ʧ˲+u'ĹW~=bUk"&FM$CyAWҎZU rtΞh䃎--N;:_`K4Y"BVl4:>r##05`gNa aBa/!FdPv% 86?Lo OH~*t|9"Pt4uCGD<&6} a%w`&;VS|uXEZ6gY]?'}ccx%kdsYS*΋wkwKɔoy@hOX:K:5_ϑ5ő\s}Ҩ(vJ߽+duN@H8<0 }BsмxnBVϗ٧cm"wƝOZ=֢ T"C̈NRJC%O@5'6qo#3o5bU벧Td;aղltAN%G9oYiYX;YI_w#1w]{Rh n7O(bëNkCdF'MLՖŠM#֖$PC*?G2J THD> ~#DQbwvڐ[(OC`@:(Z[MY`"z8d251D\4q)laJ259d;i߆;J}D F2jhpQ&6K'cA;Ճ &Vc sD2OF-:ynEql7"nN5GU0%=IYەpӐ{-0/ s1sk8 &|YonS}-5E5ő*rC>ɹ˼%YY tQ 5|/ @ffnh>q2Flrkψ=ROwEJl& ": Ig#OjyIOjΏ0`䉈e}Q#p9I,뇪`ҖCKj|GljE-qA`~m">c0@k7ݰXL姗\5ԉџUWYNy2&˽bČ?wycdI/Oœ,]2ȱgyEbέIHYLg%,91?uH(=!1GSCEOkx#T[!6 V:~)U@Sa+JSdpQov+ryx #jgD^zȱO3،2Z#i$8`(llaY{]UM*ǥus#%FQ_ǏH o Cl`y/-_6꼲R+؇n޹JɋH7V}E՝G< q5xf29!8$]L Am e!{e'F*ڣ42 ,!+kl[3e4dW;üf'̉4\1xZ_zMNjPHB%ƑB*vn`_~{4r Q9pmZ ~jדLx 1'2&dN0f聧 {p{a~Q7i&2(u+H_#dR!@_V)?Kxů{M!mdz; fFu6v~tghF%4n}9f+ׅ+NUQ"z1I\qpFk芚AQsejG W#+[ωpb{JF3"@q[\Μkjs/d5ׄCmTssv}2U M#4!Ėv5³Mb+b= (3_jQO];+mYe7F7F1e˾6߬;_YIɠ#T!$5O'$q=Q%?  h`Lw.?0r^UfU.}ֶuxZ@32ʑ.oZg‡.uLJƣQle\Yw[Y}^Ͷg[UMG΄zW6D8ؑAŸ,Nc}N{7^QMׯd}7&2fZgl/Ȝe7IUw7|Fq8 q&g4?:o7` ͦjzP l[-H7׫As ̦m^nt ۄJ-pUmbY1SSHPFڌ~dJ|7r:d_Cy*n#x)_^@'ΦgnZHG%%*3Rѳ>/7co~L=iG m5~7k+E' )_~#WHV}һR1 ٸV]JMIaEZO,P˕+]~Ru& ~m 3b%*|U'a؇!X(/z^(6n=+aj=R>_ȠXz̵Kus[^"MJkd{Y~ :Z󟩨f#QRZ(|zi84ݩ لI|+ x"mx)w0eQ `~_3B_sFZCpI9 ?/M<'Ĭ+Koe7s)ku~!۰ϕr8e*zM-Svv*c30s>X#zNx ؄o05us^:Wqo>Hj86w(Xj\hrT5dDP=J+-;l 6c?:iOG.ǭhEC>u6RሡSq%P0l! nj qP>yg:\(.r=UK?ﮅXymNec):O $%dk[L]rdKƌpه=f]+bOhT< %l%w2"F_E6rTaJ8ZԒnfT j8HoGJ@Rmi+h(8Ui|7$ś BDg#`cXPۋLZrJm4v}usi|x5aN2O}0fys )_*g`?Q1yhC8#u2R &%:+YD A2'\mgoF]RCy^X H^凰?_Vr{nq[fҊ;9'UB QR'ЪZFͨRL I}JF} +yGQMSv8ߣ5Q4sL/W.¿egj%fYī"?YI"b(/I5h3!3u/1 l5F߈1ZU YK_PX3 1Jm6pH<܌"ɪ a c$,ۊUWANe Tps?[@rXM3ry8[I%dN({uVj9Qb-z l''e2*/OrNh<٫K\q&r7~ٵ1 uVTƖ(!{J5&S3دo9O9NT^ׯZ#:\k"*pĀJVÊLhɽ)pP-Td(!YQÇA 0*znXֱUʋ4ѭUߍ]N/Ha=;ÔHoݤי\#a3x_ish>iJ>OMZ[; !cD?[qӉt:'P%ű*9-%boxi3¥׾Syqַ@Oj^4dP SWINxQkONalV# ^wU>=sdԷt"x*̄_RW_-ƱJj 2mʏ?E-thP`wnѻ)W²ĬEXB77?6+HKv5)!ib`7| .3;ԃ؏<\텒z;O腤B\UVAeI<υ'sp +2)%Ly nt9,;/$.chb&COefzt^.F |):BiL Q>g;oϪk5W7!9%jE٘;kp[E[!Zw2P͓ !q"4?&zo \gcOW59%n5{g]F<thm"B A+8kQO("~1 ؅{ al =,TAA{߄l+Z?g.ѴlnÁ E ,nH:fԫN*_1jddnT.q~ (-DF۽A8Âܜ=cTE]N?(qƾ%5 /qr#.}N*,){l@ W%X0nتjM&pPެNމպ;qx1i\ϺuHY"np΀MƈQZ{(qE *kUhJL$a1 O @"!.BU+۞` =9ОaJ7q)?&<& T_P1^2 Lx N'f?;n*+:s#|U.tA'A>ˡB8or ™OyQ#!.u}@ *=Vk7?Yx|=eBFP;K72pюB4+M"~{(DUW(# feC+0YRK1naQg h&<Ջr~UaD&|4SY /% & ̸, S[nI_A8f1썶5)eQ7mkHq%DgyU8W52/)5|vNn,"&IfpHiKy[`F:\/ =<tbOzNo_MC>RHbquJ*/v? 6+>K'#O˼$LA@0L-M5HTe7lLtMx{W+Nl}e&!m;q JQ.R:jI@ ⒩r},K`iO.7ju3Mm0QȒ }_jEeKX6?*Uڪbt'=bzO'sNoe~^Grgӱ+ _-yjDPv*S]RD&Ƣ,hz3IxJ ˱0KgE{dcc泷˒Ѽ1jh_G{{=ZK=]?ƶY>y]J0D ҝUd_l}t9OuC2z%e;] /)9ts㣂+odU~J5v[HCu6͉VGz JjPƻ"xN$r (&ޕJS}*s\~e0 Җ0i ,Y=}}o{_'V;6iWcY Բ/h *>Ʋ ¶gm4pճqʢ~0i|6y}wU? un'^_cvjZx(Y.Ll+g bZW<~,[>Ȁ6.Z)BaWN3);\ByA[iPDNC,s+jcʚDʖXF u6%SݜB_ 5]=>QX85Bj |"撚!>&@ѱл]8@w!O =nBlJ:FϱRFMZ0?(1BǍ3] IM'\1TP"'~ #+n< !COV{%80zMwb дkIc@uPS|uaÙq@? "Sĕ6#yk޳rN6/Z:WX47?EK%Y>BuʽFGv2W(If.y--EUC"kV }1>qD1M&Ch^kMK y:/ -($BGX.ULk={X}bIuV.ѓՕiLT{LA bTeAb G+]]zOGWyLRɋkwv)7,S e[cILN`[s" 79,lS[GJ/x2} 7%yI(?K-%:ΊT?9*9u}j7lSCd;!|wLԞ8N"US 5Gg"Vʎj8^D 澨QKq9ħkl@ k 7 ش ʖݷv qw6qjQ\6 o7̧嗎٪!/J=lh0r&T|jT ߚ} Q'/\CATZH1C}KRXuzc5+;3{(7!8nQdD(|L僜SE~s왷J~!Fj'qN@^ ሧ"11PvlLq"&t'do7!Ox ?USYnNcAB |o"]]l"DžR,R2:Mx@ԔF5?^"*ڿ$E|XћcLt ݽMp)_V.k%3q`̈8* .i:J@-Y&Ǔ^ǎFo~eslJڳ!\7U7n+Nhʠw gq g0(㇖uMsE 9f߫hCNF˲|-h.[II9I-AUc}/˻]UA|@ؠ%L CO0Gy4lWi;eؠ`kk V+tI4N* q%h5HMuպM*&eM"[ر0}#iеRs$]~.kP#Y0]yfLa+|H3ׂiy'jFs nS LAQH`EU vfnoa5LIkŬ@uZ|Pq4=NxM.[InyIQobSy+wIA(y꜎8hp@{;EY{>,q.]j@ MzX1E9gi,f蟪Y< /~-Aq=|GjF}$@˪uI5rɇH"4WoiH/mv9 d1KM.J2#&ܴ&#3-D`*wvHaBP4Hh2ep!l2s/r1uDT.*#x7-әZq P ol@䤁B>g^d:VV%+#"b`:`R+iMtG/ĞAY[ A͇Kr6 2w4Fbރgu`xf c)`:t:qZĚ)EcTLR= H@}'IM2 jϸ4-#.s+~Kyw᥉<<1'FKfd0j ~mkU"E4ג2¥,ֳ3lاh?ۘ NɌ^^wӶZq6*.P+w>F{fPt:FMF6 \W,z\@n>Q,u*'|ۢrA/"}LL}=/y|it~%S<MX%#:k9'-D=*ꭨ4E۽@*#!:Xp9rHr+dJڝ063:" \42'I !AbR+|2O Ɵ݆\!BVdC Wg^BdE)ͅʀQ\=]`ڛI}2`LIMJJ |49C9u`ж<{ <-oX/*sO8pEmts`u$SnEu= endstream endobj 1005 0 obj << /Length1 1630 /Length2 18209 /Length3 0 /Length 19051 /Filter /FlateDecode >> stream xڬsto&b۶mb۶m6;IΙ3|3̜?j޸6}ZO"'VR6u06pwgf`(X8)8pѫYÈVb@W3)@`#:8z9[YXU4iiS ?4=],l]B_;\-VfQE%miI:@h Pr32YٻQ>LM)ͅ/ pq43fibhlg`pڻ큫_ `J..&VQ$%.V󿖦&n/_ZW XfS+G[f@p6:ښOwNR=_9Xٚ31i7=?"mo`f?tfj?3C7 QoH }$7PB oWKz+{.=Y4@_5L-ab`ET`۳M͜mr虙N27_3j+o G5' @M_@y:[yt?OFQuڛ)Gm-U_sofif`jڈU0:-c|4̱E8ޡ? 3r!ukǡ L[t"|?RbmNYg>WKr:LU ߡfzXaI݋M20|k,sFrH9<16:9xGK OCe|b RۡYFDƜuJh% Ih8A2">4YhRtVMƠyOMwQk̊d&i)'RNxJF ,'[ RPcDuPYA! HZPSޙ(8}Gu8Y#J[.Xv+HOڅuHh̶^_䬯8RvD<wwi}F?ZeaZF.@*ea t>FZ[tcNjrEs9Ry rWlE铈6H#d&@ -lOe`=:1غEv` kr?E4Rk< c(,'a%\uhIҞ/slrܚuLO,57'LES)Ы&WYf(<`&G+K_'iJZ5 \&'Vnb^i䢁P* hBC(|#Af5U6 ?P3-TlxLV/{;dgu1dۏMش8W.0}/  AN(ʅu;=*X YREZ4bv85e& ؁]\8ڑ-([EP@ZH*pl%O^/ 偋ADlB6qY1{z4ρgMJ:3'oVk«YNOPjV ͭ?~r`Qts8k1s)@N,&{rF?+ԁÐؤJ[8C8'y0NR*O,9d?>(v(or)*"|i<(&y*.>Sn`ByH\DC")i,#A>@br2߱,2bC%zht\DA=@#`SN+ IIH#yTd#wWeT|7WBm[l^d;(].k9㥬 FY<H$O~ڨS`ƌF9zhKBҾ0yx18UPحٛQ`ZXBuIziilh8AԺUʸẁtB TlDO4dY\L5$aZQ%;wA3[A]ًdY{+g6( JK)bv6&u,ؙ) ZcG0bf伡S5 Ff9 B[%W=8 Z'\ Is˖sLUx^m?0asObށU-bT~Cf{2L/F/g_"uJ`5=-t M^.un=|} J _~[#{=p}Qy=mPdn}°٦~#$}:x7GR|)YwX.=0 |&)qX9be REt# ug>zpwRIJdM^hd,*zrgϳ'l)`&Sf؄^2L#Ar;ξwPY{@J3zAU?Ҿi;Js'%HR&'Rt,Sl<t8\#B&2dݨO*7רO-FV-Ok ܷ! `"<. kϡθI'\Zm]1GBYܑB._+J[g]^t KK5i'ȃ^[&㩒HQ7':ViD![7A*GUʰ{6ʶ[k =__Dʇ)bYVϿ1ko SWG9u\D|7Wc'lbr;.mw b-Nik}Tj8!w6,% u`Y㮊˶C ;?>5#/ZkӃo+ǓM,hR8@(AhV-h.5 1s VQY=2 Dctyg #A[c+w8@ר E*j Qd$Ee5| CHH{}bچ,韮74nsdű7Ih9g=%'ڀT%d\GR݆uδ#\#o'Oc wûF^sfN%dfm=ٿ Wʴ^ōo"Cl[3rJ`A1 *gdi8q'ߤTwCTO֨f⪟6xcˍTzA7?L3]oS-}%|e=(ri x~~0fr}hOF{ӹ|=[]7R~y/}(Hs鹇'P!RIeGcZt 9d % m09L+~"?8/ib|:MqGBÀ8#S:bkR`^K,4$]f?+6IZ5@SlLw[bQ=|mH eҢ65.x_y{R+<`É_%/4'V*Mqfr^K8zR:Ӷa2 SdVbr5kFՆ&iO~ƥk&7Hՙ9H4(* +Ex69CбeW&W}/Nj~>n擺+wbɃ0]Cpgl |1j+3@Cq79=i@!i Bw&ӫb|Z8̺RCԔ<~m ̟-n*h9R{ gx/3R S:*>E]3" {ee$L}<3,K+h*xV]H?8 c{Fy*otR LDhz~cBh];L/q4J5|Uj:=O5l]u% Rl"C+/hP5q;-}qMBü?.p..=&r:x yM?:`_,9 ݜ4L@ އXJ㓮zΈp>IE 4BLKS?^rAq:ogǮrznpG+\r&#"I M(aՕ0hGP}qPڢٽ4Q:x#(W1''5- zQpoc.~byGpd~/M|ωB'b뻊Pk,<0~ gB\Z&&;o?Jt^'McZ` ec[sG̓2m]¾+D^|⮳I߾3AM{m0Iz:, j(w7b|0gp%w]Čo}΂^D CҘuoh\CxEV5SmX%5n*X{HQnl@| `6*_TAO٩ZVQ.ZqµF9fO#v=Z/|@/J䫆.Ox^5[Ǭ%w92h"J0%Kl~9ng4߻}AZXjN#"AvTxXiT+فuebmMJӈfNcP6=_Wmɾ1Gåş#>Lk#Rܟ>άn703cHtXҨ1 ;5Z? Bp0gtRbD5RmYɧt+l^BR+{w0|a<W JsntiR)9d|s̙Jm뾓^H[Dȉ2`C z1Tջu"~429pH 8ة hޮiE;u wt%\B@I]7^$(THRJ5YW@ _3m~,~ăcJw[yR.\&^iu}Sodw*,f{Tx1üNʗ5N *\L\R4fP6-㒌 LJ0nMbMa̧\_/LyUTWvL ;UVdur,Mے/Na{6ޜZ9a8B/:U^~oF/F~*.&_+0gkk!a\aʫXޒΦ0 ~TrxQNj22^ARۇMMZ Ne4Dfbj,ZGUnyAĠ m B-]PTFz>$)7t!w!h_=E-6\*> ǿ^gedS*_^:P # |f5)F.W*"92fpEUܞ= Вs¸K f1n18myBRPHs?$GrEy7å YW"l>0W nh|5*-[)#d~gijak]=-"H`vM\1chHH'N`2 _҄hKɷ.sEVt[tlrUɖ59u/ddߟ 9QH9 +zYnb{[8n@oRV#) S)TV:#Z}II(C;F᢮buؒD|޴BRfVO趄0c 7S*|Lm@W:M*-X xUt1NrД˭IF[5)ĔI5 Y'?|9y|~͗\Qwʠ4'CiܡUgM1ml-3\˯ɢe GL*b20?"_7wg5Q6gTmiZճ3>bio)4d:ZNHnx%?+|!gjh'mGS>#a4hϚ_E.88hS٣"WpQCǪWB.d߼.qXNk66ag1݌vuKt7ӤplX(K>0z cKf'*$,mO%\([hܿ6)}b^c{D1kPW.N/h~}"$5~(@y[//#9WE=+'`ŌR".n*Pi8Żrt[Y{CS__e'5+eyg(2cxiFW_E^A7^@g )'Kf79AØl@g͓Z :RENUuFzM+&,v~7pe@"86>_E q誌n8+D:#Hwo懜x#DRC x\z 娵KC:,H[L&Y%N]LRD^(t2,?>)9 Lq($J%YȞY[VAd wߋl4O^;X:κ4p/&t7G6uSVxEVC}Sa/cS3B#fZԕܦB.Eo {>x!4HED.(9129{tn X"w@KDzf'U]vrU,#4 d֡uIadyWD89θ}HXP\?"rT][7-sBUXE3Ze@sQx_0|7z GdMe޼kN jnX󇇺S2~CŦnᤦC,| GI +viS8Xm *_USm}l.iV0 ~ Ka]-"~C͏5+|o_kx?bFnSX#خyÃ.TFxm5  ӹ_P Ռr@ّ4#-!mi bRDf+%N+oH/~,[5ɹ+:"n=c 3Epv)LRt'+d>Ux!W^mF4".iڸX:SUwu i'L^ܔ8I#YTBh sUIOtEnXiRZoe$L7ZΚ[-f9kAeEw. Z#(,ph4x)@~;Γ9/"^?CbqgG)\N17,$g5nUqt+*tΌHBlVy(f=L=_ &=m6>IzMѽ a\Y,eS0lzn*2|> /ȶpяeS>uRAݏ՗Yw&qH1e/hV'\v$N3AF&fMHQ0ػJ0)tDe59i?߷\$<@t͌,'[fɝ 蛉-2e7SQ}y%ӃԆKOE6 ;XnC"X.}(@)&ъ?1}(@WL0}-K'FC@]jk}#=2gg틻)Bҋ)>U0U`h Qp&X{nL0*1 펁t15בCUN@*I;pH9E,f<<*S+|^*xCcݢ zj(m {rۊBvqx$%Z}ܰ1X$٧FCp@B(8 R({RI,fI i3V tBU+-A؅!f0uı:zo{GΔ6,nv~:i뤷}5JCf1R?3gPn 6kX6C*jlHȒ=_z\j P=CY~B &JGkCM;k&1!\m3Yq?'7[M!%يbZDFЕէ`hm )olO=A烐>r;U>{Cp.-3x)TFkn\z<8KI!m2WE?ϭܧpf#ofA^;m\071_%UYVpeI&o< P>,0j] u^gqTt@bFC@,fO [W|3K!윐ٗ%fh7'N!)?kR2y٭*H-w`CYf}HiKW:yg{GiWK]0;6="B%jEb9p}i؃Ao4h(Th9fɭU6*'+YL5L0Adrraq3{X:Q7H_,ʬn5qqoBPi se+ ED>l}la63 vHe*GwR27617(Wyշ5E S̵rXS|y$uIUו *R>9KtN 8F]3,j'.VR}; !M`yN]LfZPM6 ' S`Os!-{&VcLV;Jg]a?}o'nyR,;R*lDIhL;E+a9~YioXTvZ@}V'~!tH+ڶkAurÀ=2(e$MY %7NÐ!A9"Kpw+el^Zu7V*'H(eԎC?yN~]mPc-snجt+\Ss8%^%6P.)g2z1n< E?i1 ' cq@c8'B`aa:@N._36e` ""x jϷ1ݯqEA鑷OD?zĥGw񜃅oi?QjH}R 7iMFFL31.Ɩh+.gco"`3,߂xnD\K 'N2ֿL) w,V0~kr5S 8aطVLHq%B8/m0? l"3-VFZPj":`P$r`vQ* <~T0qs{EOoӐr{ e(eQrЊ^,B0F:RmCaW* =*4u7Z2bU; *J4_K=UNcٲ$=ŘpбY>燯sO5 0"p|oI.jҍSKOۓNƂȲh]A>Vڽ閐^V 72RBaD"a]F)by|]>bX|LVQi 6UzqlH9FN1z 3 g>&r>u)1; 7lʚ }钄3QFӧk-y5:n/SGf}R?v @֌ j^m$iG cX?b`w5}p%aCQFjdT4CkwgE`…k_Q5P +#jp9LАWX#vl KOؤPaYgufk/ɟW宣>}';?lx}F8u ҳKTCH;rcA=Q#v+gy_ [ /.+BY8!nh=(>K8BS` osN.jsYfwH'F0*%^@PU5׌ǝF)̏ɼh^*'/)4 8bSXlUalT\gt fދH 4 WjD˙bx%0m&~sZOJɇGKo7|/M'.^4.CNGڴdtlдx]v?ݍ;]m@Sw,^ 7OFuo3QYsq XtRQHW6=<#j!5&3jjÃ7_lj+ܮ t>R$c*R|+Pmbfۨ^h=SsPg ;T_RS A>f +` GB:*$8^jĉyډј\xmw*PXI?DwtKN`c0Peqn_}D0dxW. y8@4}wH[6UMp/܏1ۆm: |@U>P{tn$RT\,3RՒ-ȶ71gU~6*M&\dEeJ0dag$g&@ 8N|a4K,%t 4G-]bSԚǭK}N fg)dQEQv8JMV>B tLzS\t͑ $;מ2_YXJ!}'8E,j)[67L</fxsԂ* 4Tc>E<+aG[jE(!&,rb[bضN]P1h&P $~QXCO!HJH1tƼ@-Ap4a %cWME;x;aѶƄyvin9>VPVR99tAV"wfK]b;~i|CNU Hn8$~]a6rX2΅/AP Ɓsv`nai1KAӇ Bu1zl.:*`/35NږMhWZo4?/vAsWΊ{_9m+Moqs(ߋIkB ȁ45 Vl7[/*g7$*u\(qBdn8Qw~eP@e8uCp+o8}SuY:RΤ0M*wVWKBFwm,}!3lj;W &\4"F&s89d б\8gUuߋ6G]gDvsgS H]=u_]s}Z)z"CB t} g\CMQVgqEGv<‚\uq+R3YɊ[6Z,g"T`Õ#|vlMtѴ c&hp|7yRZ4!\J(%A,%&~C-`2a_u s5&vEsy8:!mXE}zbe#%2SW/=e-'Jװz<%b ˡV.ȸ(^iL?:GpʚTc?~܄.qquYDPӐѸM|mo?( : 7>0 z"*]7^eqb=)94c3snwLGP>~4{"Sn1rV@=NO'k^tyЯ=%;e0<49=Um͝q4UXa5 Pr~=Zr*(8 &ڵ,1Џѝ {o唞Ƿ)C΄R7ƣB{޶ ǎAb?g`W-_ ?Y m|60{7UZɆsLxa:q0uz!v1*e|,Do9ȤRsBñqG(0Z88ɫi;ΐt/@L"e2$$5G@D+Hl<1pI}(`âZO}=ȠV_6F0`I[lpX CB(OU+.{KT\쁛+`bVRz2 O(^ $oVDg~p(F{,I=v h^'bR"8\&ۅ@Aq /}_EkVBwGo!c*" .0fMod4^uweDά{H`>r06H@iptM/C 6s'BxuLylX2.NtAtu]zvS:?Ȯ@-/=.=cӅAkx 6+u{kQ,j $]m7'q9K?e~pTe[YSq ^c@<|㡢a~<+"8Av}ﳋ &߉[e нY)(RJM[ʫ\VZJ. GsKl oݠ,Wˑb}MStyp슱QA]{ҁiɼoΣ)lwO0a/&?e$qV' fhg8tt xJꀥa9h18oցXQLR K-D#{H^ tV5vIN?$v;f9ݣS۰oY2Ȩ\AP_)Lo%u0Ez)QuBGJWyD,i"r;fIy`thIG 樿ˠm|{ƲPEA=L^Jv3m 4qqYӓ*4Klv򺝵P /{Dfj(]wy(]>&:L>^Ezk.UblIG69ФWr\*)8AqVIl}69+Q&)hW\w^TUIT$08UR;"emW;Ԝ~(^ `O֮3(.5̿cc٨, >70b,W)/\Xv}JuَC\snVzA% (]N%UC(sXY -q3+6DO^7J~ޗۗ(;,~CB\}\+߬䦡|VxWl } I4Y;uV(62 $i J|zl몱S0׿@|e&< b?XYǁWDljNwhu@ 5 ))ܖZv%bZ afb\bRi0O~H[Ȥi@Íiӻpv38EFwNQcb'E=!"iZ͏\olkxr^  rBCO IU٭\Ehݻ} $ s2c2+2Ñc:k)sm"/*oF=τ.)oFMe=-w[e_ΊA#6l3״&ӯɡ%FYU{tE>EIɺ)ЉvHbM?큘K9x Gm!)?2ZʳR\QsWٮcQo‰Ya,j"K:[1HITun_;tv_eJ앆W_N3O#\5 tT"?_pD7=22ik(7ŵl/$оra8ឋg܂xM>T$ 7D*q?հMM&iwJNϘ:˚…0$&2PMqfy Q?T9/iQ I.֩$ס2|&rb)٬0d'},qzYA?Pu?9Ycvn.yRJ\12FJGl`wɹ)u6InɹN>i ؘpoi,%"nNC sgV2Q` ~_䝥[ {X?lRPSj|gYqg~,*Isd}of4J2!7/'wwOA؅LLϴ~\}1_+ޏ g#messXW鎭!+9 +2{qk5r=6(0@H^sH:U μO2A$S_pJ5X稄K D)xQ (G5p!#3:D i)*+p7,9sG"Y\Ul gD>5*WX1UH9F;B%E{)Q/+\eYsA WB/4uAn˒Z3et?D̤;R~]h;^wۈ%8Q[~,c0z8O,15 ##cP q&3UZm!H="ฏ@{Kݭފl:mv{aZ+' XZZ&5US}ܻK"`mB.m^1Bi草Pְ:8o,9g'6 -s"kdnh;{%NM2W*Bm=v0ByM/xWLP0-i]>[qK^aJ1hXCŒK/@-%Ͱ2RϐUo Wi_tmuc8)@AߔGf(_B?QL!"y,znFvz%JSGzGu3Ə?-l! F_a&ul/58?IJ.wY67Wh %jRgЖO;nuM@KۭCjChҰꄍ\QuR! endstream endobj 1007 0 obj << /Length1 1644 /Length2 6246 /Length3 0 /Length 7086 /Filter /FlateDecode >> stream xڭVuXmQ$A:{ bf`F)ABAJi$vzw=~}>ϹE "!h~a!.2D"u ]C Dp *0B*P0@D ,--MPF }ah)7//߿,@>@0( P8Cv|ЎP= P7Upԡp;r:00r0. %RD aܠ`(7@B]a(C܁p4hx@~'#$tG`nb0 >FaH4U_E<ю@( 17!` ( @`( CtI;+>;qP NDF`h^HXvϊ&@i$ .>ԞHPƄpTo"E<{;.3f̞~/\|76BbڢwH/- &%$C}`n @]`p(F? 3r῅ !#ٟUմ+%3lcm䃄3c䟇߄JJo_DJ1I vy,1~`7U8=HO@83{4L8yP7Ly wJ@W XvuE +AKo."Gd|WkZ<.S{ lܝ_9[$yCmI2>۟Yij2Y_20y}I8"~k;ͳ  4VOwΤo'z>\͉! LfIFعՁ/<%QSٍI^=ُ(3vEnWM⵽"D _1*iԼ>+1S+/5+#ިVOg+_&7z3e0"007y8*)Vs_CU4Qu@YXtӭmXF5/= ox=;rz) R88_멕ʆ?}'THJ^好!zAEյYf.ǡaMcek[x(ɄfW[>u}mX%ڷtR,_Nz,cY-nVJj&,˘8^T0O$~L:[M5}l+ 䲥Uiv bCki_{L'4s92#S{[hzVJL 1 Y1xDӝ {W{B?\emO .{èŖ+ {[~ǠH&t<ٙ е҉:s4w6bR[t"#FJJ-+؂ϛ-ܞu_ r%Z]=R9qBQ.tRKo3r g*.I_&,q-;.u7N.wZ,@I1-8ozt=-067}JJv@N&.S'11c.I遟QH_+ #츕f Y',bt}pcDc0]}[Ͱ[{t6c֣;e.zF;-N4O^}5aui/N_XLuY Weu'=i(-W'T :Ê䜌@Y0l5=o{Ri_DuzJ=}jj ?[5E0a\(rZ!~B]ݮIb;6HHVeyʃs7{puF IMkwWz67@I9<մp?UR BWsw;qޕ娔m x0iMN[-'BE|T6aP&(L>~s(,UiԂ%/׫Do@'m eaB/kU颴3;ҐY_.w9ctyCo3M(X K̔{wGrem]jE~v;:*}=7/* ^1ļu=u00ud6 ѻ?gj4{t>Z6]wo]V], JlL-fkNT"q>}-Q71Ryuʱ= 6oe) .XznHcƝMܒȀ*N6m<쿙龜h4=\XchXZdo?l}v(O#C]@T~Ij]/JktJL3p\*njGJVe% 5svS^/^v*m(?".?u36T0* sHmo1iֳk:XL:mkOT:fe|&ی?+p^L D\ry2n7xx 4S|e 2GY &('YϗL'\EA:%JAe(^fƆjN=矿zҹ5L7Ln' \ {krT/Z)rPf ,vb{'G)W$yU ] ՖL&'k>p'&2pmP 7߷*7Tx+ev5d=-f.+)Y7&lԅv z43ܺrXGo7i/E$VfHX'O!-{B+͚-E9qz \88ܾSؘF,d&Ł#ZK'Zp%{e䇑e읡D4>֟?'v`H SzQ?.djyW < R26/wX%e & +˽1KBZ}`G^px*ō$.=^%jxo÷3RrvHfsvuž p#`׭Z8uA=|xAy.W^K'r52˷GypU@ly (D{f*k#:6*З~8qR[Y~tA;ǚwO3"1e wDf3Z9$ {v#! Gߓe,\4x%3}+';vFJQ cߊgƕR$;RJwg>Mtmdd^rJ##:J~#9,y{Lmli5l8ъ 2_ݚG2uIbk\: Ãa$؁-.7>V[F  RQYu^sMۖBa~Skke.Y\^p<6MtxfU'\Uq%hPS.Ek×Tg|S[x* Tv65Uq_mh=3+핶 -|Q5" zS3I $?~PĆ֊dvFF+KLT1g)\lT+v\`_%T{Dpp"'" ^bD%ђ:1=KUGk5/QKi8ZI2.h GkK'5?[o8~#:|S@P%NbR؈WZZqp)v9LG;wq&WhWYHfb1P񇡰ظQe S82<}7tMySQ l 8HНs \7VϙIkJDF^dlOK$rxgΆ ve<:tz)E 4x Q>iy\Y*۞qϡ&oZiQQF!_`Cqj)Oyހ{R%@NGڄD)r0#juЍnqxJ WܑK7O] cK[Ilb5^]xJHWQ% =h,{U šn l8pDēT+ۼeP#Gؽא&,Ǭ%߽SPF\+(Qmnu|m in3ˋ7ZRz^ wZ-+fO JVK܅Q^n-C47)v?PӫMcJj_u6ˍ_]짚l\P/ِz)JF \Ђȥot}V%/K{NK * ܓd.{ʝDY}!=Jk,$\eD{J`r xX ^tm:gyj2Ό'q -Sse)ÂM}1Jbx CzXnK 0ے %yɓN3gEq.rTt2ގA>Ͱ5jx#ls&š>7N4H GbQʕCٰˆ3Opc+#Ǣi $1^Ɩnv)-%Zt3URcgnstzW  NN4}WHn~֒8^c3D'x7V"PZm)mīDq?[O;'%.D:j o^dAm8=e+f. UbCg)Q?E]6SPGqk/s:⦆ffЛҠx G͚ȟѱAް^XZ0JⲔڐihI.[ffǞn'\xiks˚ҙ\?6+OW@r{fh5t?PKZHA>tF2fZ+Cn 9/Cq}J޶xWfQ7I(s*Jq~oo1.ib 16]Qb݃3 ^Z^SĶqI1窲mSzvǨF}>1lAo=Ɖ1ݷ"ΔU\,>I%BE= ~І까o(uƱ;3BZ%َeH,O᣽cZab1ЃŶ M︒kjV`)˞GnU>I%Fow3J 0 :5;~O!&1Pv6%`M q i a Y`hB0Un4 H̔=Qhߟrn`( ɭ Q$&d{x:l6 bEKiPXh4 6YZBWv@-줻F SƙW\AM 􂊎 %d x3!9u^I{l*h2_QSS }l=>,yL febզJ7u䪞{M6r ت > stream xڭwct$ܶm͊:mv*۶;ض{wwTk5k"'VT27۹13r-m]md锁R.F6O \ hbio'jhM@33  bdinTS֠+c"Ζv?܀6@;O p,mE-)y @ht,B kisR68LL-*͙K`pvX~=LAo3.K;Wӿ OLUQTyX؛}47qOOp+1`j`c4\-- hndjtv;_7rp[3ƌ3glsK;8E?17 kf>02]>C(g* +GZFsgk௅ciZxw~[3TfKgqKyLN6vO#a&vhg5|w RbJ4ͶTz:IC?Q {عt9r1~_g9#'K#=##F9Rq134:9}*64[Y7 JLwf v(ZTWmUiZL0p/M}0܍iCѕp0_ tܽ7R)ؙmB aG: i;n{(@#TK#'mD{a:,ыy^zʹ|P俘BmTY~ҌL VxgON- pFJ] QDV5Ԋty5bʑwsG=qq3Z^Y[CKmjdU2Ux5t`WL.~e & B"zZ4|՞qcd9\CQnnT O^A= %䋃äՑ*}#l)QdFۋDR{>=6\I5 '",QP ),y8q9q#0F7gT~raVarXF .2UW!v!_>lGivho sBR"2j'(8jw~fj Vϲ L=ƻj⛔`QB &ٔɀVsnK^+c l?Mg:]*DDk98NH{bEi u$~~N5Lub4rne"pl[vS6'=PUSٛ@RM":U""UjҰy ͻ'E [ϣTH&~dRY+>F}nr.?Z=1} Nf 7K缊Vgi=B5Fn 3ȵ, of4v0lU%iGHϕZeh9(&ƶ)3!/9Bm2Cg 6qwHقD'yxN6HrokHl wxՏqɔK1~k ( _q5ʧIܮM l?YrL[j`Șb4W=0NHTGlqv vjt>%m+Ryɢ`Tvi?3aI 5M|+RhkIyREW'ƳRԌe+XU#XXg:/+4o2 ]JS3gK͙o"?;R% |k1^ Evgjh?DD) Ƥ$P¯ait7;wȒ39?| -Yol 7;*CwNHɦ$vㇽ#yN X AhF8!)яÝ&Ί8Ƣ⇘t[ɉ\bRh 3ix~pсUp̆nԇH!NI}`Eޯ3ߢPIfh'VJh 04*;nb1 VApi#^}s74sJiGeqixu `\Y/QdА% ֖ B4"ӼqRٓ/0/= ;5.$lNG9(?fD0FВ[v&ƮH6hܱ]@7z_#p62ZQSkJshPeҮK3[j`q[tV 5W,:M`a n]o r c 84njvĚO3}wdA9Yfbt57`hoX+uQcel1p 9% XSc J '|Y:_N `R}ˍwH9cTp hǟ$]u}fHP 'b%vf%vPf$jK0_¶YU'`UiP2쯌#?@2԰1 )|?:ɝR&aM[Z0EejD:)R֯FYN- @&MAXy_ X8>wԻtݬ'ύAϦ=&>B3E#Bhc+(^UL:SwA~uifNK-̱:" LRz0I{hB:rSup[{kNgOl{ KEC1rq1գ,"=.(n=ƟH!R5 fq/s 9#~ w,_ftMs~˲Nޜ781M14 !eDH2 \:MUDEMcgN' K֩gqkʮZSU,OCHwM 0m/UأҠбZNӟ_0b7U{ l5U#w &Hj$l&#oAgV|^w<ЌKj𨏲ey=AprT]|Mi81YŅp.OD|;s!-;}ݒh2%-ʬ1 fj~g\2ji!V֦vWhomEͽ?'=7ɤ- Z 6;qa5+aV=ꡫ>q+IrZ=R%|pY>reK}5p6NY t%s qٽ_.IWռ;b_Pb2ʘ 6$ce e,^`l<*1Fcv'AS6HB^qLe]پftw}4@qmz5ng?G$+ix;,ńW~PPzQ}v\Pۗ1rXk~Bdcj܍u?)%+&m,f{*)UF!CnnY"now͈Rx46OPbΈ5}ͷA G&6%?bw8O|t**ks\HZ2 ?Et~(łZA.OVl%X^ FIrexx%&$Hx5D5s(qE{7\We`ш5z9,AtH'ID;a+86>Uxt|vo4mp4͸w%b[FiJ&[k _%8Md A$U*ЬV/=|hR)%;&XM|JѫT{pu~SRpƘ^z tEpU*fKZHhJ֙u#"`uj)6FN{'cIXd٩̏ݪ}fz(3%rCW]7/5=mpE 0p@箘xQ#~[HK#&"32x^f^:d*/dr(v8+Bbj ^1^rM22lk.5ީVi}Szirҍ/|z@5?ٝF(?nj c2.ф>^NKXl7c`/*wsc$#jɞ8LkvM?6 LCSLgN8%E'(]"֭H ,$x$G^J⇤Ɲub gm,7PKP{9\X@?ccN"`U!iޅm:7u sEļ3"mgsZKVkt߄J1E 5<mkc! NLz 7ޑֽ9_ҽnȤoՍjb$hqY I{f3">!O}Klݒ6vjaOtP%}7B*ۏ⦼* e᭭*C9g fjBKo%By08rCYمYͼ. .9uH ɋTWeX,5R֟`}g*Ä72Mw j(k++ _ɪ}$&8z7>d^ҫޱ]$RSd _j`v! uT pepVJgOտ"\ҹL`k60_u A5)J|yxDfM p }Swk904ls@y9V)旊'M30y_ JSgijqTY{5*GǙ(/ZyT XцX T&i-L'p^y,DYh 'oxX O<.k__'/F2ɾbyc=T|w?tuTd56*ǁx'oyW8kOǘUoM)f-,FeQw/Cm>./;E9Wt,]u#\ }Bem M6) rl (!:J_.0qHET}<(Ҋ#VZSbq7 eۡ`ҝ:]pdYhT abᏛ"Ko~0 %6jԓkdK΍{|,_jIωgp{z'@Hp%v ӂ{C wx8TA~ 3{4aysxMU?L(VhG=GԏfbD?0{(ڋKsܐdGÇ(R{!^OW44@ԎxFCxYdw$PIöջJ<.4֖dIftNj`X"WYJ`)v~o<~Ny>BR OfKO=:?QiВ첋#!܀/HØéqpxᱛM$|a!XbTJI6,fEYD(؏x청3Ў~w&P)˜  Gc-eri#&Ri% !VC;?* |Q_AiVn4Yi*mxbIw7OϾ@24+iZ3xhK=1Q:r1~E6$/$<Ί\~HVmcb +BLhv\c3qaUdqb brnλ(;/z4%)ϙ&#{c^hr#rOl /{-ݶ&1`&Ŋ1ox+c2-*aoGiᲯp~h0fy8<ק \q)rU/|P\SNΛr k y6H=6PW$] =0mNdօnc2vY4+8Qb̞5'cr:J΢io@'j䭘Oʁ?0҇^nRfҾMo]ueBS:͛9(Âe6w'X5"iQ'- 52zMVg*leN9Q`~4P6} )lk<&s4nnh,ңd;؋Eu^i˯6, &.H8嚸vL<~±ߓK<ͺ`4}?@K2;>No_| ".V'c#<|p|>&cN(G)+ Dwދ*#Ki[%b -VWx B 9r.%6\v0ЀbJB`5 n*޿p%*a5s<_$auiNS"j]0w7 *fЮx?7 uqlކgAeSL<!5n3ʁ "A/lQ>f\<fDعTwjRbʢfl׈{4i:Z_T\ErNzr6uF1u6Wee\ bKn,~_w x? $@1BR0nxA\zUɚzl؅I٧qXHbv %1Ae}7Mެ0|HUprė:butπ~67M/Z^m.>jL)IMm~ʖ+Q˱iR_>g/ԃqZ98'YEPHVՎ6Rv;?IRU1\Q} B[:G%R+ m4T[/h]?ٙǥ|8 )=U#NfxJ[tr>3_b^SX9z,}T<p:1j}ٺ;EN/2:4Trm`˪mgjD- A Y;R9mœ'o4ٻOm)4_djl>Y@#߃cqWjĥzV)xp_M61t\IYts*WaOML\,{8>߱ʸ[h&ͪu3n$ݐrX6`ĈE( GHsJE&IPN)t䷢/d P]b-NJ۳"gi֢1L}5Cw LgŦ@F3hF9v&B1dK@lj+vH#ΆAh-¯4\Ȱ@\΋t53-2up9K$s !u$д[ot1iT?zEfhL黱NEě3qҟ8_f4=sa+D_\ߘ̈edx.pqUu\+XJ.233sOxuU1DjzTj?6xVǾzDqOggp d#Jc i/E9?-C˜Upof98$}ۺVw|UP{L>WV!Gi J*0 ߚodO0o$5>g !hR߇z'.n38Bl.DYWVO{[Sx:6^aP~Ũ0b⮟b|lG*пGI"H~\P .s&cRԱ P>pksJ^F ]Hqm(@r Z7:M Vc*⁎7L׏%>?wSzPajT!(y[FbonQ;qaT] Uϫv[6桕Ï0E@0Ƕ{.C`hUFE^glؑ&ETJsU4=tܺ_A~lEnاZ.Hp[@0?uq7>! ՐKla mߟB&Rn@^n B&uѺ(//P6U%QٖD`ӏǥF&[3[D8EeOX{IA+Ua+$TW:ZBWKR0涀CFͅ[ Ȥ$aòQhd%|d./].侾A*%muΩu%"F\t8-B9pѴps@Fc!$sk!~)LD<~e_1̎y45ҮvY$X)~KVrdȄ9'Ar^ZZf6(n= >I#nN@_m e)cZ"W|9UtiXwc \FfJXkDrDLӉ^EER?+c'gFyC_ @}αjLn)Pt/ */ߡQz",x˶;Cˬѽ1ZpY;#V~&~8EFhTrU4w{(XA~b*'{n7 i",Fm!ݩ#jva#ܬD@΍\1A\ˆCOV= 4fBW-ƍyeu|3b("X&{Wb,l XaW_M'mvӤ2z:c=]ʸGJrZB!y7sƝ:`G)nB>Kߪbt* Tv7iMW]7maHpt}U!|+'q>#3ɿR<}!֫T,CB}?da .iPz b4Fr-X i u73Ct'P!!+Elk+}s¤{.C=i&mw5h|LZ `DJfYGIr ^.kin+&GU;S Bk~?oKf{dⴲή·~+4dK#y9~|vJaٽ.aژ :,E[׏*D((,y Cll bDyjtg9"a6 lAa&rC;:t^xr hAē~tmlRRVloEvCc%~/ɖ $[ș$%5 $j/͋̓k9#Z@lka or6V(Y)" vh 'T~c+_wf }<&-`P-a7Vk#qJVC>T`r00O `t= ң bSwz@anP;̇`قM h#9 xXL޻M)[\qy'9cR⟶C*Vh=b`vlR3k/µxWXk"‹'2^ɨM-3ėWw4z˔Tʏ=Rm*xyFe5LVce-HШ3<³c ;v }z {辫;iŔAhMQ7tH"=vk"{ҚqEjVCy)Z 4> stream xmTMo0Wx$ ! 8l[jWHL7IPV=M̼ su;Uٛ=w]yil;<[[j<=?׾+v`&ߴț<^*;~&Q>MS >_P{=s@dkx;`VY`s4JaQܡn.Uu9\Y6><ٴ.Z.4>Dӗ}~r:-d0VWk,8yLһʮӮђ[*mLr?q 5F8@=@)& 8Rx uD\j2HV0CzL] bctI g$`htы0\F0s jd< I6zg W qȐ+#k .bsrbmXK7ǵH7Gnb>&jؐu1VljOu$՟qWS/%1{\xB!K(hHTЖ枃Jρϯv=k2UKς_:~$/ ~E+7ˢ/ l(/} -+ZXukoԝE?ZKq endstream endobj 1012 0 obj << /Length 739 /Filter /FlateDecode >> stream xmUMo0WxvHUdCmU^!1H#x?gx]OTm$|͜s_Iss :L;<Sz==׾f`*_`ɫڟk3'iѴ}=M;7rfnj-eSӵOLg~8 )ok A8 $`I\3`Af<Z]! xNky"7 _㓧q H`nḱRONH=CpB:# =%888QA~!*zƜАT?!~> tw8y*sύ }nFE>7*QύR>7G];~<6OIyktg>O:yұϓN|I/|yIg>O:y҅ϓ.}2 L> stream xmUMo0WxvHB!qض*jn$HP#x?gxLT$|+$=wwY[L5Okˍ}M=ٝP7{=,yfܢ_ybsn yS6`z¦}TEA] $rwyś~0uoMd?tNC0}*f6` `bێh[W0ƂtmeӶ4ݶ0[*0M\B+vX*+T*Xb-L s[ #*X,caq\``2Iш P]QA2E;XXJKC k88pLB$qƩ/088?rxy!B=X y82VAנp"Zqx8t9MD/W)u8|}ۆ~)30|SRHCOt$"NN_h 1'>4$OOB:]*N:qJ(sB5Qύ}nTsύ(Q<6O͓yk'<ϓ|t'=y '|yҩϓ|t <)>Ozg~x^uEtϭ{ՍȧU" t endstream endobj 1014 0 obj << /Length 740 /Filter /FlateDecode >> stream xmUMo0WxvHB!qض*jn$HP#x?gxLT$|+$=wwY[L5Okˍ}M=4$OOB:]*N:qJ(sB5Qύ}nTsύ(Q<6O͓yk'<ϓ|t'=y '|yҩϓ|t <)>Ozg~x^uEtϭ{ՍȧU"  endstream endobj 1015 0 obj << /Length 900 /Filter /FlateDecode >> stream xmUMo:W5?$R. d9M eCkmCp;;w~>|3E_?O]5߶w]Occ]=~?}Oyh9%?۹׬B|Ɯ>);vw%g43>\ 6 EJ78 1{~`W(-;]%=xe_,b+-O;q\L}UI--=BKE1p[! Mߊyu>.N5K)Wb٬8i[_uʕMzQ)V(Txޢjy!Z2P="Zd0\ÃGR\).2*Шa!U,H`+j.5Nα@VK-x%3%AYӀzΚ>kP#5m0Woþj.ZT$X/)n)#Wo(oRZ $Kp4Z-b\1ܰJ P"GXQi/8k^Zq:Zs9dB )sL-7xJ`aɽ)f$1 dъcCZC<73JgznHȰYɚTa,_-O87}KԴܗLloK+gJ.GZyVc48Wt]:P~`rZq.n1] S/Pu7Ue:?&?!d&1yHn5)yғBx#1ޞ]Go׏M?X endstream endobj 1016 0 obj << /Length 1022 /Filter /FlateDecode >> stream xmVMo8Wh҃kTHrضh^I IJ!ۇf|tǙqV}xܟ>ڿ7]Ocp{Vc> stream xmTn0+Jb'$8B 8l[jWHL$Q;o.Z ̼7/o~:W{xPCWQb6;J^ǩv'-[~Gݾߣ#i6ڿRV_n84]֚̽e[sYͮi P[ L:?=v8|`4nh7u{QE sU5Y7{C]_?{B^QSu; 3jV՞d;&xD\20-0b# !ڇ\)&q)% 1ON"ۂ%480`rH%Dd#C K .%"l %RQ NLHI($ux-LJ@J!^H :ggM597F7FN|[{}&Ff*pdk_ΜN0VG9ʱwDK4X=CaCɁg2)4X(rb0/s4lƵ.b]ʌ[r> stream xmTn0CƆ@LE"jD;oƤjgy_xN{qV'wC&]\]]u>t\qxں7ŦmN7isƬ'k~G]?ߓ` 4;RV_n86]{̭֚u[sfߴ L:?v>4|`0nhWu}QE KU=5Yw߇l?N6jwwv Z/բ,ko{&PaffIq XMJ0LfhrdĥP> stream xmVnH+AMyثL,R~(r]]n7W~c7߽p}z\[{%8OeWϝ\'}oe<]8m|kq7,r[|UJ;P)ڮ:U8 *&~(Ia7~x;~z. OM~?/,x72 .OC+B89 :u m#)u:#@,B: 6f{b\_> stream xmTn0CƆ@LE"j.RC~8iZ)Ayo7?nkNy$냛G׎ծU[7|SlfM[kwʽ5g x=i6;RV׵_n85]֚̽u[OsE͡i P{ LՑ @4=tb/yVvL MnݞArjwf4P׏ީFT]Nrî}sBZ2pmmR?\rs<, X#.KIɌCH'hjmJIQ09da"2rG~\5hגQv]`n @v)(A'b}qHI($ux-JBJ!^I :ggM597F7FN}Y{}&Ff.pdk_ ΜN0VG9ʱwDK4X=CaCɁg2)4X(rb0/s4lƵǮb]ˌ[r> stream xmTn0CƆ@LE"h.RC~8iZ)Ayo7?^$ŝPIs77EW]}==硫nTشxGɛz?{k۝=` 4vN߷u8NM>(s&`ywS0jzQshz+&TuS~Hxqq`P<+ OC톦}SWUn}@`T;P3qtj}w*5UWSܰo\ze \[3. 9ff ؤdF@!i @F\ ` H sn4ȶ` $(Ng 2R0zd9#Cb.k(@.0[Czr aà8SuX$Q:\CAfpGR~m%^!N%$h&՚R #ƿp'XϾ>AI }3Nh25gNE'bkkؿs %|V !3?fc91ӊ9|u 6ZcWCab d1׮eF-9Ag깐3Z=I= 6-7p?)pegT> stream xmTn0CƆ@LE"j.RC~8M])A̼7W?^$PIsWWEW]}~{SCWmݨMi7mv9I+ڴg{ҏÄ~F )P ǦkZn;@1zz5= 7m=x Fgu P}?i]X<;k C톦}UYoO} A`TS7~wpjmS!詺]]ꂅK(ew&97\=̒5⒁yAa>:M1ȈK,x΍t,@F*&" C,zdWXPv-hakH/]d"btv"gg?|2JB^G5kdwt,uVT Jb9;kBX!00a0bw3W M";\88̿9Earʱs ށ?c>+q p~PrL  hi˜c>:q-+01~k2#Ϡ3\OLqRυ>¹M \)s9O \Y!O>\\/Au*[ӺkzT%C0t endstream endobj 1023 0 obj << /Length 700 /Filter /FlateDecode >> stream xmTn0CƆ@LE"j.RC~8M])A̼7W?^$PIsWWEW]}~{SCWmݨMi7mv9I+ڴg{ҏÄ~F )P ǦkZn;@1zz5= 7m=x Fgu P}?i]X<;k C톦}UYoO} A`TS7~wpjmS!詺]]ꂅK(ew&97\=̒5⒁yAa>:M1ȈK,x΍t,@F*&" C,zdWXPv-hakH/]d"btv"gg?|2JB^G5kdwt,uVT Jb9;kBX!00a0bw3W M";\88̿9Earʱs ށ?c>+q p~PrL  hi˜c>:q-+01~k2#Ϡ3\OLqRυ>¹M \)s9O \Y!O>\\/Au*[ӺkzT%C2t endstream endobj 723 0 obj << /Type /ObjStm /N 100 /First 961 /Length 5844 /Filter /FlateDecode >> stream x\is7_߫ؗTyXc9.+ZmHBR= 4n6)RqjR6h,wm5F Hpwrwh+׆{1ӼLjdDj[-9Xn=кNF R(`j }#D!F(,@d2.1HJdhtE4Hm4qN40dcC+cЙsĀPX|-$2H Dy͙܅(i$Z:Ff14Z[H(=:Bw%s)=ZHrh!2P #WB h=╲2T0K04VR(%T?` Fx*ЛP/AMQd%%4a d`:$@.AdTBAAHvlG-WC <z*j (= ^C$S ޒ\Xhb,tzgdp(d: 10IʤGj8j譠ڳ 􍜡©M.ΨMΨ'-1j1@90Ud: "5.o'պۦ}]'k^҃ ·IAǤ}\ۦ}qӾ}^7&xEr=kB:iMLI*x.6i]-W %T_wFE2Ej}Jp>0[ήHonJ~{|X>@>BVYj*Y e[Yzw: )1Ǣ1ڔ WȽc;ɎYw0br98)Jʸcr`)>" MY}̻kձ|= iHEwMrhĝk[mԼCY?Cw:4T2^>vȍm!|i.8N*.%%@6xL$..v2{ZX5Ϙp֜ZӢE꯫BCpVH2UYRvgd`F? bN6Mu>VSX~SPnXksd]毸oY@#@`ERpZhJ(iBo`00,SH9*/>Rq|*%%$\Q(xSFh>be!tG%1 ]1;Bx \ wՎERB&!kn>!(AS3 BY%Ez0UU&(ȏ'$g@6S遼o&Jm ipMyr Ա:^PW&wh2  4vh2>[Wj| ^=ϴ 5j` 赴gZ =H TFJ?O;BbjF靄D6BǼ'ePo?I#t-C}D^T qLyJ}utciC=*&% wEkgGWH7SJkd N Aq,C5CW^: '&TWʲTI*/#x"Bп&RKR;^eL:Z ʇ!oBy ?zp|XGɏUsfcpp8^MW3 "$k(G;xH3%膄)U -4ZhhBS<=d(9~H&0e "90fQ;zH<? aРav%zWA1G7"@<]L:őX$ kOxw\-lzH@G=` *]w*34yFqf( 4Enja++ YA;ȡo[K}`vxȀ,_0}P*w%ÒATr,A.GPiK> ^".Oi{cΡSGщDMUAny܎g޸*۩ ;Uojt5vN;]okt35v Zи3B ;c*4L :e3B.o(&bxE %pv0v]ܮ/9xOIJ 립@ > uJk7 S#(LT5Sѹ}ww(&@1|^b>9ż-Ap%aEߏҽu9MPRtH6$v7V$:_`jt+tCR_X IF5.&@ FјKiAch9BG.}cwt, y& a4Yg9_9<>xX}^pZ^ R^i:' CA{ #M4 |<ˠ KL(e ehȗHe } g }Ɲ g }ƝtNTxЋ zQA/*-!gE7?C H'|c6`붛pc~ w7u.ms:ƙDDϖ>R":MEOD' .oMEjO:Ns=ovPd5>[g`[?IbVCp:[ί׋eD.<}˓o|^\L?Uc#@#p(lv 'OkL 18~=ݻx1C N׳_k$@ gi{=[bM%H9z.߇O_ ƪbU:qwVYb_N=[_>S>0~^S2닛U_\<0ۤTlNAD\rԾ.βIڞ͗g32.1v{1[i_ίP~ys__|iY_ZiO?~srzd\sŸ1&kZXdŶ~2p uwV g?~|~fu:zvtqq>n H2 Ae `x #W0~׾svgԜ}ƙ.F:>gr gNW gA} ߷0l_/UsWLY{^vٮnB9ȅ7ϟ~s^O_.  RɫJrekȁڏ|Neڬy{= 9O^u dv>œ;sOWپ&][t(kiC~VKgzlqp FaT7˰}rivj~5-p޲G8[0wɭ?-gvǢiol5_/̖=:9iӕ&\ҚP TZӼ7]UivVVblq%.ʝ}>^:خm(:+v%zv"gB[fr9|]OOͭ>kPqi;,-g~GcS%[-I>%=VMћ|V&ɋ VV 5V =T05Ln W@vi @+ gu7I{L".F4)'L\Nit4>=ꫝR8׃UڸqKEtu5#t-˸`Y`CoN _5O"$bxVW s$h6bA4ӟ_= BfIp!Ibޟ KRcRR4 IRCX"S鍏Ph Raں=?v#)ںaEtd 1bn۩崣s"Nm 7gG `̷Éܵ pcWF`w q.Ll"+~|CnӂM//jgkQ<S]_E[RŠnf='Dg]:`Ev 5!˲;mC*&+ SG!z|_;~|gs=/ME s}}`#e;12PF܎ ;`j{ACsGF֟H endstream endobj 1082 0 obj << /Producer (pdfTeX-1.40.25) /Author(\376\377\000T\000h\000o\000m\000a\000s\000\040\000B\000r\000e\000u\000e\000r\000\040\000;\000\040\000S\000e\000b\000a\000s\000t\000i\000a\000n\000\040\000G\000u\000t\000s\000c\000h\000e\000\040\000;\000\040\000M\000a\000x\000\040\000H\000o\000r\000n\000\040\000;\000\040\000A\000l\000e\000x\000a\000n\000d\000e\000r\000\040\000H\000u\000l\000p\000k\000e\000\040\000;\000\040\000P\000e\000d\000r\000o\000\040\000G\000a\000r\000c\000\355\000a\0004\0005\000S\000\341\000n\000c\000h\000e\000z\000\040\000;\000\040\000C\000h\000r\000i\000s\000t\000o\000p\000h\000e\000r\000\040\000J\000e\000f\000f\000e\000r\000s\000o\000n\000\040\000;\000\040\000S\000t\000e\000f\000a\000n\000\040\000K\000o\000h\000l\000\040\000;\000\040\000F\000r\000a\000n\000k\000\040\000L\000\374\000b\000e\000c\000k\000\040\000;\000\040\000C\000h\000r\000i\000s\000\040\000W\000e\000n\000s\000l\000e\000y)/Title(\376\377\000u\000t\000i\000l\000s)/Subject()/Creator(\376\377\000L\000a\000T\000e\000X\000\040\000w\000i\000t\000h\000\040\000h\000y\000p\000e\000r\000r\000e\000f\000\040\000p\000a\000c\000k\000a\000g\000e\000\040\000/\000\040\000G\000A\000P\000D\000o\000c)/Keywords() /CreationDate (D:19700101000000Z) /ModDate (D:19700101000000Z) /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023/Debian) kpathsea version 6.3.5) >> endobj 1028 0 obj << /Type /ObjStm /N 72 /First 673 /Length 3359 /Filter /FlateDecode >> stream xڭZߏ ~_1q$(00iA.=s%51gFI͒}$EQCg.PgmvtmCA.uHCd9uh t\Q`t`:kO}Ǧ:CRgѦ' φDy?)EDJ#y $Yᐼ{SFT,c(>$(<wOLS͓cKOO%Ëz[gק?v1g3CdQY F-Dctjf̋|;k~[ACT*Z@~8C[k~u:._l|o.D ߈\fW9M +(Y[aq Rnk@W%|fCFm#Q_l'·pekDH4)3VګnACQB  K]j})n̆k!R{VT@ _ Ԇ7?<~z|*39iyI" %@)?3w;u{\EeFEJ@"JDp#~{sK5j9  'ƅ=1)~ i>WC%pq". [x!v}"Dz"@E&6i188#\RNnF9X$폝)xvPEY ev27=%g@Ye&C,d'_q Gߜ$އ(OȐg2P#GgV48Z^/ n-vs<,7_C~l7"GyK7idĐL?onm͌y~I7l8q}J=8̋r{oQA>o9.V.\cQd[蛳3 'KL0d7}`8ʜR (-XKYJ;Nadlc{'eg2y.rQ}sv87ƞ 8 @ 9;`Y^i9@g47'C"Z5Sp>.NJ3"@>f[j+Տ蛳m44d$OVv4&r Zbj9U#Q;UN[S3F7. R9KSF`ܧI."~Dߜ$f`N=Sn/d'8e#Z5 P8g' ; T)}:NEwۨ"ȇ$s }svC3 !r|T yF^x,D C& >ܸTJ:}{[sӔ`R#WCs?cY蛳ymS&Ӌ 2|j;zdfɇJrD0Ifq;on疑|8ȑTn{<}ZnP/ekkB%\Sx5~FO:_u\,-sY3-V$vPl#ȋ8&3%w񾎻QMYﲃ,hIG}^wN0F xտ|K&%|3J9=oN~|uȎָ$g@ZcD^Rm9k;n5KzXj7d +"fj˦$6AjqN&Aʔ+Z$NZ, i&.LN3rlIˇIK7:jN #Rh OjrMD3'mPH6: ;65x`;F9]Dy4?WjtƅrRHBT3 t n" eN'il6ȥPI"HmLttpzxwRU({&*,W q#|feѽKfJَiYJ\] zb(@k_^֎GEÎG,)aB^3Ki d(|d5?38!{]ں ]XSJKthss$RI)6ur{o5޻k n̼JTCp0>4YGt&)Ϊh'^cVehAߺmT%$ζfEu$ C 3kqg*!X[ǦJ`\T<\]#,<5 /6TK#6U‚lC 3b44 *iM&6U51EùDJ#0Eyewd@ U "6U2ζB5gyx$y+sʯBQ>+\;GՇ ͟j+/:'K ORnYU^Xya嫯};u𕁯 |e}#f*P .RoZϿzwzuOE/ϟ߼'?L/^?3~;} b?/-E2 endstream endobj 1083 0 obj << /Type /XRef /Index [0 1084] /Size 1084 /W [1 3 1] /Root 1081 0 R /Info 1082 0 R /ID [<45922D68FCC87C00835492A052CD5F85> <45922D68FCC87C00835492A052CD5F85>] /Length 2783 /Filter /FlateDecode >> stream x%wx_U{ݛё٤m6$m&iIδI#m Q(K.Kϣz[@@ p ʔ) K}ϧwgEQtFL4n6J3`$K3ibrh˦9&B,$LlXLs L?IJSOdBL/чFX}ifOĪv&[@L_- um!#U $-1ܖ@)1}g0X1z΅2b9Ĵ;ˡX!1z΃&c4+X%4b{h.Zb YڈlFbkbvlivlNsvXL6KX0N"J\ ˈwl-!6DVdJ蕦KLVHlk`# y c+_ô'5)Mekj:`9 _{w~[)# :)# T{Q5vTUj zl; a>PTqhj7d h2QKQ Π1j2t(DEW]@%0 (@]nxPzIҤ*ն%T]:XXv6LXuMzƨ@9*1Pa;`l%mdE3jcR L#aKraLk3q0&@6L2ш.ɠsv YAG:whz].'0tD'G:B9x2fJ63^3sI5Ì0ѩW*MtfZcLf Sd3 ti&L+,{TAbc2ucku+`%^a ^} O.ҧ & `D76-a7vZ*`,#z^jKX=Ii#Uz*/]u]-5ѫb KxMֱWWX]RAR]9) .&0_okȌoh6YS𔅧|U/s_+ԧS=%Dw㌹[z_ .rtym ?%1QspWlxYyAᾏ? <ئ$anJtaIdݥz#3HB%2O9k u|L𿫄u6L[Tg ))-;G0Ja¤)U03!K(!^/L{H3' yB>\-^"YdP)̮HӅ2[ BrnJɾzT~UX0W-$QְGh$fKImӤ&؅Ev~Z"B'5faeZ{#ήhO2plԋ;MX. kԵm:n[u$ovwMAona ]UFIa{Ifv5Rvsa/c$85){ R%煓د-M0{L ¾iNgϨw3NY#2 s '#~;{E8=)j{g/^)\B+\*^&5n/AbqUӄM-) kJš{ kJ?KuoT{m^Rc-wcGƾՙTzDMjYz`R=QImGM&ubeLjzlRwl֣؛t-4p]'ra@ߐN;*9U8['*)$T*0~tПfBCWEP Ja6́PP`>TBu5BC4BdZ"hvX K:A_9rX{g/d%O endstream endobj startxref 305026 %%EOF utils-0.94/doc/manual.six0000644000000000000000000004332115174515600012312 0ustar00#SIXFORMAT GapDocGAP HELPBOOKINFOSIXTMP := rec( encoding := "UTF-8", bookname := "Utils", entries := [ [ "Title page", "0.0", [ 0, 0, 0 ], 1, 1, "title page", "X7D2C85EC87DD46E5" ], [ "Abstract", "0.0-1", [ 0, 0, 1 ], 64, 2, "abstract", "X7AA6C5737B711C89" ] , [ "Copyright", "0.0-2", [ 0, 0, 2 ], 82, 2, "copyright", "X81488B807F2A1CF1" ], [ "Acknowledgements", "0.0-3", [ 0, 0, 3 ], 92, 2, "acknowledgements", "X82A988D47DFAFCFA" ], [ "Table of Contents", "0.0-4", [ 0, 0, 4 ], 101, 3, "table of contents", "X8537FEB07AF2BEC8" ], [ "\033[1X\033[33X\033[0;-2YIntroduction\033[133X\033[101X", "1", [ 1, 0, 0 ], 1, 5, "introduction", "X7DFB63A97E67C0A1" ], [ "\033[1X\033[33X\033[0;-2YInformation for package authors\033[133X\033[101X\ ", "1.1", [ 1, 1, 0 ], 66, 6, "information for package authors", "X8508AD637B79CEE8" ], [ "\033[1X\033[33X\033[0;-2YPrinting Lists and Iterators\033[133X\033[101X", "2", [ 2, 0, 0 ], 1, 7, "printing lists and iterators", "X83686EE47E4D4F66" ], [ "\033[1X\033[33X\033[0;-2YPrinting selected items\033[133X\033[101X", "2.1", [ 2, 1, 0 ], 4, 7, "printing selected items", "X7F6817927F86240F" ], [ "\033[1X\033[33X\033[0;-2YLists, Sets and Strings\033[133X\033[101X", "3", [ 3, 0, 0 ], 1, 9, "lists sets and strings", "X7AE6EFC086C0EB3C" ], [ "\033[1X\033[33X\033[0;-2YFunctions for lists\033[133X\033[101X", "3.1", [ 3, 1, 0 ], 4, 9, "functions for lists", "X7C3F1E7D878AAA65" ], [ "\033[1X\033[33X\033[0;-2YDistinct and Common Representatives\033[133X\033[\ 101X", "3.2", [ 3, 2, 0 ], 109, 11, "distinct and common representatives", "X82F443FF84B8FCE3" ], [ "\033[1X\033[33X\033[0;-2YFunctions for strings\033[133X\033[101X", "3.3", [ 3, 3, 0 ], 159, 12, "functions for strings", "X8033A2FE80FC2F2A" ], [ "\033[1X\033[33X\033[0;-2YNumber-theoretic functions\033[133X\033[101X", "4", [ 4, 0, 0 ], 1, 13, "number-theoretic functions", "X86E71C1687F2D0AD" ], [ "\033[1X\033[33X\033[0;-2YFunctions for integers\033[133X\033[101X", "4.1", [ 4, 1, 0 ], 4, 13, "functions for integers", "X7D33B5B17BF785CA" ], [ "\033[1X\033[33X\033[0;-2YGroups and homomorphisms\033[133X\033[101X", "5", [ 5, 0, 0 ], 1, 16, "groups and homomorphisms", "X8171DAF2833FF728" ], [ "\033[1X\033[33X\033[0;-2YFunctions for groups\033[133X\033[101X", "5.1", [ 5, 1, 0 ], 4, 16, "functions for groups", "X7E21E6D285E6B12C" ], [ "\033[1X\033[33X\033[0;-2YLeft Cosets for Groups\033[133X\033[101X", "5.2", [ 5, 2, 0 ], 113, 18, "left cosets for groups", "X7FE4848B7DE6B3FD" ], [ "\033[1X\033[33X\033[0;-2YInverse\033[133X\033[101X", "5.2-2", [ 5, 2, 2 ], 160, 19, "inverse", "X793E48267EF5FD77" ], [ "\033[1X\033[33X\033[0;-2YFunctions for group homomorphisms\033[133X\033[10\ 1X", "5.3", [ 5, 3, 0 ], 174, 19, "functions for group homomorphisms", "X80A512877F515DE7" ], [ "\033[1X\033[33X\033[0;-2YMatrices\033[133X\033[101X", "6", [ 6, 0, 0 ], 1, 24, "matrices", "X812CCAB278643A59" ], [ "\033[1X\033[33X\033[0;-2YSome operations for matrices\033[133X\033[101X", "6.1", [ 6, 1, 0 ], 4, 24, "some operations for matrices", "X802118FB7C94D6BA" ], [ "\033[1X\033[33X\033[0;-2YIterators\033[133X\033[101X", "7", [ 7, 0, 0 ], 1, 26, "iterators", "X85A3F00985453F95" ], [ "\033[1X\033[33X\033[0;-2YSome iterators for groups and their isomorphisms\\ 033[133X\033[101X", "7.1", [ 7, 1, 0 ], 4, 26, "some iterators for groups and their isomorphisms", "X7BB5350081B27D17" ], [ "\033[1X\033[33X\033[0;-2YOperations on iterators\033[133X\033[101X", "7.2", [ 7, 2, 0 ], 68, 27, "operations on iterators", "X85413EED812C6497" ], [ "\033[1X\033[33X\033[0;-2YRecords\033[133X\033[101X", "8", [ 8, 0, 0 ], 1, 29, "records", "X7AA1073C7E943DD7" ], [ "\033[1X\033[33X\033[0;-2YFunctions for records\033[133X\033[101X", "8.1", [ 8, 1, 0 ], 4, 29, "functions for records", "X82B3D1D583CDF0E5" ], [ "\033[1X\033[33X\033[0;-2YOption records for functions\033[133X\033[101X", "8.2", [ 8, 2, 0 ], 25, 29, "option records for functions", "X7E6207B47B9AA30C" ], [ "\033[1X\033[33X\033[0;-2YWeb Downloads\033[133X\033[101X", "9", [ 9, 0, 0 ], 1, 31, "web downloads", "X815B0C4B7EBE6E1E" ], [ "\033[1X\033[33X\033[0;-2YFunctions for downloading files from the web\033[\ 133X\033[101X", "9.1", [ 9, 1, 0 ], 12, 31, "functions for downloading files from the web", "X8758CB7F79EFB6ED" ], [ "\033[1X\033[33X\033[0;-2YUser preference \033[10XDownloadVerifyCertificat\ e\033[110X\033[101X\027\033[1X\027\033[133X\033[101X", "9.1-2", [ 9, 1, 2 ], 75, 32, "user preference downloadverifycertificate", "X85182BA486E3C2AA" ], [ "\033[1X\033[33X\033[0;-2YUser preference \033[10XDownloadMaxTime\033[110X\\ 033[101X\027\033[1X\027\033[133X\033[101X", "9.1-3", [ 9, 1, 3 ], 98, 32, "user preference downloadmaxtime", "X79E10E5B83EF929F" ], [ "\033[1X\033[33X\033[0;-2YGeneralized Straight Line Programs\033[133X\033[1\ 01X", "10", [ 10, 0, 0 ], 1, 33, "generalized straight line programs", "X8314837E85D3D052" ], [ "\033[1X\033[33X\033[0;-2YFunctions for Generalized Straight Line Programs\\ 033[133X\033[101X", "10.1", [ 10, 1, 0 ], 87, 34, "functions for generalized straight line programs", "X7D1B00C979C8AEFD" ], [ "\033[1X\033[33X\033[0;-2YGeneralizedStraightLineProgram\033[133X\033[101X" , "10.1-2", [ 10, 1, 2 ], 113, 35, "generalizedstraightlineprogram", "X8503408985150E37" ], [ "\033[1X\033[33X\033[0;-2YVarious other functions\033[133X\033[101X", "11", [ 11, 0, 0 ], 1, 39, "various other functions", "X83EFC3178180D918" ], [ "\033[1X\033[33X\033[0;-2YFile operations\033[133X\033[101X", "11.1", [ 11, 1, 0 ], 4, 39, "file operations", "X81A0A4FF842B039B" ], [ "\033[1X\033[33X\033[0;-2YLaTeX strings\033[133X\033[101X", "11.2", [ 11, 2, 0 ], 27, 39, "latex strings", "X84D2922D87EDE9E9" ], [ "\033[1X\033[33X\033[0;-2YConversion to \033[22XMagma\033[122X\033[101X\\ 027\033[1X\027 strings\033[133X\033[101X", "11.3", [ 11, 3, 0 ], 59, 40, "conversion to magma strings", "X79F021B1830B68F6" ], [ "\033[1X\033[33X\033[0;-2YObsolete functions\033[133X\033[101X", "12", [ 12, 0, 0 ], 1, 42, "obsolete functions", "X7F561B1D803182FF" ], [ "\033[1X\033[33X\033[0;-2YOperations from AutoDoc\033[133X\033[101X", "12.1", [ 12, 1, 0 ], 4, 42, "operations from autodoc", "X7A6BB3D084912F35" ], [ "\033[1X\033[33X\033[0;-2YFunctions for printing\033[133X\033[101X", "12.2", [ 12, 2, 0 ], 21, 42, "functions for printing", "X86F322FC7DECE36F" ], [ "\033[1X\033[33X\033[0;-2YOther obsolete functions\033[133X\033[101X", "12.3", [ 12, 3, 0 ], 48, 43, "other obsolete functions", "X84A4F0B281FA0F94" ], [ "\033[1X\033[33X\033[0;-2YApplicable Methods\033[133X\033[101X", "12.3-1", [ 12, 3, 1 ], 51, 43, "applicable methods", "X78B7D1A982BE9866" ], [ "\033[1X\033[33X\033[0;-2YExponentOfPrime\033[133X\033[101X", "12.3-2", [ 12, 3, 2 ], 82, 43, "exponentofprime", "X7C1AF2467FB55D79" ], [ "\033[1X\033[33X\033[0;-2YThe transfer procedure\033[133X\033[101X", "13", [ 13, 0, 0 ], 1, 44, "the transfer procedure", "X84AC9613842F014C" ], [ "Bibliography", "bib", [ "Bib", 0, 0 ], 1, 46, "bibliography", "X7A6F98FD85F02BFE" ], [ "References", "bib", [ "Bib", 0, 0 ], 1, 46, "references", "X7A6F98FD85F02BFE" ], [ "Index", "ind", [ "Ind", 0, 0 ], 1, 47, "index", "X83A0356F839C696F" ], [ "GitHub repository", "1.0", [ 1, 0, 0 ], 1, 5, "github repository", "X7DFB63A97E67C0A1" ], [ "\033[2XPrintSelection\033[102X for a list of positions", "2.1-1", [ 2, 1, 1 ], 14, 7, "printselection for a list of positions", "X784638AC84D49870" ], [ "\033[2XPrintSelection\033[102X for a first item and a step", "2.1-1", [ 2, 1, 1 ], 14, 7, "printselection for a first item and a step", "X784638AC84D49870" ], [ "\033[2XDifferencesList\033[102X", "3.1-1", [ 3, 1, 1 ], 7, 9, "differenceslist", "X78B7C92681D2F13C" ], [ "\033[2XQuotientsList\033[102X", "3.1-2", [ 3, 1, 2 ], 27, 9, "quotientslist", "X7975371E865B89BC" ], [ "\033[2XFloatQuotientsList\033[102X", "3.1-2", [ 3, 1, 2 ], 27, 9, "floatquotientslist", "X7975371E865B89BC" ], [ "\033[2XSearchCycle\033[102X", "3.1-3", [ 3, 1, 3 ], 55, 10, "searchcycle", "X86096E73858CFABD" ], [ "\033[2XRandomCombination\033[102X", "3.1-4", [ 3, 1, 4 ], 95, 10, "randomcombination", "X7EF06CAD7F35245D" ], [ "distinct and common representatives", "3.2", [ 3, 2, 0 ], 109, 11, "distinct and common representatives", "X82F443FF84B8FCE3" ], [ "\033[2XDistinctRepresentatives\033[102X", "3.2-1", [ 3, 2, 1 ], 112, 11, "distinctrepresentatives", "X78105CAA847A888C" ], [ "\033[2XCommonRepresentatives\033[102X", "3.2-1", [ 3, 2, 1 ], 112, 11, "commonrepresentatives", "X78105CAA847A888C" ], [ "\033[2XCommonTransversal\033[102X", "3.2-1", [ 3, 2, 1 ], 112, 11, "commontransversal", "X78105CAA847A888C" ], [ "\033[2XIsCommonTransversal\033[102X", "3.2-1", [ 3, 2, 1 ], 112, 11, "iscommontransversal", "X78105CAA847A888C" ], [ "\033[2XBlankFreeString\033[102X", "3.3-1", [ 3, 3, 1 ], 162, 12, "blankfreestring", "X870C964E7804B266" ], [ "\033[2XAllSmoothIntegers\033[102X for two integers", "4.1-1", [ 4, 1, 1 ], 7, 13, "allsmoothintegers for two integers", "X8191A031788AC7C0" ], [ "\033[2XAllSmoothIntegers\033[102X for a list and an integer", "4.1-1", [ 4, 1, 1 ], 7, 13, "allsmoothintegers for a list and an integer", "X8191A031788AC7C0" ], [ "smooth integer", "4.1-1", [ 4, 1, 1 ], 7, 13, "smooth integer", "X8191A031788AC7C0" ], [ "\033[2XAllProducts\033[102X", "4.1-2", [ 4, 1, 2 ], 35, 13, "allproducts", "X78BE6B8B878D250D" ], [ "\033[2XRestrictedPartitionsWithoutRepetitions\033[102X", "4.1-3", [ 4, 1, 3 ], 57, 14, "restrictedpartitionswithoutrepetitions", "X845F46E579CEA43F" ], [ "\033[2XNextProbablyPrimeInt\033[102X", "4.1-4", [ 4, 1, 4 ], 79, 14, "nextprobablyprimeint", "X81708BF4858505E8" ], [ "\033[2XPrimeNumbersIterator\033[102X", "4.1-5", [ 4, 1, 5 ], 99, 14, "primenumbersiterator", "X8021EEE5787FCA37" ], [ "\033[2XComm\033[102X", "5.1-1", [ 5, 1, 1 ], 7, 16, "comm", "X80761843831B468E" ], [ "\033[2XIsCommuting\033[102X", "5.1-2", [ 5, 1, 2 ], 25, 16, "iscommuting", "X803A050C7A183CCC" ], [ "\033[2XListOfPowers\033[102X", "5.1-3", [ 5, 1, 3 ], 42, 16, "listofpowers", "X87A8F01286548037" ], [ "\033[2XGeneratorsAndInverses\033[102X", "5.1-4", [ 5, 1, 4 ], 62, 17, "generatorsandinverses", "X820B71307E41BEE5" ], [ "\033[2XUpperFittingSeries\033[102X", "5.1-5", [ 5, 1, 5 ], 78, 17, "upperfittingseries", "X84CF95227F9D562F" ], [ "\033[2XLowerFittingSeries\033[102X", "5.1-5", [ 5, 1, 5 ], 78, 17, "lowerfittingseries", "X84CF95227F9D562F" ], [ "\033[2XFittingLength\033[102X", "5.1-5", [ 5, 1, 5 ], 78, 17, "fittinglength", "X84CF95227F9D562F" ], [ "Fitting series", "5.1-5", [ 5, 1, 5 ], 78, 17, "fitting series", "X84CF95227F9D562F" ], [ "\033[2XLeftCoset\033[102X", "5.2-1", [ 5, 2, 1 ], 116, 18, "leftcoset", "X8340B4537F17DCD3" ], [ "\033[2XEpimorphismByGenerators\033[102X", "5.3-1", [ 5, 3, 1 ], 177, 19, "epimorphismbygenerators", "X80C9A0B583FEA7B9" ], [ "\033[2XPullback\033[102X", "5.3-2", [ 5, 3, 2 ], 209, 19, "pullback", "X7C705F2A79F8E43C" ], [ "\033[2XPullbackInfo\033[102X", "5.3-2", [ 5, 3, 2 ], 209, 19, "pullbackinfo", "X7C705F2A79F8E43C" ], [ "\033[2XCentralProduct\033[102X", "5.3-3", [ 5, 3, 3 ], 258, 20, "centralproduct", "X78DD2C617B992BE2" ], [ "\033[2XCentralProductInfo\033[102X", "5.3-3", [ 5, 3, 3 ], 258, 20, "centralproductinfo", "X78DD2C617B992BE2" ], [ "\033[2XIdempotentEndomorphisms\033[102X", "5.3-4", [ 5, 3, 4 ], 309, 21, "idempotentendomorphisms", "X801038CB808FC956" ], [ "\033[2XIdempotentEndomorphismsData\033[102X", "5.3-4", [ 5, 3, 4 ], 309, 21, "idempotentendomorphismsdata", "X801038CB808FC956" ], [ "\033[2XIdempotentEndomorphismsWithImage\033[102X", "5.3-4", [ 5, 3, 4 ], 309, 21, "idempotentendomorphismswithimage", "X801038CB808FC956" ], [ "\033[2XDirectProductOfFunctions\033[102X", "5.3-5", [ 5, 3, 5 ], 367, 22, "directproductoffunctions", "X81FA9E6C7F3B9238" ], [ "\033[2XDirectProductOfAutomorphismGroups\033[102X", "5.3-6", [ 5, 3, 6 ], 392, 22, "directproductofautomorphismgroups", "X7CB2D5F27F4182AF" ], [ "\033[2XDirectSumDecompositionMatrices\033[102X", "6.1-1", [ 6, 1, 1 ], 7, 24, "directsumdecompositionmatrices", "X787B89237E1398B6" ], [ "Iterators", "7.1", [ 7, 1, 0 ], 4, 26, "iterators", "X7BB5350081B27D17" ] , [ "\033[2XAllIsomorphismsIterator\033[102X", "7.1-1", [ 7, 1, 1 ], 11, 26, "allisomorphismsiterator", "X7F8B54D1806C762D" ], [ "\033[2XAllIsomorphismsNumber\033[102X", "7.1-1", [ 7, 1, 1 ], 11, 26, "allisomorphismsnumber", "X7F8B54D1806C762D" ], [ "\033[2XAllIsomorphisms\033[102X", "7.1-1", [ 7, 1, 1 ], 11, 26, "allisomorphisms", "X7F8B54D1806C762D" ], [ "\033[2XAllSubgroupsIterator\033[102X", "7.1-2", [ 7, 1, 2 ], 44, 27, "allsubgroupsiterator", "X831DA5AE8437578F" ], [ "\033[2XCartesianIterator\033[102X", "7.2-1", [ 7, 2, 1 ], 76, 27, "cartesianiterator", "X87395A9181A35301" ], [ "\033[2XUnorderedPairsIterator\033[102X", "7.2-2", [ 7, 2, 2 ], 99, 28, "unorderedpairsiterator", "X7C95E27987A812EA" ], [ "\033[2XAssignGlobals\033[102X", "8.1-1", [ 8, 1, 1 ], 7, 29, "assignglobals", "X84D82EB579B2ACCD" ], [ "\033[2XOptionRecordWithDefaults\033[102X", "8.2-1", [ 8, 2, 1 ], 28, 29, "optionrecordwithdefaults", "X8322B9377CC590D2" ], [ "\033[2XDownload\033[102X", "9.1-1", [ 9, 1, 1 ], 15, 31, "download", "X7A7438AE8448635E" ], [ "\033[10XDownloadVerifyCertificate\033[110X", "9.1-2", [ 9, 1, 2 ], 75, 32, "downloadverifycertificate", "X85182BA486E3C2AA" ], [ "\033[10XDownloadMaxTime\033[110X", "9.1-3", [ 9, 1, 3 ], 98, 32, "downloadmaxtime", "X79E10E5B83EF929F" ], [ "\033[2XIsGeneralizedStraightLineProgram\033[102X", "10.1-1", [ 10, 1, 1 ], 90, 34, "isgeneralizedstraightlineprogram", "X7D6F31797B8C3452" ], [ "\033[2XGeneralizedStraightLineProgram\033[102X for a list of lines (and th\ e number of generators)", "10.1-2", [ 10, 1, 2 ], 113, 35, "generalizedstraightlineprogram for a list of lines and the number of ge\ nerators", "X8503408985150E37" ], [ "\033[2XGeneralizedStraightLineProgram\033[102X for kind and list", "10.1-2", [ 10, 1, 2 ], 113, 35, "generalizedstraightlineprogram for kind and list", "X8503408985150E37" ], [ "\033[2XDataOfGeneralizedStraightLineProgram\033[102X", "10.1-3", [ 10, 1, 3 ], 141, 35, "dataofgeneralizedstraightlineprogram", "X7C5BD3777DBBB390" ], [ "\033[2XNrInputsOfGeneralizedStraightLineProgram\033[102X", "10.1-4", [ 10, 1, 4 ], 161, 35, "nrinputsofgeneralizedstraightlineprogram", "X7F47B79F7D7A51AC" ], [ "\033[2XNrOutputsOfGeneralizedStraightLineProgram\033[102X", "10.1-5", [ 10, 1, 5 ], 185, 36, "nroutputsofgeneralizedstraightlineprogram", "X7EFDD9F07F3AF218" ], [ "\033[2XResultOfGeneralizedStraightLineProgram\033[102X", "10.1-6", [ 10, 1, 6 ], 207, 36, "resultofgeneralizedstraightlineprogram", "X785C69E2789B3985" ], [ "\033[2XEquivalentStraightLineProgram\033[102X", "10.1-7", [ 10, 1, 7 ], 248, 37, "equivalentstraightlineprogram", "X81E725087E481727" ], [ "\033[2XIsInternallyConsistent\033[102X for generalized straight line progr\ am", "10.1-8", [ 10, 1, 8 ], 284, 38, "isinternallyconsistent for generalized straight line program", "X85E5CF147DAD5FA3" ], [ "\033[2XLog2HTML\033[102X", "11.1-1", [ 11, 1, 1 ], 7, 39, "log2html", "X7B7ECADF85F748BE" ], [ "\033[2XIntOrInfinityToLaTeX\033[102X", "11.2-1", [ 11, 2, 1 ], 30, 39, "intorinfinitytolatex", "X85F11FFA7F036669" ], [ "\033[2XLaTeXStringFactorsInt\033[102X", "11.2-2", [ 11, 2, 2 ], 45, 40, "latexstringfactorsint", "X7DC642B97CD02F4E" ], [ "\033[2XConvertToMagmaInputString\033[102X", "11.3-1", [ 11, 3, 1 ], 62, 40, "converttomagmainputstring", "X8768D7707B4CBBD4" ], [ "PermGroupToMagmaFormat", "11.3-1", [ 11, 3, 1 ], 62, 40, "permgrouptomagmaformat", "X8768D7707B4CBBD4" ], [ "PcGroupToMagmaFormat", "11.3-1", [ 11, 3, 1 ], 62, 40, "pcgrouptomagmaformat", "X8768D7707B4CBBD4" ], [ "MatrixGroupToMagmaFormat", "11.3-1", [ 11, 3, 1 ], 62, 40, "matrixgrouptomagmaformat", "X8768D7707B4CBBD4" ], [ "FindMatchingFiles", "12.1", [ 12, 1, 0 ], 4, 42, "findmatchingfiles", "X7A6BB3D084912F35" ], [ "CreateDirIfMissing", "12.1", [ 12, 1, 0 ], 4, 42, "createdirifmissing", "X7A6BB3D084912F35" ], [ "StringDotSuffix", "12.1", [ 12, 1, 0 ], 4, 42, "stringdotsuffix", "X7A6BB3D084912F35" ], [ "GetSuffix", "12.1", [ 12, 1, 0 ], 4, 42, "getsuffix", "X7A6BB3D084912F35" ], [ "SetIfMissing", "12.1", [ 12, 1, 0 ], 4, 42, "setifmissing", "X7A6BB3D084912F35" ], [ "PrintOneItemPerLine", "12.2", [ 12, 2, 0 ], 21, 42, "printoneitemperline", "X86F322FC7DECE36F" ], [ "PrintApplicableMethod", "12.3-1", [ 12, 3, 1 ], 51, 43, "printapplicablemethod", "X78B7D1A982BE9866" ], [ "ExponentOfPrime", "12.3-2", [ 12, 3, 2 ], 82, 43, "exponentofprime", "X7C1AF2467FB55D79" ], [ "OKtoReadFromUtils", "13.0", [ 13, 0, 0 ], 1, 44, "oktoreadfromutils", "X84AC9613842F014C" ] ] ); utils-0.94/doc/matrix.xml0000644000000000000000000000772515174515600012346 0ustar00 Matrices
Some operations for matrices In June 2023 Hongyi Zhao asked in the Forum for a function to implement matrix decomposition into blocks. Such a function was then provided by Pedro García-Sánchez. Hongyi Zhao then requested that the function be added to Utils. What is provided here is a revised version of the original solution, returning a list of decompositions.

This function is a partial inverse to the undocumented library operation DirectSumMat. So if L is the list of diagonal decompositions of a matrix M then each entry in L is a list of matrices, and the direct sum of each of these lists is equal to the original M.

In the following examples, M_6 is an obvious direct sum with 3 blocks. M_4 is an example with three decompositions, while M_8 = M_4 \oplus M_4 has 16 decompositions (not listed).

M6 := [ [1,2,0,0,0,0], [3,4,0,0,0,0], [5,6,0,0,0,0], > [0,0,9,0,0,0], [0,0,0,1,2,3], [0,0,0,4,5,6] ];; gap> Display( M6 ); [ [ 1, 2, 0, 0, 0, 0 ], [ 3, 4, 0, 0, 0, 0 ], [ 5, 6, 0, 0, 0, 0 ], [ 0, 0, 9, 0, 0, 0 ], [ 0, 0, 0, 1, 2, 3 ], [ 0, 0, 0, 4, 5, 6 ] ] gap> L6 := DirectSumDecompositionMatrices( M6 ); [ [ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ], [ [ 9 ] ], [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] ] ] gap> M4 := [ [0,3,0,0], [0,0,0,0], [0,0,0,0], [0,0,4,0] ];; gap> Display( M4 ); [ [ 0, 3, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 4, 0 ] ] gap> L4 := DirectSumDecompositionMatrices( M4 ); [ [ [ [ 0, 3 ] ], [ [ 0, 0 ], [ 0, 0 ], [ 4, 0 ] ] ], [ [ [ 0, 3 ], [ 0, 0 ] ], [ [ 0, 0 ], [ 4, 0 ] ] ], [ [ [ 0, 3 ], [ 0, 0 ], [ 0, 0 ] ], [ [ 4, 0 ] ] ] ] gap> for L in L4 do > A := DirectSumMat( L );; > if ( A = M4 ) then Print( "yes, A = M4\n" ); fi; > od; yes, A = M4 yes, A = M4 yes, A = M4 gap> M8 := DirectSumMat( M4, M4 );; gap> Display( M8 ); [ [ 0, 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, 4, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 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, 4, 0 ] ] gap> L8 := DirectSumDecompositionMatrices( M8 );; gap> Length( L8 ); 16 ]]>

The current method does not, however, catch all possible decompositions. In the following example the matrix M_5 has its third row and third column extirely zero, and the only decomposition found has a [0] factor. There are clearly two 2-factor decompositions with a 2-by-3 and a 3-by-2 factor, but these are not found at present.

M5 := [ [1,2,0,0,0], [3,4,0,0,0], [0,0,0,0,0], > [0,0,0,6,7], [0,0,0,8,9] ];; gap> Display(M5); [ [ 1, 2, 0, 0, 0 ], [ 3, 4, 0, 0, 0 ], [ 0, 0, 0, 0, 0 ], [ 0, 0, 0, 6, 7 ], [ 0, 0, 0, 8, 9 ] ] gap> L5 := DirectSumDecompositionMatrices( M5 ); [ [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 0 ] ], [ [ 6, 7 ], [ 8, 9 ] ] ] ] ]]>

utils-0.94/doc/nocolorprompt.css0000644000000000000000000000031315174515600013731 0ustar00 /* colors for ColorPrompt like examples */ span.GAPprompt { color: #000000; font-weight: normal; } span.GAPbrkprompt { color: #000000; font-weight: normal; } span.GAPinput { color: #000000; } utils-0.94/doc/number.xml0000644000000000000000000001324215174515600012321 0ustar00 Number-theoretic functions
Functions for integers This function has been transferred from package &RCWA;.

smooth integer The function AllSmoothIntegers(maxp,maxn) returns the list of all positive integers less than or equal to maxn whose prime factors are all in the list L = \{p ~|~ p \leqslant maxp, p~\mbox{prime} \}.

In the alternative form, when L is a list of primes, the function returns the list of all positive integers whose prime factors lie in L.

AllSmoothIntegers( 3, 1000 ); [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96, 108, 128, 144, 162, 192, 216, 243, 256, 288, 324, 384, 432, 486, 512, 576, 648, 729, 768, 864, 972 ] gap> AllSmoothIntegers( [5,11,17], 1000 ); [ 1, 5, 11, 17, 25, 55, 85, 121, 125, 187, 275, 289, 425, 605, 625, 935 ] gap> Length( last ); 16 gap> List( [3..20], n -> Length( AllSmoothIntegers( [5,11,17], 10^n ) ) ); [ 16, 29, 50, 78, 114, 155, 212, 282, 359, 452, 565, 691, 831, 992, 1173, 1374, 1595, 1843 ] ]]> This function has been transferred from package &RCWA;.

The command AllProducts(L,k) returns the list of all products of k entries of the list L. Note that every ordering of the entries is used so that, in the commuting case, there are bound to be repetitions.

AllProducts([1..4],3); [ 1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16, 2, 4, 6, 8, 4, 8, 12, 16, 6, 12, 18, 24, 8, 16, 24, 32, 3, 6, 9, 12, 6, 12, 18, 24, 9, 18, 27, 36, 12, 24, 36, 48, 4, 8, 12, 16, 8, 16, 24, 32, 12, 24, 36, 48, 16, 32, 48, 64 ] gap> Set(last); [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 64 ] gap> AllProducts( [(1,2,3),(2,3,4)], 2 ); [ (2,4,3), (1,2)(3,4), (1,3)(2,4), (1,3,2) ] ]]> This function has been transferred from package &RCWA;.

For a positive integer n and a set of positive integers S, this function returns the list of partitions of n into distinct elements of S. Unlike RestrictedPartitions, no repetitions are allowed.

RestrictedPartitions( 20, [4..10] ); [ [ 4, 4, 4, 4, 4 ], [ 5, 5, 5, 5 ], [ 6, 5, 5, 4 ], [ 6, 6, 4, 4 ], [ 7, 5, 4, 4 ], [ 7, 7, 6 ], [ 8, 4, 4, 4 ], [ 8, 6, 6 ], [ 8, 7, 5 ], [ 8, 8, 4 ], [ 9, 6, 5 ], [ 9, 7, 4 ], [ 10, 5, 5 ], [ 10, 6, 4 ], [ 10, 10 ] ] gap> RestrictedPartitionsWithoutRepetitions( 20, [4..10] ); [ [ 10, 6, 4 ], [ 9, 7, 4 ], [ 9, 6, 5 ], [ 8, 7, 5 ] ] gap> RestrictedPartitionsWithoutRepetitions( 10^2, List([1..10], n->n^2 ) ); [ [ 100 ], [ 64, 36 ], [ 49, 25, 16, 9, 1 ] ] ]]> This function has been transferred from package &RCWA;.

The function NextProbablyPrimeInt(n) does the same as NextPrimeInt(n) except that for reasons of performance it tests numbers only for IsProbablyPrimeInt(n) instead of IsPrimeInt(n). For large n, this function is much faster than NextPrimeInt(n)

n := 2^251; 3618502788666131106986593281521497120414687020801267626233049500247285301248 gap> NextProbablyPrimeInt( n ); 3618502788666131106986593281521497120414687020801267626233049500247285301313 gap> NextPrimeInt( n ); # same result, just faster 3618502788666131106986593281521497120414687020801267626233049500247285301313 ]]> This function has been transferred from package &RCWA;.

This function returns an iterator which runs over the prime numbers in ascending order; it takes an optional argument chunksize which specifies the length of the interval which is sieved in one go (the default is 10^7), and which can be used to balance runtime vs. memory consumption. It is assumed that chunksize is larger than any gap between two consecutive primes within the range one intends to run the iterator over.

iter := PrimeNumbersIterator();; gap> for i in [1..100] do p := NextIterator(iter); od; gap> p; 541 gap> sum := 0;; gap> ## "prime number race" 1 vs. 3 mod 4 gap> for p in PrimeNumbersIterator() do > if p <> 2 then sum := sum + E(4)^(p-1); fi; > if sum > 0 then break; fi; > od; gap> p; 26861 ]]>

utils-0.94/doc/obsolete.xml0000644000000000000000000000755715174515600012661 0ustar00 Obsolete functions
Operations from AutoDoc The file functions FindMatchingFiles FindMatchingFiles and CreateDirIfMissing CreateDirIfMissing were copied from package AutoDoc where they are named AutoDoc_FindMatchingFiles and AutoDoc_CreateDirIfMissing.

The string function StringDotSuffix StringDotSuffix was also copied from package AutoDoc, where it is named AUTODOC_GetSuffix. GetSuffix

The function SetIfMissing SetIfMissing was also transferred from package AutoDoc, where it is called AUTODOC_SetIfMissing. It writes into a record provided the position is not yet bound.

As from version 0.61, all these functions became obsolete in Utils, but continue to be defined in AutoDoc.

Functions for printing The function PrintOneItemPerLine PrintOneItemPerLine was used to prints lists vertically, rather than horizontally. Since a very similar result may be achieved using the &GAP; library functions Perform and Display, this function became obsolete in version 0.61.

s3 := SymmetricGroup( 3 );; gap> L := KnownPropertiesOfObject( GeneratorsOfGroup( s3 ) );; gap> Perform( L, Display ); IsFinite IsSmallList IsGeneratorsOfMagmaWithInverses IsAssociative IsGeneratorsOfSemigroup IsSubsetLocallyFiniteGroup gap> Perform( s3, Display ); () (2,3) (1,3) (1,3,2) (1,2,3) (1,2) ]]>

Other obsolete functions Applicable Methods The function PrintApplicableMethod PrintApplicableMethod, which was included in versions from 0.41 to 0.58, has been removed since it was considered superfluous. The example shows how to print out a function.

ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 1, 1 ); #I Searching Method for IsCyclic with 1 argument: #I Total: 8 entries #I Method 5: ``IsCyclic'' at GAPROOT/lib/grp.gi: 34 , value: 36 function( G ) ... end gap> Print( last ); function ( G ) if Length( GeneratorsOfGroup( G ) ) = 1 then return true; else TryNextMethod(); fi; return; end gap> ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 0, 3 ); function( obj ) ... end gap> Print( last ); function ( obj ) <> from GAPROOT/lib/oper1.g:767 end ]]> ExponentOfPrime The function ExponentOfPrime ExponentOfPrime was originally transferred from package &RCWA;. The command ExponentOfPrime(n,p) returned the exponent of the prime p in the prime factorization of n.

Since the &GAP; function PValuation produces the same results, and does so more quickly, this function has been made obsolete.

utils-0.94/doc/others.xml0000644000000000000000000001205515174515600012336 0ustar00 Various other functions
File operations This function has been transferred from package &RCWA;.

This function converts the &GAP; logfile filename to HTML. It appears that the logfile should be in your current directory. The extension of the input file must be *.log. The name of the output file is the same as the one of the input file except that the extension *.log is replaced by *.html. There is a sample CSS file in utils/doc/gaplog.css, which you can adjust to your taste.

LogTo( "triv.log" ); gap> a := 33^5; 39135393 gap> LogTo(); gap> Log2HTML( "triv.log" ); ]]>

&LaTeX; strings This function has been transferred from package &ResClasses;.

returns the &LaTeX; string for n.

IntOrInfinityToLaTeX( 10^3 ); "1000" gap> IntOrInfinityToLaTeX( infinity ); "\\infty" ]]> This function has been transferred from package &RCWA;.

It returns the prime factorization of the integer n as a string in &LaTeX; format.

LaTeXStringFactorsInt( Factorial(12) ); "2^{10} \\cdot 3^5 \\cdot 5^2 \\cdot 7 \\cdot 11" ]]>

Conversion to &Magma; strings The function ConvertToMagmaInputString( obj [, str] ) attempts to output a string s which can be read into &Magma; so as to produce the same group in that computer algebra system. In the second form the user specifies the name of the resulting object, so that the output string has the form "str := ...".

When obj is a permutation group, the operation PermGroupToMagmaFormat(obj) is called. PermGroupToMagmaFormat This function has been taken from other.gi in the main library where it was called MagmaInputString.

When obj is a pc-group, the operation PcGroupToMagmaFormat(obj) is called. PcGroupToMagmaFormat This function was private code of Max Horn.

When obj is a matrix group over a finite field, the operation MatrixGroupToMagmaFormat(obj) is called. MatrixGroupToMagmaFormat This function is a modification of private code of Frank Lübeck.

Hopefully code for other types of group will be added in due course.

These functions should be considered experimental, and more testing is desirable.

## permutation groups gap> ConvertToMagmaInputString( Group( (1,2,3,4,5), (3,4,5) ) ); "PermutationGroup<5|(1,2,3,4,5),\n(3,4,5)>;\n" gap> ConvertToMagmaInputString( Group( (1,2,3,4,5) ), "c5" ); "c5 := PermutationGroup<5|(1,2,3,4,5)>;\n" gap> ## pc-group gap> ConvertToMagmaInputString( DihedralGroup( IsPcGroup, 10 ) ); "PolycyclicGroup< f1,f2 |\nf1^2,\nf2^5,\nf2^f1 = f2^4\n>;\n" gap> ## fp-group gap> F2 := FreeGroup( 2 );; gap> f := F2.1;; g := F2.2;; gap> relq8 := [ f^4, g^4, f*g*f*g^-1, f^2*g^2 ];; gap> q8 := F2/relq8;; gap> ConvertToMagmaInputString( q8 ); no conversion function yet available for fp-groups fail gap> ## matrix group gap> M := GL(2,5);; Size(M); 480 gap> s1 := ConvertToMagmaInputString( M ); "F := GF(5);\nP := GL(2,F);\ngens := [\nP![2,0,0,1],\nP![4,1,4,0]\n];\nsub

;\n" gap> Print( s1 ); F := GF(5); P := GL(2,F); gens := [ P![2,0,0,1], P![4,1,4,0] ]; sub

; gap> n1 := [ [ Z(9)^0, Z(9)^0 ], [ Z(9)^0, Z(9) ] ];; gap> n2 := [ [ Z(9)^0, Z(9)^3 ], [ Z(9)^4, Z(9)^2 ] ];; gap> N := Group( n1, n2 );; Size( N ); 5760 gap> s2 := ConvertToMagmaInputString( N, "gpN" );; gap> Print( s2 ); F := GF(3^2); P := GL(2,F); w := PrimitiveElement(F); gens := [ P![ 1, 1, 1,w^1], P![ 1,w^3, 2,w^2] ]; gpN := sub

; ]]>

utils-0.94/doc/print.xml0000644000000000000000000000455315174515600012172 0ustar00 Printing Lists and Iterators
Printing selected items The functions described here print lists or objects with an iterator with one item per line, either the whole list/iterator or certain subsets: by giving a list of positions of items to be printed, or by specifying a first item and then a regular step. This function, given three (or four) parameters, calls operations PrintSelectionFromList or PrintSelectionFromIterator which prints the first item specified, and then the item at every step. The fourth parameter is essential when the object being printed is infinite.

Alternatively, given two parameters, with the second parameter a list L of positive integers, only the items at positions in L are printed.

L := List( [1..20], n -> n^5 );; gap> PrintSelection( L, [18..20] ); 18 : 1889568 19 : 2476099 20 : 3200000 gap> PrintSelection( L, 2, 9 ); 2 : 32 11 : 161051 20 : 3200000 gap> PrintSelection( L, 2, 3, 11 ); 2 : 32 5 : 3125 8 : 32768 11 : 161051 gap> s5 := SymmetricGroup( 5 );; gap> PrintSelection( s5, [30,31,100,101] ); 30 : (1,5)(3,4) 31 : (1,5,2) 100 : (1,4,3) 101 : (1,4)(3,5) gap> PrintSelection( s5, 1, 30 ); 1 : () 31 : (1,5,2) 61 : (1,2,3) 91 : (1,3,5,2,4) gap> PrintSelection( s5, 9, 11, 43 ); 9 : (2,5,3) 20 : (2,4) 31 : (1,5,2) 42 : (1,5,2,3,4) ]]>

utils-0.94/doc/ragged.css0000644000000000000000000000023115174515600012244 0ustar00/* times.css Frank Lübeck */ /* Change default CSS to use Times font. */ body { text-align: left; } utils-0.94/doc/rainbow.js0000644000000000000000000000533615174515600012313 0ustar00 function randchar(str) { var i = Math.floor(Math.random() * str.length); while (i == str.length) i = Math.floor(Math.random() * str.length); return str[i]; } hexdigits = "0123456789abcdef"; function randlight() { return randchar("cdef")+randchar(hexdigits)+ randchar("cdef")+randchar(hexdigits)+ randchar("cdef")+randchar(hexdigits) } function randdark() { return randchar("012345789")+randchar(hexdigits)+ randchar("012345789")+randchar(hexdigits)+ randchar("102345789")+randchar(hexdigits) } document.write('\n'); utils-0.94/doc/record.xml0000644000000000000000000001162215174515600012307 0ustar00 Records
Functions for records This function has been transferred from package &RCWA;.

It assigns the record components of rec to global variables with the same names.

r := rec( a := 1, b := 2, c := 3 );; gap> AssignGlobals( r ); The following global variables have been assigned: [ "a", "b", "c" ] gap> [a,b,c]; [ 1, 2, 3 ] ]]>

Option records for functions This functions has been transferred by Chris Jefferson from other packages. It simplifies the handling of records which are intended to be used for expressing configuration options. defaults represents the "default record", and useroptions lets the user give new values for values in defaults.

The function returns a record with the same component names as defaults and which has the same values as defaults, except for those component names in useroptions, where the values in useroptions are used instead. An error is given if useroptions contains any component names not in defaults. If useroptions is an empty list it is treated as an empty record, and if useroptions is a list of length 1 containing a record, this record is used as useroptions.

defaults := rec( a := 1, b := 2, c := 3 );; gap> OptionRecordWithDefaults( defaults, rec( a := 6) ); rec( a := 6, b := 2, c := 3 ) gap> OptionRecordWithDefaults( defaults, rec( b := 7, c := 8 ) ); rec( a := 1, b := 7, c := 8 ) gap> OptionRecordWithDefaults( defaults, [ ] ); rec( a := 1, b := 2, c := 3 ) gap> OptionRecordWithDefaults( defaults, [ rec( c := 8 ) ] ); rec( a := 1, b := 2, c := 8 ) gap> OptionRecordWithDefaults( defaults, rec( d := 9 ) ); Error, Unknown option: d gap> OptionRecordWithDefaults( defaults, [ rec( b := 7 ), rec( c := 8 ) ] ); Error, Too many arguments for function gap> OptionRecordWithDefaults( defaults, [6,7,8] ); Error, Too many arguments for function ]]> This function is designed to support functions with optional arguments given as a variable record, of the form function(x,y,options...).

In the following, very contrived, example function, PrintDimensions, the defaults are given by the variable order which takes values h, w and d having default values 1, 2 and 3. If there is a second argument, then OptionRecordWithDefaults( order, arg[2] ); is used to change the values. These three values then determine the order in which the three dimensions are printed using a SortParallel command. PrintDimensions := function( arg ) > local nargs, dim, order, V, L, len, K, i; > nargs := Length( arg ); > dim := [ arg[1]!.height, arg[1]!.width, arg[1]!.depth ]; > order := rec( h := 1, w := 2, d := 3 ); > V := [ "height", "width", "depth" ]; > if ( nargs > 1 ) and IsRecord( arg[2] ) then > order := OptionRecordWithDefaults( order, arg[2] ); > fi; > L := [ order!.h, order!.w, order!.d ]; > len := Length( L ); > K := [ 1..len ]; > SortParallel( L, K ); > Print( "dimensions: " ); > Print( V[K[1]], " = ", dim[K[1]], ", " ); > Print( V[K[2]], " = ", dim[K[2]], ", " ); > Print( V[K[3]], " = ", dim[K[3]], "\n" ); > end;; ]]> In the example below the first call to PrintDimensions has just one parameter, mydim, so the default order is used. In the second call, alternate values for h, w and d are given, causing the width to be printed first, and then the depth and height. mydim := rec( height := 45, width := 31, depth := 17 ); rec( depth := 17, height := 45, width := 31 ) gap> PrintDimensions( mydim ); dimensions: height = 45, width = 31, depth = 17 gap> PrintDimensions( mydim, rec( h:=3, w:=1, d:=2 ) ); dimensions: width = 31, depth = 17, height = 45 ]]>

utils-0.94/doc/template.xml0000644000000000000000000000174215174515600012646 0ustar00 Number-theoretic functions
Functions for integers These functions are in the process of being transferred from package &Home;.

They

utils-0.94/doc/times.css0000644000000000000000000000026115174515600012137 0ustar00/* times.css Frank Lübeck */ /* Change default CSS to use Times font. */ body { font-family: Times,Times New Roman,serif; } utils-0.94/doc/title.xml0000644000000000000000000000613115174515600012151 0ustar00 utils Utility functions in &GAP; 0.94 Thomas Breuer
sam@math.rwth-aachen.de https://www.math.rwth-aachen.de/~Thomas.Breuer
Sebastian Gutsche
gutsche@mathematik.uni-siegen.de https://sebasguts.github.io/
Max Horn
mhorn@rptu.de https://github.com/mhorn
Alexander Hulpke
hulpke@math.colostate.edu https://www.math.colostate.edu/~hulpke
Pedro García-Sánchez
pedro@ugr.es http://www.ugr.es/local/pedro
Christopher Jefferson
caj21@st-andrews.ac.uk https://caj.host.cs.st-andrews.ac.uk/
Stefan Kohl
stefan@mcs.st-and.ac.uk https://www.gap-system.org/DevelopersPages/StefanKohl/
Frank Lübeck
Frank.Luebeck@Math.RWTH-Aachen.De https://www.math.rwth-aachen.de/~Frank.Luebeck
Chris Wensley
cdwensley.maths@btinternet.com https://github.com/cdwensley
30 April 2026 The &Utils; package provides a space for utility functions in a variety of &GAP; packages to be collected together into a single package. In this way it is hoped that they will become more visible to package authors.

Any package author who transfers a function to &Utils; will become an author of &Utils;.

If deemed appropriate, functions may also be transferred from the main library.

Bug reports, suggestions and comments are, of course, welcome. Please contact the last author at cdwensley.maths@btinternet.com or submit an issue at the GitHub repository https://github.com/gap-packages/utils/issues/. © 2015-2026, The GAP Group.

The &Utils; package is free software; you can redistribute it and/or modify it under the terms of the 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 documentation was prepared using the &GAPDoc; and &AutoDoc; packages.

The procedure used to produce new releases uses the package GitHubPagesForGAP and the package ReleaseTools.

utils-0.94/doc/toggless.css0000644000000000000000000000167215174515600012654 0ustar00/* toggless.css Frank Lübeck */ /* Using javascript we change all div.ContSect to div.ContSectOpen or div.ContSectClosed. This way the config for div.ContSect in manual.css is no longer relevant. Here we add the CSS for the new elements. */ /* This layout is based on an idea by Burkhard Höfling. */ div.ContSectClosed { text-align: left; margin-left: 1em; } div.ContSectOpen { text-align: left; margin-left: 1em; } div.ContSectOpen div.ContSSBlock { display: block; text-align: left; margin-left: 1em; } div.ContSectOpen div.ContSSBlock a { display: block; width: 100%; margin-left: 1em; } span.tocline a:hover { display: inline; background: #eeeeee; } span.ContSS a:hover { display: inline; background: #eeeeee; } span.toctoggle { font-size: 80%; display: inline-block; width: 1.2em; } span.toctoggle:hover { background-color: #aaaaaa; } utils-0.94/doc/toggless.js0000644000000000000000000000420515174515600012473 0ustar00/* toggless.js Frank Lübeck */ /* this file contains two functions: mergeSideTOCHooks: this changes div.ContSect elements to the class ContSectClosed and includes a hook to toggle between ContSectClosed and ContSectOpen. openclosetoc: this function does the toggling, the rest is done by CSS */ closedTOCMarker = "▶ "; openTOCMarker = "▼ "; noTOCMarker = " "; /* merge hooks into side toc for opening/closing subsections with openclosetoc */ function mergeSideTOCHooks() { var hlist = document.getElementsByTagName("div"); for (var i = 0; i < hlist.length; i++) { if (hlist[i].className == "ContSect") { var chlds = hlist[i].childNodes; var el = document.createElement("span"); var oncl = document.createAttribute("class"); oncl.nodeValue = "toctoggle"; el.setAttributeNode(oncl); var cont; if (chlds.length > 2) { var oncl = document.createAttribute("onclick"); oncl.nodeValue = "openclosetoc(event)"; el.setAttributeNode(oncl); cont = document.createTextNode(closedTOCMarker); } else { cont = document.createTextNode(noTOCMarker); } el.appendChild(cont); hlist[i].firstChild.insertBefore(el, hlist[i].firstChild.firstChild); hlist[i].className = "ContSectClosed"; } } } function openclosetoc (event) { /* first two steps to make it work in most browsers */ var evt=window.event || event; if (!evt.target) evt.target=evt.srcElement; var markClosed = document.createTextNode(closedTOCMarker); var markOpen = document.createTextNode(openTOCMarker); var par = evt.target.parentNode.parentNode; if (par.className == "ContSectOpen") { par.className = "ContSectClosed"; evt.target.replaceChild(markClosed, evt.target.firstChild); } else if (par.className == "ContSectClosed") { par.className = "ContSectOpen"; evt.target.replaceChild(markOpen, evt.target.firstChild); } } /* adjust jscontent which is called onload */ jscontentfuncs.push(mergeSideTOCHooks); utils-0.94/doc/transfer.xml0000644000000000000000000001143615174515600012660 0ustar00 The transfer procedure We consider here the process for transferring utility functions from a package &Home; to &Utils; which has to avoid the potential problem of duplicate declarations of a function causing loading problems in &GAP;.

If the functions in &Home; all have names of the form HOME_FunctionName then, in &Utils;, these functions are likely to be renamed as FunctionName or something similar. In this case the problem of duplicate declarations does not arise. This is what has happened with transfers from the &AutoDoc; package.

The case where the function names are unchanged is more complicated. Initially we tried out a process which allowed repeated declarations and installations of the functions being transferred. This involved additions to the main library files global.g and oper.g. Since there were misgivings about interfering in this way with basic operations such as BIND_GLOBAL, a simpler (but slightly less convenient) process has been adopted.

Using this alternative procedure, the following steps will be followed when making transfers from &Home; to &Utils;. (&Home;:) Offer functions for inclusion. This may be simply done by emailing a list of functions. More usefully, email the declaration, implementation, test and documentation files, e.g.: home.gd, home.gi, home.tst and home.xml. (All active authors should be involved.) (&Home;:) Declare that m.n is the last version of &Home; to contain these functions, so that m.n+1 (or similar) will be the first version of &Home; to have all these functions removed, and to specify &Utils; as a required package. (&Utils;:) Add strings "home" and "m.n" to the list UtilsPackageVersions in the file utils/lib/start.gd. While the transfers are being made, it is essential that any new versions of &Home; should be tested with the latest version of &Utils; before they are released, so as to avoid loading failures. (&Utils;:) Include the function declaration and implementation sections in suitable files, enclosed within a conditional clause of the form: . . . . . . fi; ]]> OKtoReadFromUtils The function OKtoReadFromUtils returns true only if there is an installed version of &Home; and if this version is greater than m.n. So, at this stage, the copied code will not be read, and the transferred functions can only be called if &Home; has been installed. (&Utils;:) Add the test and documentation material to the appropriate files. The copied code can be tested by temporarily moving &Home; away from &GAP;'s package directory. (&Utils;:) Release a new version of &Utils; containing all the transferred material. (&Home;:) Edit out the declarations and implementations of all the transferred functions, and remove references to them in the manual and tests. Possibly add a note to the manual that these functions have been transferred. Add &Utils; to the list of &Home;'s required packages in PackageInfo.g. Release a new version of &Home;. (&Utils;:) In due course, when the new version(s) of &Home; are well established, it may be safe to remove the conditional clauses mentioned in item 4 above. The entry for &Home; in UtilsPackageLists may then be removed.

Finally, a note on the procedure for testing these functions. As long as a function being transferred still exists in the &Home; package, the code will not be read from &Utils;. So, when the tests are run, it is necessary to LoadPackage("home") before the function is called. The file utils/tst/testall.g makes sure that all the necessary packages are loaded before the individual tests are called. utils-0.94/doc/utils.tex0000644000000000000000000034670315174515600012204 0ustar00% generated by GAPDoc2LaTeX from XML source (Frank Luebeck) \documentclass[a4paper,11pt]{report} \usepackage[top=37mm,bottom=37mm,left=27mm,right=27mm]{geometry} \sloppy \pagestyle{myheadings} \usepackage{amssymb} \usepackage[utf8]{inputenc} \usepackage{makeidx} \makeindex \usepackage{color} \definecolor{FireBrick}{rgb}{0.5812,0.0074,0.0083} \definecolor{RoyalBlue}{rgb}{0.0236,0.0894,0.6179} \definecolor{RoyalGreen}{rgb}{0.0236,0.6179,0.0894} \definecolor{RoyalRed}{rgb}{0.6179,0.0236,0.0894} \definecolor{LightBlue}{rgb}{0.8544,0.9511,1.0000} \definecolor{Black}{rgb}{0.0,0.0,0.0} \definecolor{linkColor}{rgb}{0.0,0.0,0.554} \definecolor{citeColor}{rgb}{0.0,0.0,0.554} \definecolor{fileColor}{rgb}{0.0,0.0,0.554} \definecolor{urlColor}{rgb}{0.0,0.0,0.554} \definecolor{promptColor}{rgb}{0.0,0.0,0.589} \definecolor{brkpromptColor}{rgb}{0.589,0.0,0.0} \definecolor{gapinputColor}{rgb}{0.589,0.0,0.0} \definecolor{gapoutputColor}{rgb}{0.0,0.0,0.0} %% for a long time these were red and blue by default, %% now black, but keep variables to overwrite \definecolor{FuncColor}{rgb}{0.0,0.0,0.0} %% strange name because of pdflatex bug: \definecolor{Chapter }{rgb}{0.0,0.0,0.0} \definecolor{DarkOlive}{rgb}{0.1047,0.2412,0.0064} \usepackage{fancyvrb} \usepackage{mathptmx,helvet} \usepackage[T1]{fontenc} \usepackage{textcomp} \usepackage[ pdftex=true, bookmarks=true, a4paper=true, pdftitle={Written with GAPDoc}, pdfcreator={LaTeX with hyperref package / GAPDoc}, colorlinks=true, backref=page, breaklinks=true, linkcolor=linkColor, citecolor=citeColor, filecolor=fileColor, urlcolor=urlColor, pdfpagemode={UseNone}, ]{hyperref} \newcommand{\maintitlesize}{\fontsize{50}{55}\selectfont} % write page numbers to a .pnr log file for online help \newwrite\pagenrlog \immediate\openout\pagenrlog =\jobname.pnr \immediate\write\pagenrlog{PAGENRS := [} \newcommand{\logpage}[1]{\protect\write\pagenrlog{#1, \thepage,}} %% were never documented, give conflicts with some additional packages \newcommand{\GAP}{\textsf{GAP}} %% nicer description environments, allows long labels \usepackage{enumitem} \setdescription{style=nextline} %% depth of toc \setcounter{tocdepth}{1} %% command for ColorPrompt style examples \newcommand{\gapprompt}[1]{\color{promptColor}{\bfseries #1}} \newcommand{\gapbrkprompt}[1]{\color{brkpromptColor}{\bfseries #1}} \newcommand{\gapinput}[1]{\color{gapinputColor}{#1}} \begin{document} \logpage{[ 0, 0, 0 ]} \begin{titlepage} \mbox{}\vfill \begin{center}{\maintitlesize \textbf{ utils \mbox{}}}\\ \vfill \hypersetup{pdftitle= utils } \markright{\scriptsize \mbox{}\hfill utils \hfill\mbox{}} {\Huge \textbf{ Utility functions in \textsf{GAP} \mbox{}}}\\ \vfill {\Huge 0.94 \mbox{}}\\[1cm] { 30 April 2026 \mbox{}}\\[1cm] \mbox{}\\[2cm] {\Large \textbf{ Thomas Breuer\\ \mbox{}}}\\ {\Large \textbf{ Sebastian Gutsche\\ \mbox{}}}\\ {\Large \textbf{ Max Horn\\ \mbox{}}}\\ {\Large \textbf{ Alexander Hulpke\\ \mbox{}}}\\ {\Large \textbf{ Pedro Garc{\a'\i}a\texttt{\symbol{45}}S{\a'a}nchez\\ \mbox{}}}\\ {\Large \textbf{ Christopher Jefferson\\ \mbox{}}}\\ {\Large \textbf{ Stefan Kohl\\ \mbox{}}}\\ {\Large \textbf{ Frank L{\"u}beck\\ \mbox{}}}\\ {\Large \textbf{ Chris Wensley\\ \mbox{}}}\\ \hypersetup{pdfauthor= Thomas Breuer\\ ; Sebastian Gutsche\\ ; Max Horn\\ ; Alexander Hulpke\\ ; Pedro Garc{\a'\i}a\texttt{\symbol{45}}S{\a'a}nchez\\ ; Christopher Jefferson\\ ; Stefan Kohl\\ ; Frank L{\"u}beck\\ ; Chris Wensley\\ } \end{center}\vfill \mbox{}\\ {\mbox{}\\ \small \noindent \textbf{ Thomas Breuer\\ } Email: \href{mailto://sam@math.rwth-aachen.de} {\texttt{sam@math.rwth\texttt{\symbol{45}}aachen.de}}\\ Homepage: \href{https://www.math.rwth-aachen.de/~Thomas.Breuer} {\texttt{https://www.math.rwth\texttt{\symbol{45}}aachen.de/\texttt{\symbol{126}}Thomas.Breuer}}}\\ {\mbox{}\\ \small \noindent \textbf{ Sebastian Gutsche\\ } Email: \href{mailto://gutsche@mathematik.uni-siegen.de} {\texttt{gutsche@mathematik.uni\texttt{\symbol{45}}siegen.de}}\\ Homepage: \href{https://sebasguts.github.io/} {\texttt{https://sebasguts.github.io/}}}\\ {\mbox{}\\ \small \noindent \textbf{ Max Horn\\ } Email: \href{mailto://mhorn@rptu.de} {\texttt{mhorn@rptu.de}}\\ Homepage: \href{https://github.com/mhorn} {\texttt{https://github.com/mhorn}}}\\ {\mbox{}\\ \small \noindent \textbf{ Alexander Hulpke\\ } Email: \href{mailto://hulpke@math.colostate.edu} {\texttt{hulpke@math.colostate.edu}}\\ Homepage: \href{https://www.math.colostate.edu/~hulpke} {\texttt{https://www.math.colostate.edu/\texttt{\symbol{126}}hulpke}}}\\ {\mbox{}\\ \small \noindent \textbf{ Pedro Garc{\a'\i}a\texttt{\symbol{45}}S{\a'a}nchez\\ } Email: \href{mailto://pedro@ugr.es} {\texttt{pedro@ugr.es}}\\ Homepage: \href{http://www.ugr.es/local/pedro} {\texttt{http://www.ugr.es/local/pedro}}}\\ {\mbox{}\\ \small \noindent \textbf{ Christopher Jefferson\\ } Email: \href{mailto://caj21@st-andrews.ac.uk} {\texttt{caj21@st\texttt{\symbol{45}}andrews.ac.uk}}\\ Homepage: \href{https://caj.host.cs.st-andrews.ac.uk/} {\texttt{https://caj.host.cs.st\texttt{\symbol{45}}andrews.ac.uk/}}}\\ {\mbox{}\\ \small \noindent \textbf{ Stefan Kohl\\ } Email: \href{mailto://stefan@mcs.st-and.ac.uk} {\texttt{stefan@mcs.st\texttt{\symbol{45}}and.ac.uk}}\\ Homepage: \href{https://www.gap-system.org/DevelopersPages/StefanKohl/} {\texttt{https://www.gap\texttt{\symbol{45}}system.org/DevelopersPages/StefanKohl/}}}\\ {\mbox{}\\ \small \noindent \textbf{ Frank L{\"u}beck\\ } Email: \href{mailto://Frank.Luebeck@Math.RWTH-Aachen.De} {\texttt{Frank.Luebeck@Math.RWTH\texttt{\symbol{45}}Aachen.De}}\\ Homepage: \href{https://www.math.rwth-aachen.de/~Frank.Luebeck} {\texttt{https://www.math.rwth\texttt{\symbol{45}}aachen.de/\texttt{\symbol{126}}Frank.Luebeck}}}\\ {\mbox{}\\ \small \noindent \textbf{ Chris Wensley\\ } Email: \href{mailto://cdwensley.maths@btinternet.com} {\texttt{cdwensley.maths@btinternet.com}}\\ Homepage: \href{https://github.com/cdwensley} {\texttt{https://github.com/cdwensley}}}\\ \end{titlepage} \newpage\setcounter{page}{2} {\small \section*{Abstract} \logpage{[ 0, 0, 1 ]} The \textsf{Utils} package provides a space for utility functions in a variety of \textsf{GAP} packages to be collected together into a single package. In this way it is hoped that they will become more visible to package authors. Any package author who transfers a function to \textsf{Utils} will become an author of \textsf{Utils}. If deemed appropriate, functions may also be transferred from the main library. Bug reports, suggestions and comments are, of course, welcome. Please contact the last author at \href{mailto://cdwensley.maths@btinternet.com} {\texttt{cdwensley.maths@btinternet.com}} or submit an issue at the GitHub repository \href{https://github.com/gap-packages/utils/issues/} {\texttt{https://github.com/gap\texttt{\symbol{45}}packages/utils/issues/}}. \mbox{}}\\[1cm] {\small \section*{Copyright} \logpage{[ 0, 0, 2 ]} {\copyright} 2015\texttt{\symbol{45}}2026, The GAP Group. The \textsf{Utils} package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. \mbox{}}\\[1cm] {\small \section*{Acknowledgements} \logpage{[ 0, 0, 3 ]} This documentation was prepared using the \textsf{GAPDoc} \cite{GAPDoc} and \textsf{AutoDoc} \cite{AutoDoc} packages. The procedure used to produce new releases uses the package \textsf{GitHubPagesForGAP} \cite{GitHubPagesForGAP} and the package \textsf{ReleaseTools}. \mbox{}}\\[1cm] \newpage \def\contentsname{Contents\logpage{[ 0, 0, 4 ]}} \tableofcontents \newpage \chapter{\textcolor{Chapter }{Introduction}}\label{chap-intro} \logpage{[ 1, 0, 0 ]} \hyperdef{L}{X7DFB63A97E67C0A1}{} { The \textsf{Utils} package provides a space for utility functions from a variety of \textsf{GAP} packages to be collected together into a single package. In this way it is hoped that they will become more visible to other package authors. This package was first distributed as part of the \textsf{GAP} 4.8.2 distribution. The package is loaded with the command \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@LoadPackage( "utils" );| true \end{Verbatim} Functions have been transferred from the following packages: \begin{itemize} \item Conversion of a \textsf{GAP} group to a ${\sf Magma}$ output string, taken from various sources including \texttt{other.gi} in the main library. \end{itemize} Transfer is complete (for now) for functions from the following packages: \begin{itemize} \item \textsf{AutoDoc} \cite{AutoDoc} (with function names changed); \item \textsf{ResClasses} \cite{ResClasses}; \item \textsf{RCWA} \cite{RCWA}; \item \textsf{XMod} \cite{XMod}. \end{itemize} The package may be obtained either as a compressed \texttt{.tar} file or as a \texttt{.zip} file, \texttt{utils\texttt{\symbol{45}}version{\textunderscore}number.tar.gz}, by ftp from one of the following sites: \begin{itemize} \item the \textsf{Utils} GitHub release site: \href{https://gap-packages.github.io/utils/} {\texttt{https://gap\texttt{\symbol{45}}packages.github.io/utils/}}. \item any \textsf{GAP} archive, e.g. \href{https://www.gap-system.org/Packages/packages.html} {\texttt{https://www.gap\texttt{\symbol{45}}system.org/Packages/packages.html}}; \end{itemize} \index{GitHub repository} The package also has a GitHub repository at: \href{https://github.com/gap-packages/utils} {\texttt{https://github.com/gap\texttt{\symbol{45}}packages/utils}}. Once the package is loaded, the manual \texttt{doc/manual.pdf} can be found in the documentation folder. The \texttt{html} versions, with or without ${\sf MathJax}$, may be rebuilt as follows: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@ReadPackage( "utils", "makedoc.g" ); | \end{Verbatim} It is possible to check that the package has been installed correctly by running the test files (which terminates the \textsf{GAP} session): \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@ReadPackage( "utils", "tst/testall.g" );| Architecture: . . . . . testing: . . . . . . . . #I No errors detected while testing \end{Verbatim} Note that functions listed in this manual that are currently in the process of being transferred are only read from the source package \textsf{Home} (say), and so can only be used if \textsf{Home} has already been loaded. There are no such functions in transition at present. \section{\textcolor{Chapter }{Information for package authors}}\label{sect-author-info} \logpage{[ 1, 1, 0 ]} \hyperdef{L}{X8508AD637B79CEE8}{} { A function (or collection of functions) is suitable for transfer from a package \textsf{Home} to \textsf{Utils} if the following conditions are satisfied. \begin{itemize} \item The function is sufficiently non\texttt{\symbol{45}}specialised so that it might be of use to other authors. \item The function does not depend on the remaining functions in \textsf{Home} \item The function does not do what can already be done with a \textsf{GAP} library function. \item Documentation of the function and test examples are available. \item When there is more than one active author of \textsf{Home}, they should all be aware (and content) that the transfer is taking place. \end{itemize} Authors of packages may be reluctant to let go of their utility functions. The following principles may help to reassure them. (Suggestions for more items here are welcome.) \begin{itemize} \item A function that has been transferred to \textsf{Utils} will not be changed without the approval of the original author. \item The current package maintainer has every intention of continuing to maintain \textsf{Utils}. In the event that this proves impossible, the \textsf{GAP} development team will surely find someone to take over. \item Function names will not be changed unless specifically requested by \textsf{Home}'s author(s) or unless they have the form \texttt{HOME{\textunderscore}FunctionName}. \item In order to speed up the transfer process, only functions from one package will be in transition at any given time. Hopefully a week or two will suffice for most packages. \item Any package author who transfers a function to \textsf{Utils} will become an author of \textsf{Utils}. (In truth, \textsf{Utils} does not have \emph{authors}, just a large number of \emph{contributors}.) \end{itemize} The process for transferring utility functions from \textsf{Home} to \textsf{Utils} is described in Chapter \ref{chap-transfer}. } } \chapter{\textcolor{Chapter }{Printing Lists and Iterators}}\label{chap-print} \logpage{[ 2, 0, 0 ]} \hyperdef{L}{X83686EE47E4D4F66}{} { \section{\textcolor{Chapter }{Printing selected items}}\label{sec-print-select} \logpage{[ 2, 1, 0 ]} \hyperdef{L}{X7F6817927F86240F}{} { The functions described here print lists or objects with an iterator with one item per line, either the whole list/iterator or certain subsets: \begin{itemize} \item by giving a list of positions of items to be printed, or \item by specifying a first item and then a regular step. \end{itemize} \subsection{\textcolor{Chapter }{PrintSelection (for a list of positions)}} \logpage{[ 2, 1, 1 ]}\nobreak \hyperdef{L}{X784638AC84D49870}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PrintSelection({\mdseries\slshape obj, list})\index{PrintSelection@\texttt{PrintSelection}!for a list of positions} \label{PrintSelection:for a list of positions} }\hfill{\scriptsize (function)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PrintSelection({\mdseries\slshape obj, first, step[, last]})\index{PrintSelection@\texttt{PrintSelection}!for a first item and a step} \label{PrintSelection:for a first item and a step} }\hfill{\scriptsize (function)}}\\ This function, given three (or four) parameters, calls operations \texttt{PrintSelectionFromList} or \texttt{PrintSelectionFromIterator} which prints the \emph{first} item specified, and then the item at every \emph{step}. The fourth parameter is essential when the object being printed is infinite. Alternatively, given two parameters, with the second parameter a list \texttt{L} of positive integers, only the items at positions in \texttt{L} are printed. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@L := List( [1..20], n -> n^5 );;| !gapprompt@gap>| !gapinput@PrintSelection( L, [18..20] );| 18 : 1889568 19 : 2476099 20 : 3200000 !gapprompt@gap>| !gapinput@PrintSelection( L, 2, 9 ); | 2 : 32 11 : 161051 20 : 3200000 !gapprompt@gap>| !gapinput@PrintSelection( L, 2, 3, 11 );| 2 : 32 5 : 3125 8 : 32768 11 : 161051 !gapprompt@gap>| !gapinput@s5 := SymmetricGroup( 5 );;| !gapprompt@gap>| !gapinput@PrintSelection( s5, [30,31,100,101] );| 30 : (1,5)(3,4) 31 : (1,5,2) 100 : (1,4,3) 101 : (1,4)(3,5) !gapprompt@gap>| !gapinput@PrintSelection( s5, 1, 30 );| 1 : () 31 : (1,5,2) 61 : (1,2,3) 91 : (1,3,5,2,4) !gapprompt@gap>| !gapinput@PrintSelection( s5, 9, 11, 43 );| 9 : (2,5,3) 20 : (2,4) 31 : (1,5,2) 42 : (1,5,2,3,4) \end{Verbatim} } } } \chapter{\textcolor{Chapter }{Lists, Sets and Strings}}\label{chap-lists} \logpage{[ 3, 0, 0 ]} \hyperdef{L}{X7AE6EFC086C0EB3C}{} { \section{\textcolor{Chapter }{Functions for lists}}\label{sec-lists} \logpage{[ 3, 1, 0 ]} \hyperdef{L}{X7C3F1E7D878AAA65}{} { \subsection{\textcolor{Chapter }{DifferencesList}} \logpage{[ 3, 1, 1 ]}\nobreak \hyperdef{L}{X78B7C92681D2F13C}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DifferencesList({\mdseries\slshape L})\index{DifferencesList@\texttt{DifferencesList}} \label{DifferencesList} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{ResClasses}. It takes a list $L$ of length $n$ and outputs the list of length $n-1$ containing all the differences $L[i]-L[i-1]$. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@List( [1..12], n->n^3 );| [ 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728 ] !gapprompt@gap>| !gapinput@DifferencesList( last );| [ 7, 19, 37, 61, 91, 127, 169, 217, 271, 331, 397 ] !gapprompt@gap>| !gapinput@DifferencesList( last );| [ 12, 18, 24, 30, 36, 42, 48, 54, 60, 66 ] !gapprompt@gap>| !gapinput@DifferencesList( last );| [ 6, 6, 6, 6, 6, 6, 6, 6, 6 ] \end{Verbatim} } \subsection{\textcolor{Chapter }{QuotientsList}} \logpage{[ 3, 1, 2 ]}\nobreak \hyperdef{L}{X7975371E865B89BC}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{QuotientsList({\mdseries\slshape L})\index{QuotientsList@\texttt{QuotientsList}} \label{QuotientsList} }\hfill{\scriptsize (function)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{FloatQuotientsList({\mdseries\slshape L})\index{FloatQuotientsList@\texttt{FloatQuotientsList}} \label{FloatQuotientsList} }\hfill{\scriptsize (function)}}\\ These functions have been transferred from package \textsf{ResClasses}. They take a list $L$ of length $n$ and output the quotients $L[i]/L[i-1]$ of consecutive entries in $L$. An error is returned if an entry is zero. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@List( [0..10], n -> Factorial(n) );| [ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 ] !gapprompt@gap>| !gapinput@QuotientsList( last );| [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] !gapprompt@gap>| !gapinput@L := [ 1, 3, 5, -1, -3, -5 ];;| !gapprompt@gap>| !gapinput@QuotientsList( L );| [ 3, 5/3, -1/5, 3, 5/3 ] !gapprompt@gap>| !gapinput@FloatQuotientsList( L );| [ 3., 1.66667, -0.2, 3., 1.66667 ] !gapprompt@gap>| !gapinput@QuotientsList( [ 2, 1, 0, -1, -2 ] );| [ 1/2, 0, fail, 2 ] !gapprompt@gap>| !gapinput@FloatQuotientsList( [1..10] );| [ 2., 1.5, 1.33333, 1.25, 1.2, 1.16667, 1.14286, 1.125, 1.11111 ] !gapprompt@gap>| !gapinput@Product( last );| 10. \end{Verbatim} } \subsection{\textcolor{Chapter }{SearchCycle}} \logpage{[ 3, 1, 3 ]}\nobreak \hyperdef{L}{X86096E73858CFABD}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{SearchCycle({\mdseries\slshape L})\index{SearchCycle@\texttt{SearchCycle}} \label{SearchCycle} }\hfill{\scriptsize (operation)}}\\ This function has been transferred from package \textsf{RCWA}. \texttt{SearchCycle} is a tool to find likely cycles in lists. What, precisely, a \emph{cycle} is, is deliberately fuzzy here, and may possibly even change. The idea is that the beginning of the list may be anything, following that the same pattern needs to be repeated several times in order to be recognized as a cycle. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@L := [1..20];; L[1]:=13;; | !gapprompt@gap>| !gapinput@for i in [1..19] do | !gapprompt@>| !gapinput@ if IsOddInt(L[i]) then L[i+1]:=3*L[i]+1; else L[i+1]:=L[i]/2; fi;| !gapprompt@>| !gapinput@ od; | !gapprompt@gap>| !gapinput@L; | [ 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4 ] !gapprompt@gap>| !gapinput@SearchCycle( L ); | [ 1, 4, 2 ] !gapprompt@gap>| !gapinput@n := 1;; L := [n];;| !gapprompt@gap>| !gapinput@for i in [1..100] do n:=(n^2+1) mod 1093; Add(L,n); od;| !gapprompt@gap>| !gapinput@L; | [ 1, 2, 5, 26, 677, 363, 610, 481, 739, 715, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004 ] !gapprompt@gap>| !gapinput@C := SearchCycle( L );| [ 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754 ] !gapprompt@gap>| !gapinput@P := Positions( L, 157 );| [ 14, 26, 38, 50, 62, 74, 86, 98 ] !gapprompt@gap>| !gapinput@Length( C ); DifferencesList( P );| 12 [ 12, 12, 12, 12, 12, 12, 12 ] \end{Verbatim} } \subsection{\textcolor{Chapter }{RandomCombination}} \logpage{[ 3, 1, 4 ]}\nobreak \hyperdef{L}{X7EF06CAD7F35245D}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{RandomCombination({\mdseries\slshape S, k})\index{RandomCombination@\texttt{RandomCombination}} \label{RandomCombination} }\hfill{\scriptsize (operation)}}\\ This function has been transferred from package \textsf{ResClasses}. It returns a random unordered $k$\texttt{\symbol{45}}tuple of distinct elements of a set{\nobreakspace}$S$. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@## "6 aus 49" is a common lottery in Germany| !gapprompt@gap>| !gapinput@RandomCombination( [1..49], 6 ); | [ 2, 16, 24, 26, 37, 47 ] \end{Verbatim} } } \section{\textcolor{Chapter }{Distinct and Common Representatives}}\logpage{[ 3, 2, 0 ]} \hyperdef{L}{X82F443FF84B8FCE3}{} { \index{distinct and common representatives} \subsection{\textcolor{Chapter }{DistinctRepresentatives}} \logpage{[ 3, 2, 1 ]}\nobreak \hyperdef{L}{X78105CAA847A888C}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DistinctRepresentatives({\mdseries\slshape list})\index{DistinctRepresentatives@\texttt{DistinctRepresentatives}} \label{DistinctRepresentatives} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{CommonRepresentatives({\mdseries\slshape list})\index{CommonRepresentatives@\texttt{CommonRepresentatives}} \label{CommonRepresentatives} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{CommonTransversal({\mdseries\slshape grp, subgrp})\index{CommonTransversal@\texttt{CommonTransversal}} \label{CommonTransversal} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsCommonTransversal({\mdseries\slshape grp, subgrp, list})\index{IsCommonTransversal@\texttt{IsCommonTransversal}} \label{IsCommonTransversal} }\hfill{\scriptsize (operation)}}\\ These operations have been transferred from package \textsf{XMod}. They deal with lists of subsets of $[1 \ldots n]$ and construct systems of distinct and common representatives using simple, non\texttt{\symbol{45}}recursive, combinatorial algorithms. When $L$ is a set of $n$ subsets of $[1 \ldots n]$ and the Hall condition is satisfied (the union of any $k$ subsets has at least $k$ elements), a set of \texttt{DistinctRepresentatives} exists. When $J,K$ are both lists of $n$ sets, the operation \texttt{CommonRepresentatives} returns two lists: the set of representatives, and a permutation of the subsets of the second list. The operation \texttt{CommonTransversal} may be used to provide a common transversal for the sets of left and right cosets of a subgroup $H$ of a group $G$, although a greedy algorithm is usually quicker. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@J := [ [1,2,3], [3,4], [3,4], [1,2,4] ];;| !gapprompt@gap>| !gapinput@DistinctRepresentatives( J );| [ 1, 3, 4, 2 ] !gapprompt@gap>| !gapinput@K := [ [3,4], [1,2], [2,3], [2,3,4] ];;| !gapprompt@gap>| !gapinput@CommonRepresentatives( J, K );| [ [ 3, 3, 3, 1 ], [ 1, 3, 4, 2 ] ] !gapprompt@gap>| !gapinput@d16 := DihedralGroup( IsPermGroup, 16 ); | Group([ (1,2,3,4,5,6,7,8), (2,8)(3,7)(4,6) ]) !gapprompt@gap>| !gapinput@SetName( d16, "d16" );| !gapprompt@gap>| !gapinput@c4 := Subgroup( d16, [ d16.1^2 ] ); | Group([ (1,3,5,7)(2,4,6,8) ]) !gapprompt@gap>| !gapinput@SetName( c4, "c4" );| !gapprompt@gap>| !gapinput@RightCosets( d16, c4 );| [ RightCoset(c4,()), RightCoset(c4,(2,8)(3,7)(4,6)), RightCoset(c4,(1,8,7,6,5, 4,3,2)), RightCoset(c4,(1,8)(2,7)(3,6)(4,5)) ] !gapprompt@gap>| !gapinput@trans := CommonTransversal( d16, c4 );| [ (), (2,8)(3,7)(4,6), (1,2,3,4,5,6,7,8), (1,2)(3,8)(4,7)(5,6) ] !gapprompt@gap>| !gapinput@IsCommonTransversal( d16, c4, trans );| true \end{Verbatim} } } \section{\textcolor{Chapter }{Functions for strings}}\label{sec-strings} \logpage{[ 3, 3, 0 ]} \hyperdef{L}{X8033A2FE80FC2F2A}{} { \subsection{\textcolor{Chapter }{BlankFreeString}} \logpage{[ 3, 3, 1 ]}\nobreak \hyperdef{L}{X870C964E7804B266}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BlankFreeString({\mdseries\slshape obj})\index{BlankFreeString@\texttt{BlankFreeString}} \label{BlankFreeString} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{ResClasses}. The result of \texttt{BlankFreeString( obj );} is a composite of the functions \texttt{String( obj )} and \texttt{RemoveCharacters( obj, " " );}. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@gens := GeneratorsOfGroup( DihedralGroup(12) );| [ f1, f2, f3 ] !gapprompt@gap>| !gapinput@String( gens ); | "[ f1, f2, f3 ]" !gapprompt@gap>| !gapinput@BlankFreeString( gens ); | "[f1,f2,f3]" \end{Verbatim} } } } \chapter{\textcolor{Chapter }{Number\texttt{\symbol{45}}theoretic functions}}\label{chap-number} \logpage{[ 4, 0, 0 ]} \hyperdef{L}{X86E71C1687F2D0AD}{} { \section{\textcolor{Chapter }{Functions for integers}}\label{sec-integers} \logpage{[ 4, 1, 0 ]} \hyperdef{L}{X7D33B5B17BF785CA}{} { \subsection{\textcolor{Chapter }{AllSmoothIntegers (for two integers)}} \logpage{[ 4, 1, 1 ]}\nobreak \hyperdef{L}{X8191A031788AC7C0}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AllSmoothIntegers({\mdseries\slshape maxp, maxn})\index{AllSmoothIntegers@\texttt{AllSmoothIntegers}!for two integers} \label{AllSmoothIntegers:for two integers} }\hfill{\scriptsize (function)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AllSmoothIntegers({\mdseries\slshape L, maxp})\index{AllSmoothIntegers@\texttt{AllSmoothIntegers}!for a list and an integer} \label{AllSmoothIntegers:for a list and an integer} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{RCWA}. \index{smooth integer} The function \texttt{AllSmoothIntegers(\mbox{\texttt{\mdseries\slshape maxp}},\mbox{\texttt{\mdseries\slshape maxn}})} returns the list of all positive integers less than or equal to \mbox{\texttt{\mdseries\slshape maxn}} whose prime factors are all in the list $L = \{p ~|~ p \leqslant maxp, p~\mbox{prime} \}$. In the alternative form, when $L$ is a list of primes, the function returns the list of all positive integers whose prime factors lie in $L$. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@AllSmoothIntegers( 3, 1000 );| [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96, 108, 128, 144, 162, 192, 216, 243, 256, 288, 324, 384, 432, 486, 512, 576, 648, 729, 768, 864, 972 ] !gapprompt@gap>| !gapinput@AllSmoothIntegers( [5,11,17], 1000 );| [ 1, 5, 11, 17, 25, 55, 85, 121, 125, 187, 275, 289, 425, 605, 625, 935 ] !gapprompt@gap>| !gapinput@Length( last );| 16 !gapprompt@gap>| !gapinput@List( [3..20], n -> Length( AllSmoothIntegers( [5,11,17], 10^n ) ) );| [ 16, 29, 50, 78, 114, 155, 212, 282, 359, 452, 565, 691, 831, 992, 1173, 1374, 1595, 1843 ] \end{Verbatim} } \subsection{\textcolor{Chapter }{AllProducts}} \logpage{[ 4, 1, 2 ]}\nobreak \hyperdef{L}{X78BE6B8B878D250D}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AllProducts({\mdseries\slshape L, k})\index{AllProducts@\texttt{AllProducts}} \label{AllProducts} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{RCWA}. The command \texttt{AllProducts(\mbox{\texttt{\mdseries\slshape L}},\mbox{\texttt{\mdseries\slshape k}})} returns the list of all products of \mbox{\texttt{\mdseries\slshape k}} entries of the list{\nobreakspace}\mbox{\texttt{\mdseries\slshape L}}. Note that every ordering of the entries is used so that, in the commuting case, there are bound to be repetitions. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@AllProducts([1..4],3); | [ 1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16, 2, 4, 6, 8, 4, 8, 12, 16, 6, 12, 18, 24, 8, 16, 24, 32, 3, 6, 9, 12, 6, 12, 18, 24, 9, 18, 27, 36, 12, 24, 36, 48, 4, 8, 12, 16, 8, 16, 24, 32, 12, 24, 36, 48, 16, 32, 48, 64 ] !gapprompt@gap>| !gapinput@Set(last); | [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 64 ] !gapprompt@gap>| !gapinput@AllProducts( [(1,2,3),(2,3,4)], 2 );| [ (2,4,3), (1,2)(3,4), (1,3)(2,4), (1,3,2) ] \end{Verbatim} } \subsection{\textcolor{Chapter }{RestrictedPartitionsWithoutRepetitions}} \logpage{[ 4, 1, 3 ]}\nobreak \hyperdef{L}{X845F46E579CEA43F}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{RestrictedPartitionsWithoutRepetitions({\mdseries\slshape n, S})\index{RestrictedPartitionsWithoutRepetitions@\texttt{Restricted}\-\texttt{Partitions}\-\texttt{Without}\-\texttt{Repetitions}} \label{RestrictedPartitionsWithoutRepetitions} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{RCWA}. For a positive integer \mbox{\texttt{\mdseries\slshape n}} and a set of positive integers \mbox{\texttt{\mdseries\slshape S}}, this function returns the list of partitions of \mbox{\texttt{\mdseries\slshape n}} into distinct elements of \mbox{\texttt{\mdseries\slshape S}}. Unlike \texttt{RestrictedPartitions}, no repetitions are allowed. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@RestrictedPartitions( 20, [4..10] );| [ [ 4, 4, 4, 4, 4 ], [ 5, 5, 5, 5 ], [ 6, 5, 5, 4 ], [ 6, 6, 4, 4 ], [ 7, 5, 4, 4 ], [ 7, 7, 6 ], [ 8, 4, 4, 4 ], [ 8, 6, 6 ], [ 8, 7, 5 ], [ 8, 8, 4 ], [ 9, 6, 5 ], [ 9, 7, 4 ], [ 10, 5, 5 ], [ 10, 6, 4 ], [ 10, 10 ] ] !gapprompt@gap>| !gapinput@RestrictedPartitionsWithoutRepetitions( 20, [4..10] );| [ [ 10, 6, 4 ], [ 9, 7, 4 ], [ 9, 6, 5 ], [ 8, 7, 5 ] ] !gapprompt@gap>| !gapinput@RestrictedPartitionsWithoutRepetitions( 10^2, List([1..10], n->n^2 ) );| [ [ 100 ], [ 64, 36 ], [ 49, 25, 16, 9, 1 ] ] \end{Verbatim} } \subsection{\textcolor{Chapter }{NextProbablyPrimeInt}} \logpage{[ 4, 1, 4 ]}\nobreak \hyperdef{L}{X81708BF4858505E8}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NextProbablyPrimeInt({\mdseries\slshape n})\index{NextProbablyPrimeInt@\texttt{NextProbablyPrimeInt}} \label{NextProbablyPrimeInt} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{RCWA}. The function \texttt{NextProbablyPrimeInt(\mbox{\texttt{\mdseries\slshape n}})} does the same as \texttt{NextPrimeInt(\mbox{\texttt{\mdseries\slshape n}})} except that for reasons of performance it tests numbers only for \texttt{IsProbablyPrimeInt(\mbox{\texttt{\mdseries\slshape n}})} instead of \texttt{IsPrimeInt(\mbox{\texttt{\mdseries\slshape n}})}. For large \mbox{\texttt{\mdseries\slshape n}}, this function is much faster than \texttt{NextPrimeInt(\mbox{\texttt{\mdseries\slshape n}})} \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@n := 2^251;| 3618502788666131106986593281521497120414687020801267626233049500247285301248 !gapprompt@gap>| !gapinput@NextProbablyPrimeInt( n );| 3618502788666131106986593281521497120414687020801267626233049500247285301313 !gapprompt@gap>| !gapinput@NextPrimeInt( n ); # same result, just faster| 3618502788666131106986593281521497120414687020801267626233049500247285301313 \end{Verbatim} } \subsection{\textcolor{Chapter }{PrimeNumbersIterator}} \logpage{[ 4, 1, 5 ]}\nobreak \hyperdef{L}{X8021EEE5787FCA37}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PrimeNumbersIterator({\mdseries\slshape [chunksize]})\index{PrimeNumbersIterator@\texttt{PrimeNumbersIterator}} \label{PrimeNumbersIterator} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{RCWA}. This function returns an iterator which runs over the prime numbers in ascending order; it takes an optional argument \texttt{chunksize} which specifies the length of the interval which is sieved in one go (the default is $10^7$), and which can be used to balance runtime vs. memory consumption. It is assumed that \texttt{chunksize} is larger than any gap between two consecutive primes within the range one intends to run the iterator over. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@iter := PrimeNumbersIterator();;| !gapprompt@gap>| !gapinput@for i in [1..100] do p := NextIterator(iter); od;| !gapprompt@gap>| !gapinput@p;| 541 !gapprompt@gap>| !gapinput@sum := 0;;| !gapprompt@gap>| !gapinput@## "prime number race" 1 vs. 3 mod 4| !gapprompt@gap>| !gapinput@for p in PrimeNumbersIterator() do | !gapprompt@>| !gapinput@ if p <> 2 then sum := sum + E(4)^(p-1); fi;| !gapprompt@>| !gapinput@ if sum > 0 then break; fi;| !gapprompt@>| !gapinput@ od;| !gapprompt@gap>| !gapinput@p;| 26861 \end{Verbatim} } } } \chapter{\textcolor{Chapter }{Groups and homomorphisms}}\label{chap-groups} \logpage{[ 5, 0, 0 ]} \hyperdef{L}{X8171DAF2833FF728}{} { \section{\textcolor{Chapter }{Functions for groups}}\label{sec-groups} \logpage{[ 5, 1, 0 ]} \hyperdef{L}{X7E21E6D285E6B12C}{} { \subsection{\textcolor{Chapter }{Comm}} \logpage{[ 5, 1, 1 ]}\nobreak \hyperdef{L}{X80761843831B468E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Comm({\mdseries\slshape L})\index{Comm@\texttt{Comm}} \label{Comm} }\hfill{\scriptsize (operation)}}\\ This method has been transferred from package \textsf{ResClasses}. It provides a method for \texttt{Comm} when the argument is a list (enclosed in square brackets), and calls the function \texttt{LeftNormedComm}. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@Comm( [ (1,2), (2,3) ] );| (1,2,3) !gapprompt@gap>| !gapinput@Comm( [(1,2),(2,3),(3,4),(4,5),(5,6)] );| (1,5,6) !gapprompt@gap>| !gapinput@Comm(Comm(Comm(Comm((1,2),(2,3)),(3,4)),(4,5)),(5,6)); ## the same| (1,5,6) \end{Verbatim} } \subsection{\textcolor{Chapter }{IsCommuting}} \logpage{[ 5, 1, 2 ]}\nobreak \hyperdef{L}{X803A050C7A183CCC}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsCommuting({\mdseries\slshape a, b})\index{IsCommuting@\texttt{IsCommuting}} \label{IsCommuting} }\hfill{\scriptsize (operation)}}\\ This function has been transferred from package \textsf{ResClasses}. It tests whether two elements in a group commute. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@D12 := DihedralGroup( 12 );| !gapprompt@gap>| !gapinput@SetName( D12, "D12" ); | !gapprompt@gap>| !gapinput@a := D12.1;; b := D12.2;; | !gapprompt@gap>| !gapinput@IsCommuting( a, b );| false \end{Verbatim} } \subsection{\textcolor{Chapter }{ListOfPowers}} \logpage{[ 5, 1, 3 ]}\nobreak \hyperdef{L}{X87A8F01286548037}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ListOfPowers({\mdseries\slshape g, exp})\index{ListOfPowers@\texttt{ListOfPowers}} \label{ListOfPowers} }\hfill{\scriptsize (operation)}}\\ This function has been transferred from package \textsf{RCWA}. The operation \texttt{ListOfPowers(g,exp)} returns the list $[g,g^2,...,g^{exp}]$ of powers of the element $g$. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@ListOfPowers( 2, 20 );| [ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 ] !gapprompt@gap>| !gapinput@ListOfPowers( (1,2,3)(4,5), 12 );| [ (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), (), (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), () ] !gapprompt@gap>| !gapinput@ListOfPowers( D12.2, 6 );| [ f2, f3, f2*f3, f3^2, f2*f3^2, of ... ] \end{Verbatim} } \subsection{\textcolor{Chapter }{GeneratorsAndInverses}} \logpage{[ 5, 1, 4 ]}\nobreak \hyperdef{L}{X820B71307E41BEE5}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{GeneratorsAndInverses({\mdseries\slshape G})\index{GeneratorsAndInverses@\texttt{GeneratorsAndInverses}} \label{GeneratorsAndInverses} }\hfill{\scriptsize (operation)}}\\ This function has been transferred from package \textsf{RCWA}. This operation returns a list containing the generators of $G$ followed by the inverses of these generators. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@GeneratorsAndInverses( D12 );| [ f1, f2, f3, f1, f2*f3^2, f3^2 ] !gapprompt@gap>| !gapinput@GeneratorsAndInverses( SymmetricGroup(5) ); | [ (1,2,3,4,5), (1,2), (1,5,4,3,2), (1,2) ] \end{Verbatim} } \subsection{\textcolor{Chapter }{UpperFittingSeries}} \logpage{[ 5, 1, 5 ]}\nobreak \hyperdef{L}{X84CF95227F9D562F}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{UpperFittingSeries({\mdseries\slshape G})\index{UpperFittingSeries@\texttt{UpperFittingSeries}} \label{UpperFittingSeries} }\hfill{\scriptsize (attribute)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{LowerFittingSeries({\mdseries\slshape G})\index{LowerFittingSeries@\texttt{LowerFittingSeries}} \label{LowerFittingSeries} }\hfill{\scriptsize (attribute)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{FittingLength({\mdseries\slshape G})\index{FittingLength@\texttt{FittingLength}} \label{FittingLength} }\hfill{\scriptsize (attribute)}}\\ These three functions have been transferred from package \textsf{ResClasses}. \index{Fitting series} The upper and lower Fitting series and the Fitting length of a solvable group are described here: \href{https://en.wikipedia.org/wiki/Fitting_length} {\texttt{https://en.wikipedia.org/wiki/Fitting{\textunderscore}length}}. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@upp:= UpperFittingSeries( D12 );;| !gapprompt@gap>| !gapinput@List( upp, StructureDescription );| [ "1", "C6", "D12" ] !gapprompt@gap>| !gapinput@low:= LowerFittingSeries( D12 );;| !gapprompt@gap>| !gapinput@List( low, StructureDescription );| [ "D12", "C3", "1" ] !gapprompt@gap>| !gapinput@FittingLength( D12 );| 2 !gapprompt@gap>| !gapinput@S4 := SymmetricGroup( 4 );;| !gapprompt@gap>| !gapinput@UpperFittingSeries( S4 );| [ Group(()), Group([ (1,2)(3,4), (1,4)(2,3) ]), Group([ (2,4,3), (1,2)(3,4) ]), Group([ (3,4), (2,4,3), (1,2)(3,4) ]) ] !gapprompt@gap>| !gapinput@List( last, StructureDescription );| [ "1", "C2 x C2", "A4", "S4" ] !gapprompt@gap>| !gapinput@LowerFittingSeries( S4 );| [ Sym( [ 1 .. 4 ] ), Alt( [ 1 .. 4 ] ), Group([ (1,4)(2,3), (1,2)(3,4) ]), Group(()) ] !gapprompt@gap>| !gapinput@List( last, StructureDescription );| [ "S4", "A4", "C2 x C2", "1" ] !gapprompt@gap>| !gapinput@FittingLength( S4);| 3 \end{Verbatim} } } \section{\textcolor{Chapter }{Left Cosets for Groups}}\label{sec-leftcosets} \logpage{[ 5, 2, 0 ]} \hyperdef{L}{X7FE4848B7DE6B3FD}{} { \subsection{\textcolor{Chapter }{LeftCoset}} \logpage{[ 5, 2, 1 ]}\nobreak \hyperdef{L}{X8340B4537F17DCD3}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{LeftCoset({\mdseries\slshape g, U})\index{LeftCoset@\texttt{LeftCoset}} \label{LeftCoset} }\hfill{\scriptsize (operation)}}\\ Since \textsf{GAP} uses right actions by default, the library contains the operation \texttt{RightCoset(U,g)} for constructing the right coset $Ug$ of a subgroup $U \leq G$ and an element $g \in G$. It has been noted in the reference manual that, by inverting all the elements in $Ug$, the left coset $g^{-1}U$ is obtained. Just for the sake of completeness, from August 2022 this package provides the operation \texttt{LeftCoset(g,U)} for constructing the left coset $gU$. Users are strongly recommended to continue to use \texttt{RightCoset} for all serious calculations, since left cosets have a much simpler implementation and do not behave exactly like right cosets. The methods for left cosets which are provided generally work by converting $gU$ to $Ug^{-1}$; applying the equivalent method for right cosets; and, if necessary, converting back again to left cosets. $G$ acts on left cosets by \texttt{OnLeftInverse}: $(gU)^{g_0} = g_0^{-1}*(gU) = (g_0^{-1}g)U$. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@a4 := Group( (1,2,3), (2,3,4) );; SetName( a4, "a4" );| !gapprompt@gap>| !gapinput@k4 := Group( (1,2)(3,4), (1,3)(2,4) );; SetName( k4, "k4" );| !gapprompt@gap>| !gapinput@rc := RightCosets( a4, k4 );| [ RightCoset(k4,()), RightCoset(k4,(2,3,4)), RightCoset(k4,(2,4,3)) ] !gapprompt@gap>| !gapinput@lc := LeftCosets( a4, k4 );| [ LeftCoset((),k4), LeftCoset((2,4,3),k4), LeftCoset((2,3,4),k4) ] !gapprompt@gap>| !gapinput@AsSet( lc[2] );| [ (2,4,3), (1,2,3), (1,3,4), (1,4,2) ] !gapprompt@gap>| !gapinput@LeftCoset( (1,4,2), k4 ) = lc[2];| true !gapprompt@gap>| !gapinput@Representative( lc[2] );| (2,4,3) !gapprompt@gap>| !gapinput@ActingDomain( lc[2] );| k4 !gapprompt@gap>| !gapinput@(1,4,3) in lc[3];| true !gapprompt@gap>| !gapinput@(1,2,3)*lc[2] = lc[3];| true !gapprompt@gap>| !gapinput@lc[2]^(1,3,2) = lc[3];| true \end{Verbatim} } \subsection{\textcolor{Chapter }{Inverse}}\label{subsec-inverse} \logpage{[ 5, 2, 2 ]} \hyperdef{L}{X793E48267EF5FD77}{} { The inverse of the left coset $gU$ is the right coset $Ug^{-1}$, and conversely. This is an abuse of the attribute \texttt{Inverse}, since the standard requirement, that $x*x^{-1}$ is an identity, does not hold. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@Inverse( rc[3] ) = lc[3];| true !gapprompt@gap>| !gapinput@Inverse( lc[2] ) = rc[2];| true \end{Verbatim} } } \section{\textcolor{Chapter }{Functions for group homomorphisms}}\label{sec-homomorphisms} \logpage{[ 5, 3, 0 ]} \hyperdef{L}{X80A512877F515DE7}{} { \subsection{\textcolor{Chapter }{EpimorphismByGenerators}} \logpage{[ 5, 3, 1 ]}\nobreak \hyperdef{L}{X80C9A0B583FEA7B9}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{EpimorphismByGenerators({\mdseries\slshape G, H})\index{EpimorphismByGenerators@\texttt{EpimorphismByGenerators}} \label{EpimorphismByGenerators} }\hfill{\scriptsize (operation)}}\\ This function has been transferred from package \textsf{RCWA}. It constructs a group homomorphism which maps the generators of $G$ to those of $H$. Its intended use is when $G$ is a free group, and a warning is printed when this is not the case. Note that anything may happen if the resulting map is not a homomorphism! \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@G := Group( (1,2,3), (3,4,5), (5,6,7), (7,8,9) );;| !gapprompt@gap>| !gapinput@phi := EpimorphismByGenerators( FreeGroup("a","b","c","d"), G );| [ a, b, c, d ] -> [ (1,2,3), (3,4,5), (5,6,7), (7,8,9) ] !gapprompt@gap>| !gapinput@PreImagesRepresentativeNC( phi, (1,2,3,4,5,6,7,8,9) );| d*c*b*a !gapprompt@gap>| !gapinput@a := G.1;; b := G.2;; c := G.3;; d := G.4;;| !gapprompt@gap>| !gapinput@d*c*b*a;| (1,2,3,4,5,6,7,8,9) !gapprompt@gap>| !gapinput@## note that it is easy to produce nonsense: | !gapprompt@gap>| !gapinput@epi := EpimorphismByGenerators( Group((1,2,3)), Group((8,9)) );| Warning: calling GroupHomomorphismByImagesNC without checks [ (1,2,3) ] -> [ (8,9) ] !gapprompt@gap>| !gapinput@IsGroupHomomorphism( epi );| true !gapprompt@gap>| !gapinput@Image( epi, (1,2,3) ); | () !gapprompt@gap>| !gapinput@Image( epi, (1,3,2) );| (8,9) \end{Verbatim} } \subsection{\textcolor{Chapter }{Pullback}} \logpage{[ 5, 3, 2 ]}\nobreak \hyperdef{L}{X7C705F2A79F8E43C}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Pullback({\mdseries\slshape hom1, hom2})\index{Pullback@\texttt{Pullback}} \label{Pullback} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PullbackInfo({\mdseries\slshape G})\index{PullbackInfo@\texttt{PullbackInfo}} \label{PullbackInfo} }\hfill{\scriptsize (attribute)}}\\ If $\phi_1 : G_1 \to H$ and $\phi_2 : G_2 \to H$ are two group homomorphisms with the same range, then their \emph{pullback} is the subgroup of $G_1 \times G_2$ consisting of those elements $(g_1,g_2)$ such that $\phi_1 g_1 = \phi_2 g_2$. The attribute \texttt{PullbackInfo} of a pullback group \texttt{P} is similar to \texttt{DirectProductInfo} for a direct product of groups. Its value is a record with the following components: \begin{description} \item[{\texttt{directProduct}}] the direct product $G_1 \times G_2$, and \item[{\texttt{projections}}] a list with the two projections onto $G_1$ and $G_2$. \end{description} There are no embeddings in this record, but it is possible to use the embeddings into the direct product, see \texttt{Embedding} (\textbf{Reference: Embedding}). \begin{Verbatim}[commandchars=@|C,fontsize=\small,frame=single,label=Example] @gapprompt|gap>C @gapinput|s4 := Group( (1,2),(2,3),(3,4) );;C @gapprompt|gap>C @gapinput|s3 := Group( (5,6),(6,7) );;C @gapprompt|gap>C @gapinput|c3 := Subgroup( s3, [ (5,6,7) ] );;C @gapprompt|gap>C @gapinput|f := GroupHomomorphismByImages( s4, s3, C @gapprompt|>C @gapinput| [(1,2),(2,3),(3,4)], [(5,6),(6,7),(5,6)] );; C @gapprompt|gap>C @gapinput|i := GroupHomomorphismByImages( c3, s3, [(5,6,7)], [(5,6,7)] );; C @gapprompt|gap>C @gapinput|Pfi := Pullback( f, i );C Group([ (2,3,4)(5,7,6), (1,2)(3,4) ]) @gapprompt|gap>C @gapinput|StructureDescription( Pfi );C "A4" @gapprompt|gap>C @gapinput|info := PullbackInfo( Pfi );C rec( directProduct := Group([ (1,2), (2,3), (3,4), (5,6,7) ]), projections := [ [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (2,3,4), (1,2)(3,4) ], [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (5,7,6), () ] ] ) @gapprompt|gap>C @gapinput|g := (1,2,3)(5,6,7);; C @gapprompt|gap>C @gapinput|ImageElm( info!.projections[1], g );C (1,2,3) @gapprompt|gap>C @gapinput|ImageElm( info!.projections[2], g );C (5,6,7) @gapprompt|gap>C @gapinput|dp := info!.directProduct;; C @gapprompt|gap>C @gapinput|a := ImageElm( Embedding( dp, 1 ), (1,4,3) );; C @gapprompt|gap>C @gapinput|b := ImageElm( Embedding( dp, 2 ), (5,7,6) );; C @gapprompt|gap>C @gapinput|a*b in Pfi;C true \end{Verbatim} } \subsection{\textcolor{Chapter }{CentralProduct}} \logpage{[ 5, 3, 3 ]}\nobreak \hyperdef{L}{X78DD2C617B992BE2}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{CentralProduct({\mdseries\slshape G1, G2, Z1, Phi})\index{CentralProduct@\texttt{CentralProduct}} \label{CentralProduct} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{CentralProductInfo({\mdseries\slshape G})\index{CentralProductInfo@\texttt{CentralProductInfo}} \label{CentralProductInfo} }\hfill{\scriptsize (attribute)}}\\ This function was added by Thomas Breuer, following discussions with Hongyi Zhao (see \href{https://github.com/gap-packages/hap/issues/73} {\texttt{https://github.com/gap\texttt{\symbol{45}}packages/hap/issues/73}}). Let \mbox{\texttt{\mdseries\slshape G1}} and \mbox{\texttt{\mdseries\slshape G2}} be two groups, \mbox{\texttt{\mdseries\slshape Z1}} be a central subgroup of \mbox{\texttt{\mdseries\slshape G1}}, and \mbox{\texttt{\mdseries\slshape Phi}} be an isomorphism from \mbox{\texttt{\mdseries\slshape Z1}} to a central subgroup of \mbox{\texttt{\mdseries\slshape G2}}. The \emph{central product} defined by these arguments is the factor group of the direct product of \mbox{\texttt{\mdseries\slshape G1}} and \mbox{\texttt{\mdseries\slshape G2}} by the central subgroup $\{ (z, (\mbox{\texttt{\mdseries\slshape Phi}}(z))^{-1}) : z \in \mbox{\texttt{\mdseries\slshape Z1}} \}$. The attribute \texttt{CentralProductInfo} of a group $G$ that has been created by \texttt{CentralProduct} is similar to \texttt{PullbackInfo} (\ref{PullbackInfo}) for pullback groups. Its value is a record with the following components. \begin{description} \item[{\texttt{projection}}] the epimorphism from the direct product of \mbox{\texttt{\mdseries\slshape G1}} and \mbox{\texttt{\mdseries\slshape G2}} to $G$, and \item[{\texttt{phi}}] the map \mbox{\texttt{\mdseries\slshape Phi}}. \end{description} Note that one can access the direct product as the \texttt{Source} (\textbf{Reference: Source}) value of the \texttt{projection} map, and one can access \mbox{\texttt{\mdseries\slshape G1}} and \mbox{\texttt{\mdseries\slshape G2}} as the two embeddings of this direct product, see \texttt{Embedding} (\textbf{Reference: Embedding}). \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@g1 := DihedralGroup( 8 );| !gapprompt@gap>| !gapinput@c1 := Centre( g1 );| Group([ f3 ]) !gapprompt@gap>| !gapinput@cp1 := CentralProduct( g1, g1, c1, IdentityMapping( c1 ) );| Group([ f1, f2, f5, f3, f4, f5 ]) !gapprompt@gap>| !gapinput@IdGroup( cp1 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) );| true !gapprompt@gap>| !gapinput@g2 := QuaternionGroup( 8 );| !gapprompt@gap>| !gapinput@c2 := Centre( g2 );| Group([ y2 ]) !gapprompt@gap>| !gapinput@cp2 := CentralProduct( g2, g2, c2, IdentityMapping( c2 ) );| Group([ f1, f2, f5, f3, f4, f5 ]) !gapprompt@gap>| !gapinput@IdGroup( cp2 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) );| true !gapprompt@gap>| !gapinput@info2 := CentralProductInfo( cp2 );| rec( phi := IdentityMapping( Group([ y2 ]) ), projection := [ f1, f2, f3, f4, f5, f6 ] -> [ f1, f2, f5, f3, f4, f5 ] ) !gapprompt@gap>| !gapinput@Source( Embedding( Source( info2.projection ), 1 ) ) = g2;| true \end{Verbatim} } \subsection{\textcolor{Chapter }{IdempotentEndomorphisms}} \logpage{[ 5, 3, 4 ]}\nobreak \hyperdef{L}{X801038CB808FC956}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IdempotentEndomorphisms({\mdseries\slshape G})\index{IdempotentEndomorphisms@\texttt{IdempotentEndomorphisms}} \label{IdempotentEndomorphisms} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IdempotentEndomorphismsData({\mdseries\slshape G})\index{IdempotentEndomorphismsData@\texttt{IdempotentEndomorphismsData}} \label{IdempotentEndomorphismsData} }\hfill{\scriptsize (attribute)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IdempotentEndomorphismsWithImage({\mdseries\slshape genG, R})\index{IdempotentEndomorphismsWithImage@\texttt{IdempotentEndomorphismsWithImage}} \label{IdempotentEndomorphismsWithImage} }\hfill{\scriptsize (operation)}}\\ An endomorphism $f\colon G \to G$ is idempotent if $f^2 = f$. It has an image $R \leq G$, is the identity map when restricted to $R$, and has a kernel $N$ which has trivial intersection with $R$ and has size $|G|/|R|$. The operation \texttt{IdempotentEndomorphismsWithImage(genG,R)} returns a list of the images of the generating set \texttt{genG} of a group $G$ under the idempotent endomorphisms with image $R$. The attribute \texttt{IdempotentEndomorphismsData(G)} returns a record \texttt{data} with fields \texttt{data.gens}, a fixed generating set for $G$, and \texttt{data.images} a list of the non\texttt{\symbol{45}}empty outputs of \texttt{IdempotentEndomorphismsWithImage(genG,R)} obtained by iterating over all subgroups $R$ of $G$. The operation \texttt{IdempotentEndomorphisms(G)} returns the list of these mappings obtained using \texttt{IdempotentEndomorphismsData(G)}. The first of these is the zero map, the last is the identity. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@gens := [ (1,2,3,4), (1,2)(3,4) ];; | !gapprompt@gap>| !gapinput@d8 := Group( gens );;| !gapprompt@gap>| !gapinput@SetName( d8, "d8" );| !gapprompt@gap>| !gapinput@c2 := Subgroup( d8, [ (2,4) ] );;| !gapprompt@gap>| !gapinput@SortedList( IdempotentEndomorphismsWithImage( gens, c2 ) );| [ [ (), (2,4) ], [ (2,4), () ] ] !gapprompt@gap>| !gapinput@data:= IdempotentEndomorphismsData( d8 );;| !gapprompt@gap>| !gapinput@data.images[1];| [ [ (), () ] ] !gapprompt@gap>| !gapinput@List( data.images, Length );| [ 1, 2, 2, 2, 2, 1 ] !gapprompt@gap>| !gapinput@all:= IdempotentEndomorphisms( d8 );;| !gapprompt@gap>| !gapinput@Length( all );| 10 !gapprompt@gap>| !gapinput@all[1];| [ (1,2,3,4), (1,2)(3,4) ] -> [ (), () ] !gapprompt@gap>| !gapinput@Size( Image( all[1] ) );| 1 !gapprompt@gap>| !gapinput@Last( all ) = IdentityMapping( d8 );| true \end{Verbatim} } The quaternion group \texttt{q8} is an example of a group with a tail: there is only one subgroup in the lattice which covers the identity subgroup. The only idempotent isomorphisms of such groups are the identity mapping and the zero mapping because the only pairs $N,R$ are the whole group and the identity subgroup. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@q8 := QuaternionGroup( 8 );;| !gapprompt@gap>| !gapinput@IdempotentEndomorphisms( q8 );| [ [ x, y ] -> [ of ..., of ... ], [ x, y ] -> [ x, y ] ] \end{Verbatim} \subsection{\textcolor{Chapter }{DirectProductOfFunctions}} \logpage{[ 5, 3, 5 ]}\nobreak \hyperdef{L}{X81FA9E6C7F3B9238}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DirectProductOfFunctions({\mdseries\slshape G, H, f1, f2})\index{DirectProductOfFunctions@\texttt{DirectProductOfFunctions}} \label{DirectProductOfFunctions} }\hfill{\scriptsize (operation)}}\\ Given group homomorphisms $f_1 : G_1 \to G_2$ and $f_2 : H_1 \to H_2$, this operation return the product homomorphism $f_1 \times f_2 : G_1 \times G_2 \to H_1 \times H_2$. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@c4 := Group( (1,2,3,4) );; | !gapprompt@gap>| !gapinput@c2 := Group( (5,6) );; | !gapprompt@gap>| !gapinput@f1 := GroupHomomorphismByImages( c4, c2, [(1,2,3,4)], [(5,6)] );;| !gapprompt@gap>| !gapinput@c3 := Group( (1,2,3) );; | !gapprompt@gap>| !gapinput@c6 := Group( (1,2,3,4,5,6) );; | !gapprompt@gap>| !gapinput@f2 := GroupHomomorphismByImages( c3, c6, [(1,2,3)], [(1,3,5)(2,4,6)] );; | !gapprompt@gap>| !gapinput@c4c3 := DirectProduct( c4, c3 ); | Group([ (1,2,3,4), (5,6,7) ]) !gapprompt@gap>| !gapinput@c2c6 := DirectProduct( c2, c6 ); | Group([ (1,2), (3,4,5,6,7,8) ]) !gapprompt@gap>| !gapinput@f := DirectProductOfFunctions( c4c3, c2c6, f1, f2 ); | [ (1,2,3,4), (5,6,7) ] -> [ (1,2), (3,5,7)(4,6,8) ] !gapprompt@gap>| !gapinput@ImageElm( f, (1,4,3,2)(5,7,6) ); | (1,2)(3,7,5)(4,8,6) \end{Verbatim} } \subsection{\textcolor{Chapter }{DirectProductOfAutomorphismGroups}} \logpage{[ 5, 3, 6 ]}\nobreak \hyperdef{L}{X7CB2D5F27F4182AF}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DirectProductOfAutomorphismGroups({\mdseries\slshape A1, A2})\index{DirectProductOfAutomorphismGroups@\texttt{DirectProductOfAutomorphismGroups}} \label{DirectProductOfAutomorphismGroups} }\hfill{\scriptsize (operation)}}\\ Let $A_1,A_2$ be groups of automorphism of groups $G_1,G_2$ respectively. The output of this function is a group $A_1 \times A_2$ of automorphisms of $G_1 \times G_2$. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@c9 := Group( (1,2,3,4,5,6,7,8,9) );; | !gapprompt@gap>| !gapinput@ac9 := AutomorphismGroup( c9 );; | !gapprompt@gap>| !gapinput@q8 := QuaternionGroup( IsPermGroup, 8 );;| !gapprompt@gap>| !gapinput@aq8 := AutomorphismGroup( q8 );;| !gapprompt@gap>| !gapinput@A := DirectProductOfAutomorphismGroups( ac9, aq8 );| !gapprompt@gap>| !gapinput@genA := GeneratorsOfGroup( A );;| !gapprompt@gap>| !gapinput@G := Source( genA[1] );| Group([ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13) (14,15,16,17) ]) !gapprompt@gap>| !gapinput@a := genA[1]*genA[5]; | [ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13)(14,15,16,17) ] -> [ (1,3,5,7,9,2,4,6,8), (10,16,12,14)(11,15,13,17), (10,11,12,13)(14,15,16,17) ] !gapprompt@gap>| !gapinput@ImageElm( a, (1,9,8,7,6,5,4,3,2)(10,14,12,16)(11,17,13,15) );| (1,8,6,4,2,9,7,5,3)(10,16,12,14)(11,15,13,17) \end{Verbatim} } } } \chapter{\textcolor{Chapter }{Matrices}}\label{chap-matrix} \logpage{[ 6, 0, 0 ]} \hyperdef{L}{X812CCAB278643A59}{} { \section{\textcolor{Chapter }{Some operations for matrices}}\label{sec-matrix-ops} \logpage{[ 6, 1, 0 ]} \hyperdef{L}{X802118FB7C94D6BA}{} { \subsection{\textcolor{Chapter }{DirectSumDecompositionMatrices}} \logpage{[ 6, 1, 1 ]}\nobreak \hyperdef{L}{X787B89237E1398B6}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DirectSumDecompositionMatrices({\mdseries\slshape M})\index{DirectSumDecompositionMatrices@\texttt{DirectSumDecompositionMatrices}} \label{DirectSumDecompositionMatrices} }\hfill{\scriptsize (operation)}}\\ In June 2023 Hongyi Zhao asked in the Forum for a function to implement matrix decomposition into blocks. Such a function was then provided by Pedro Garc{\a'\i}a\texttt{\symbol{45}}S{\a'a}nchez. Hongyi Zhao then requested that the function be added to \textsf{Utils}. What is provided here is a revised version of the original solution, returning a list of decompositions. This function is a partial inverse to the undocumented library operation \texttt{DirectSumMat}. So if $L$ is the list of diagonal decompositions of a matrix $M$ then each entry in $L$ is a list of matrices, and the direct sum of each of these lists is equal to the original $M$. In the following examples, $M_6$ is an obvious direct sum with $3$ blocks. $M_4$ is an example with three decompositions, while $M_8 = M_4 \oplus M_4$ has $16$ decompositions (not listed). \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@M6 := [ [1,2,0,0,0,0], [3,4,0,0,0,0], [5,6,0,0,0,0], | !gapprompt@>| !gapinput@ [0,0,9,0,0,0], [0,0,0,1,2,3], [0,0,0,4,5,6] ];;| !gapprompt@gap>| !gapinput@Display( M6 );| [ [ 1, 2, 0, 0, 0, 0 ], [ 3, 4, 0, 0, 0, 0 ], [ 5, 6, 0, 0, 0, 0 ], [ 0, 0, 9, 0, 0, 0 ], [ 0, 0, 0, 1, 2, 3 ], [ 0, 0, 0, 4, 5, 6 ] ] !gapprompt@gap>| !gapinput@L6 := DirectSumDecompositionMatrices( M6 );| [ [ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ], [ [ 9 ] ], [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] ] ] !gapprompt@gap>| !gapinput@M4 := [ [0,3,0,0], [0,0,0,0], [0,0,0,0], [0,0,4,0] ];;| !gapprompt@gap>| !gapinput@Display( M4 );| [ [ 0, 3, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 4, 0 ] ] !gapprompt@gap>| !gapinput@L4 := DirectSumDecompositionMatrices( M4 );| [ [ [ [ 0, 3 ] ], [ [ 0, 0 ], [ 0, 0 ], [ 4, 0 ] ] ], [ [ [ 0, 3 ], [ 0, 0 ] ], [ [ 0, 0 ], [ 4, 0 ] ] ], [ [ [ 0, 3 ], [ 0, 0 ], [ 0, 0 ] ], [ [ 4, 0 ] ] ] ] !gapprompt@gap>| !gapinput@for L in L4 do | !gapprompt@>| !gapinput@ A := DirectSumMat( L );; | !gapprompt@>| !gapinput@ if ( A = M4 ) then Print( "yes, A = M4\n" ); fi; | !gapprompt@>| !gapinput@ od;| yes, A = M4 yes, A = M4 yes, A = M4 !gapprompt@gap>| !gapinput@M8 := DirectSumMat( M4, M4 );; | !gapprompt@gap>| !gapinput@Display( M8 );| [ [ 0, 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, 4, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 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, 4, 0 ] ] !gapprompt@gap>| !gapinput@L8 := DirectSumDecompositionMatrices( M8 );;| !gapprompt@gap>| !gapinput@Length( L8 ); | 16 \end{Verbatim} The current method does not, however, catch all possible decompositions. In the following example the matrix $M_5$ has its third row and third column extirely zero, and the only decomposition found has a $[0]$ factor. There are clearly two $2$\texttt{\symbol{45}}factor decompositions with a $2$\texttt{\symbol{45}}by\texttt{\symbol{45}}$3$ and a $3$\texttt{\symbol{45}}by\texttt{\symbol{45}}$2$ factor, but these are not found at present. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@M5 := [ [1,2,0,0,0], [3,4,0,0,0], [0,0,0,0,0],| !gapprompt@>| !gapinput@ [0,0,0,6,7], [0,0,0,8,9] ];;| !gapprompt@gap>| !gapinput@Display(M5);| [ [ 1, 2, 0, 0, 0 ], [ 3, 4, 0, 0, 0 ], [ 0, 0, 0, 0, 0 ], [ 0, 0, 0, 6, 7 ], [ 0, 0, 0, 8, 9 ] ] !gapprompt@gap>| !gapinput@L5 := DirectSumDecompositionMatrices( M5 ); | [ [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 0 ] ], [ [ 6, 7 ], [ 8, 9 ] ] ] ] \end{Verbatim} } } } \chapter{\textcolor{Chapter }{Iterators}}\label{chap-iterator} \logpage{[ 7, 0, 0 ]} \hyperdef{L}{X85A3F00985453F95}{} { \section{\textcolor{Chapter }{Some iterators for groups and their isomorphisms}}\label{sec-group-iters} \logpage{[ 7, 1, 0 ]} \hyperdef{L}{X7BB5350081B27D17}{} { \index{Iterators} The motivation for adding these operations is partly to give a simple example of an iterator for a list that does not yet exist, and need not be created. \subsection{\textcolor{Chapter }{AllIsomorphismsIterator}} \logpage{[ 7, 1, 1 ]}\nobreak \hyperdef{L}{X7F8B54D1806C762D}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AllIsomorphismsIterator({\mdseries\slshape G, H})\index{AllIsomorphismsIterator@\texttt{AllIsomorphismsIterator}} \label{AllIsomorphismsIterator} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AllIsomorphismsNumber({\mdseries\slshape G, H})\index{AllIsomorphismsNumber@\texttt{AllIsomorphismsNumber}} \label{AllIsomorphismsNumber} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AllIsomorphisms({\mdseries\slshape G, H})\index{AllIsomorphisms@\texttt{AllIsomorphisms}} \label{AllIsomorphisms} }\hfill{\scriptsize (operation)}}\\ The main \textsf{GAP} library contains functions producing complete lists of group homomorphisms such as \texttt{AllHomomorphisms}; \texttt{AllEndomorphisms} and \texttt{AllAutomorphisms}. Here we add the missing \texttt{AllIsomorphisms(G,H)} for a list of isomorphisms from $G$ to $H$. The method is simple \texttt{\symbol{45}}\texttt{\symbol{45}} find one isomorphism $G \to H$ and compose this with all the automorphisms of $G$. In all these cases it may not be desirable to construct a list of homomorphisms, but just implement an iterator, and that is what is done here. The operation \texttt{AllIsomorphismsNumber} returns the number of isomorphisms iterated over (this is, of course, just the order of the automorphisms group). The operation \texttt{AllIsomorphisms} produces the list or isomorphisms. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@G := SmallGroup( 6,1);; | !gapprompt@gap>| !gapinput@iter := AllIsomorphismsIterator( G, s3 );;| !gapprompt@gap>| !gapinput@NextIterator( iter );| [ f1, f2 ] -> [ (6,7), (5,6,7) ] !gapprompt@gap>| !gapinput@n := AllIsomorphismsNumber( G, s3 );| 6 !gapprompt@gap>| !gapinput@AllIsomorphisms( G, s3 );| [ [ f1, f2 ] -> [ (6,7), (5,6,7) ], [ f1, f2 ] -> [ (5,7), (5,6,7) ], [ f1, f2 ] -> [ (5,6), (5,7,6) ], [ f1, f2 ] -> [ (6,7), (5,7,6) ], [ f1, f2 ] -> [ (5,7), (5,7,6) ], [ f1, f2 ] -> [ (5,6), (5,6,7) ] ] !gapprompt@gap>| !gapinput@iter := AllIsomorphismsIterator( G, s3 );;| !gapprompt@gap>| !gapinput@for h in iter do Print( ImageElm( h, G.1 ) = (6,7), ", " ); od;| true, false, false, true, false, false, \end{Verbatim} } \subsection{\textcolor{Chapter }{AllSubgroupsIterator}} \logpage{[ 7, 1, 2 ]}\nobreak \hyperdef{L}{X831DA5AE8437578F}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AllSubgroupsIterator({\mdseries\slshape G})\index{AllSubgroupsIterator@\texttt{AllSubgroupsIterator}} \label{AllSubgroupsIterator} }\hfill{\scriptsize (operation)}}\\ The manual entry for the operation \texttt{AllSubgroups} states that it is only intended to be used on small examples in a classroom situation. Access to all subgroups was required by the \textsf{XMod} package, so this iterator was introduced here. It used the operations \texttt{LatticeSubgroups(G)} and \texttt{ConjugacyClassesSubgroups(lat)}, and then iterates over the entries in these classes. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@c3c3 := Group( (1,2,3), (4,5,6) );; | !gapprompt@gap>| !gapinput@iter := AllSubgroupsIterator( c3c3 );| !gapprompt@gap>| !gapinput@while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od;| Group( () ) Group( [ (4,5,6) ] ) Group( [ (1,2,3) ] ) Group( [ (1,2,3)(4,5,6) ] ) Group( [ (1,3,2)(4,5,6) ] ) Group( [ (4,5,6), (1,2,3) ] ) \end{Verbatim} } } \section{\textcolor{Chapter }{Operations on iterators}}\label{sec-iter-ops} \logpage{[ 7, 2, 0 ]} \hyperdef{L}{X85413EED812C6497}{} { This section considers ways of producing an iterator from one or more iterators. It may be that operations equivalent to these are available elsewhere in the library \texttt{\symbol{45}}\texttt{\symbol{45}} if so, the ones here can be removed in due course. \subsection{\textcolor{Chapter }{CartesianIterator}} \logpage{[ 7, 2, 1 ]}\nobreak \hyperdef{L}{X87395A9181A35301}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{CartesianIterator({\mdseries\slshape iter1, iter2})\index{CartesianIterator@\texttt{CartesianIterator}} \label{CartesianIterator} }\hfill{\scriptsize (operation)}}\\ This iterator returns all pairs $[x,y]$ where $x$ is the output of a first iterator and $y$ is the output of a second iterator. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@it1 := Iterator( [ 1, 2, 3 ] );;| !gapprompt@gap>| !gapinput@it2 := Iterator( [ 4, 5, 6 ] );;| !gapprompt@gap>| !gapinput@iter := CartesianIterator( it1, it2 );;| !gapprompt@gap>| !gapinput@while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od;| [ 1, 4 ] [ 1, 5 ] [ 1, 6 ] [ 2, 4 ] [ 2, 5 ] [ 2, 6 ] [ 3, 4 ] [ 3, 5 ] [ 3, 6 ] \end{Verbatim} } \subsection{\textcolor{Chapter }{UnorderedPairsIterator}} \logpage{[ 7, 2, 2 ]}\nobreak \hyperdef{L}{X7C95E27987A812EA}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{UnorderedPairsIterator({\mdseries\slshape iter})\index{UnorderedPairsIterator@\texttt{UnorderedPairsIterator}} \label{UnorderedPairsIterator} }\hfill{\scriptsize (operation)}}\\ This operation returns pairs $[x,y]$ where $x,y$ are output from a given iterator \texttt{iter}. Unlike the output from \texttt{CartesianIterator(iter,iter)}, unordered pairs are returned. In the case $L = [1,2,3,\ldots]$ the pairs are ordered as $[1,1],[1,2],[2,2],[1,3],[2,3],[3,3],\ldots$. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@L := [6,7,8,9];;| !gapprompt@gap>| !gapinput@iterL := IteratorList( L );; | !gapprompt@gap>| !gapinput@pairsL := UnorderedPairsIterator( iterL );; | !gapprompt@gap>| !gapinput@while not IsDoneIterator(pairsL) do Print(NextIterator(pairsL),"\n"); od;| [ 6, 6 ] [ 6, 7 ] [ 7, 7 ] [ 6, 8 ] [ 7, 8 ] [ 8, 8 ] [ 6, 9 ] [ 7, 9 ] [ 8, 9 ] [ 9, 9 ] !gapprompt@gap>| !gapinput@iter4 := IteratorList( [ 4 ] );| !gapprompt@gap>| !gapinput@pairs4 := UnorderedPairsIterator(iter4);| !gapprompt@gap>| !gapinput@NextIterator( pairs4 );| [ 4, 4 ] !gapprompt@gap>| !gapinput@IsDoneIterator( pairs4 );| true \end{Verbatim} } } } \chapter{\textcolor{Chapter }{Records}}\label{chap-record} \logpage{[ 8, 0, 0 ]} \hyperdef{L}{X7AA1073C7E943DD7}{} { \section{\textcolor{Chapter }{Functions for records}}\label{sec-records} \logpage{[ 8, 1, 0 ]} \hyperdef{L}{X82B3D1D583CDF0E5}{} { \subsection{\textcolor{Chapter }{AssignGlobals}} \logpage{[ 8, 1, 1 ]}\nobreak \hyperdef{L}{X84D82EB579B2ACCD}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AssignGlobals({\mdseries\slshape rec})\index{AssignGlobals@\texttt{AssignGlobals}} \label{AssignGlobals} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{RCWA}. It assigns the record components of \mbox{\texttt{\mdseries\slshape rec}} to global variables with the same names. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@r := rec( a := 1, b := 2, c := 3 );; | !gapprompt@gap>| !gapinput@AssignGlobals( r );| The following global variables have been assigned: [ "a", "b", "c" ] !gapprompt@gap>| !gapinput@[a,b,c];| [ 1, 2, 3 ] \end{Verbatim} } } \section{\textcolor{Chapter }{Option records for functions}}\label{sec-options} \logpage{[ 8, 2, 0 ]} \hyperdef{L}{X7E6207B47B9AA30C}{} { \subsection{\textcolor{Chapter }{OptionRecordWithDefaults}} \logpage{[ 8, 2, 1 ]}\nobreak \hyperdef{L}{X8322B9377CC590D2}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{OptionRecordWithDefaults({\mdseries\slshape defaults, useroptions})\index{OptionRecordWithDefaults@\texttt{OptionRecordWithDefaults}} \label{OptionRecordWithDefaults} }\hfill{\scriptsize (function)}}\\ This functions has been transferred by Chris Jefferson from other packages. It simplifies the handling of records which are intended to be used for expressing configuration options. \mbox{\texttt{\mdseries\slshape defaults}} represents the "default record", and \mbox{\texttt{\mdseries\slshape useroptions}} lets the user give new values for values in \mbox{\texttt{\mdseries\slshape defaults}}. The function returns a record with the same component names as \mbox{\texttt{\mdseries\slshape defaults}} and which has the same values as \mbox{\texttt{\mdseries\slshape defaults}}, except for those component names in \mbox{\texttt{\mdseries\slshape useroptions}}, where the values in \mbox{\texttt{\mdseries\slshape useroptions}} are used instead. An error is given if \mbox{\texttt{\mdseries\slshape useroptions}} contains any component names not in \mbox{\texttt{\mdseries\slshape defaults}}. If \mbox{\texttt{\mdseries\slshape useroptions}} is an empty list it is treated as an empty record, and if \mbox{\texttt{\mdseries\slshape useroptions}} is a list of length $1$ containing a record, this record is used as \mbox{\texttt{\mdseries\slshape useroptions}}. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@defaults := rec( a := 1, b := 2, c := 3 );;| !gapprompt@gap>| !gapinput@OptionRecordWithDefaults( defaults, rec( a := 6) );| rec( a := 6, b := 2, c := 3 ) !gapprompt@gap>| !gapinput@OptionRecordWithDefaults( defaults, rec( b := 7, c := 8 ) );| rec( a := 1, b := 7, c := 8 ) !gapprompt@gap>| !gapinput@OptionRecordWithDefaults( defaults, [ ] );| rec( a := 1, b := 2, c := 3 ) !gapprompt@gap>| !gapinput@OptionRecordWithDefaults( defaults, [ rec( c := 8 ) ] );| rec( a := 1, b := 2, c := 8 ) !gapprompt@gap>| !gapinput@OptionRecordWithDefaults( defaults, rec( d := 9 ) );| Error, Unknown option: d !gapprompt@gap>| !gapinput@OptionRecordWithDefaults( defaults, [ rec( b := 7 ), rec( c := 8 ) ] );| Error, Too many arguments for function !gapprompt@gap>| !gapinput@OptionRecordWithDefaults( defaults, [6,7,8] );| Error, Too many arguments for function \end{Verbatim} This function is designed to support functions with optional arguments given as a variable record, of the form \texttt{function(x,y,options...)}. In the following, very contrived, example function, \texttt{PrintDimensions}, the defaults are given by the variable \texttt{order} which takes values \texttt{h}, \texttt{w} and \texttt{d} having default values $1$, $2$ and $3$. If there is a second argument, then \texttt{OptionRecordWithDefaults( order, arg[2] );} is used to change the values. These three values then determine the order in which the three dimensions are printed using a \texttt{SortParallel} command. \begin{Verbatim}[commandchars=@|A,fontsize=\small,frame=single,label=Example] @gapprompt|gap>A @gapinput|PrintDimensions := function( arg )A @gapprompt|>A @gapinput| local nargs, dim, order, V, L, len, K, i;A @gapprompt|>A @gapinput| nargs := Length( arg );A @gapprompt|>A @gapinput| dim := [ arg[1]!.height, arg[1]!.width, arg[1]!.depth ];A @gapprompt|>A @gapinput| order := rec( h := 1, w := 2, d := 3 );A @gapprompt|>A @gapinput| V := [ "height", "width", "depth" ];A @gapprompt|>A @gapinput| if ( nargs > 1 ) and IsRecord( arg[2] ) thenA @gapprompt|>A @gapinput| order := OptionRecordWithDefaults( order, arg[2] );A @gapprompt|>A @gapinput| fi;A @gapprompt|>A @gapinput| L := [ order!.h, order!.w, order!.d ];A @gapprompt|>A @gapinput| len := Length( L );A @gapprompt|>A @gapinput| K := [ 1..len ];A @gapprompt|>A @gapinput| SortParallel( L, K );A @gapprompt|>A @gapinput| Print( "dimensions: " );A @gapprompt|>A @gapinput| Print( V[K[1]], " = ", dim[K[1]], ", " );A @gapprompt|>A @gapinput| Print( V[K[2]], " = ", dim[K[2]], ", " );A @gapprompt|>A @gapinput| Print( V[K[3]], " = ", dim[K[3]], "\n" );A @gapprompt|>A @gapinput|end;;A \end{Verbatim} In the example below the first call to \texttt{PrintDimensions} has just one parameter, \texttt{mydim}, so the default order is used. In the second call, alternate values for \texttt{h}, \texttt{w} and \texttt{d} are given, causing the width to be printed first, and then the depth and height. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@mydim := rec( height := 45, width := 31, depth := 17 ); | rec( depth := 17, height := 45, width := 31 ) !gapprompt@gap>| !gapinput@PrintDimensions( mydim );| dimensions: height = 45, width = 31, depth = 17 !gapprompt@gap>| !gapinput@PrintDimensions( mydim, rec( h:=3, w:=1, d:=2 ) );| dimensions: width = 31, depth = 17, height = 45 \end{Verbatim} } } } \chapter{\textcolor{Chapter }{Web Downloads}}\label{chap-download} \logpage{[ 9, 0, 0 ]} \hyperdef{L}{X815B0C4B7EBE6E1E}{} { The \texttt{Download} operation has been written by Thomas Breuer, incorporating a number of suggestions from Max Horn, for version 0.77 of \textsf{Utils}. It implements downloading a file from within \textsf{GAP}. It can use the \textsf{IO} or \textsf{curlInterface} packages, or \emph{wget} or \emph{curl}, if installed, and it can be extended with other download methods quite easily. It is envisaged that, once other packages have started to use it, and any problems have been addressed, that the functions will be transferred to the main \textsf{GAP} library. \section{\textcolor{Chapter }{Functions for downloading files from the web}}\label{sec-download} \logpage{[ 9, 1, 0 ]} \hyperdef{L}{X8758CB7F79EFB6ED}{} { \subsection{\textcolor{Chapter }{Download}} \logpage{[ 9, 1, 1 ]}\nobreak \hyperdef{L}{X7A7438AE8448635E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Download({\mdseries\slshape url[, opt]})\index{Download@\texttt{Download}} \label{Download} }\hfill{\scriptsize (function)}}\\ This function downloads the file with the web address \mbox{\texttt{\mdseries\slshape url}}, which must be a string. The result is a record which has at least the component \texttt{success}, with value \texttt{true} if the download was successful and \texttt{false} otherwise. In the former case, the component \texttt{result} is bound, whose value is a string that contains the contents of the downloaded file. In the latter case, the component \texttt{error} is bound, whose value is a string that describes the problem. The function calls the methods stored in the global list \texttt{Download{\textunderscore}Methods} until one of them is successful. Currently there are methods based on the \textsf{GAP} functions \texttt{DownloadURL} (\textbf{curl: DownloadURL}) and \texttt{SingleHTTPRequest} (\textbf{IO: SingleHTTPRequest}), and methods based on the external programs \texttt{wget} and \texttt{curl}. An optional record \mbox{\texttt{\mdseries\slshape opt}} can be given. The following components are supported. \begin{description} \item[{\texttt{maxTime}}] If this component is bound then its value must be a nonnegative integer $n$, meaning that the function gives up after $n$ seconds. A zero value of $n$ means that no timeout is set, the method will never give up in this case. The default for $n$ is given by the value of the user preference \texttt{DownloadMaxTime} (see \ref{subsec-DownloadMaxTime}). \item[{\texttt{target}}] If this component is bound then its value must be a string that is a local filename, and the function writes the downloaded contents to this file; the returned record does not have a \texttt{result} component in this case. \item[{\texttt{verifyCert}}] If this component is bound and has the value \texttt{false} then those download methods that are based on \texttt{curl} or \texttt{wget} will omit the check of the server's certificate. The same effect is achieved for all \texttt{Download} calls by setting the user preference \texttt{DownloadVerifyCertificate} (see \ref{subsec-DownloadVerifyCertificate}) to \texttt{false} and omitting the \texttt{verifyCert} component from \mbox{\texttt{\mdseries\slshape opt}}. \end{description} \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@url:= "https://www.gap-system.org/index.html";;| !gapprompt@gap>| !gapinput@res1:= Download( url );;| !gapprompt@gap>| !gapinput@res1.success;| true !gapprompt@gap>| !gapinput@IsBound( res1.result ) and IsString( res1.result );| true !gapprompt@gap>| !gapinput@res2:= Download( Concatenation( url, "xxx" ) );;| !gapprompt@gap>| !gapinput@res2.success;| false !gapprompt@gap>| !gapinput@IsBound( res2.error ) and IsString( res2.error );| true \end{Verbatim} } \subsection{\textcolor{Chapter }{User preference \texttt{DownloadVerifyCertificate}}}\label{subsec-DownloadVerifyCertificate} \logpage{[ 9, 1, 2 ]} \hyperdef{L}{X85182BA486E3C2AA}{} { \index{DownloadVerifyCertificate@\texttt{DownloadVerifyCertificate}} The value \texttt{true} (the default) means that the server's certificate is checked in calls of \texttt{Download} (\ref{Download}), such that nothing gets downloaded if the certificate is invalid. If the value is \texttt{false} then download methods are supposed to omit the check of the server's certificate (this may not be supported by all download methods). One can set the value of the preference to be \texttt{val} via \texttt{SetUserPreference} (\textbf{Reference: SetUserPreference}), by calling \texttt{SetUserPreference( "utils", "DownloadVerifyCertificate", val )}, and access the current value via \texttt{UserPreference} (\textbf{Reference: UserPreference}), by calling \texttt{UserPreference( "utils", "DownloadVerifyCertificate" )}. We recommend leaving this preference at its default value \texttt{true}. Sometimes it can be necessary to change it, e.g. to work around issues with old operating systems which may not be able to correctly verify new certificates. In general it is better to update such a system, but if that is not an option, then disabling certificate checks may be a good last resort. } \subsection{\textcolor{Chapter }{User preference \texttt{DownloadMaxTime}}}\label{subsec-DownloadMaxTime} \logpage{[ 9, 1, 3 ]} \hyperdef{L}{X79E10E5B83EF929F}{} { \index{DownloadMaxTime@\texttt{DownloadMaxTime}} The value \texttt{0} (the default) means that no timeout is set in calls of \texttt{Download} (\ref{Download}). If the value is a positive integer $n$ then those download methods that support a timeout will give up after $n$ seconds. One can set the value of the preference to be \texttt{val} via \texttt{SetUserPreference} (\textbf{Reference: SetUserPreference}), by calling \texttt{SetUserPreference( "utils", "DownloadMaxTime", val )}, and access the current value via \texttt{UserPreference} (\textbf{Reference: UserPreference}), by calling \texttt{UserPreference( "utils", "DownloadMaxTime" )}. } } } \chapter{\textcolor{Chapter }{Generalized Straight Line Programs}}\label{chap-gslp} \logpage{[ 10, 0, 0 ]} \hyperdef{L}{X8314837E85D3D052}{} { The functions described in this chapter have been written by Thomas Breuer, they are available since \textsf{Utils} 0.94. \emph{Generalized straight line programs} (in the following abbreviated as \emph{gslps}) are a generalization of the straight line programs that are described in the \textsf{GAP} library, see (\textbf{Reference: Straight Line Programs}). Like the latter objects, gslps describe an efficient way for evaluating an abstract word at concrete generators. The difference is that gslps can be built from existing (generalized) straight line programs, whereas a straight line program is given by an explicit list of instructions (see \texttt{LinesOfStraightLineProgram} (\textbf{Reference: LinesOfStraightLineProgram})). So the advantages of using a gslp instead of constructing an equivalent straight line program (see \texttt{EquivalentStraightLineProgram} (\ref{EquivalentStraightLineProgram})) are that \begin{itemize} \item available objects (the building blocks of the gslp) are reused, \item the internal structure of the gslp is retained (one can access the building blocks if one wants), and \item in the evaluation of a gslp, the intermediate results that arise in a building block of the gslp can be garbage collected as soon as the evaluation of this building block has finished. \end{itemize} A gslp in \textsf{GAP} is represented by an object in the category \texttt{IsGeneralizedStraightLineProgram} (\ref{IsGeneralizedStraightLineProgram}). This object has exactly one of the following forms. \begin{itemize} \item It is a straight line program, that is, it lies in the category \texttt{IsStraightLineProgram} (\textbf{Reference: IsStraightLineProgram}), and evaluation at some group elements is defined by \texttt{ResultOfStraightLineProgram} (\textbf{Reference: ResultOfStraightLineProgram}). \item It is of ``union'' kind, that is, the defining data are a nonempty list $l$ of gslps, and evaluation at some group elements means to evaluate the gslps in $l$ at these group elements, and to return the concatenation of the results. \item It is of ``compose'' kind, that is, the defining data are a nonempty list $l$ of gslps, and evaluation at some group elements means to evaluate $l[1]$ at these elements, then to evaluate $l[2]$ at the result of the first evaluation, and so on, and to return the last result. \end{itemize} Here are two typical situations where gslps arise. In both cases, suppose that a list $l$ of standard generators for a group $G$ is given. \begin{enumerate} \item Suppose that we know a straight line program for computing generators $l'$ of a maximal subgroup $M$ of $G$ from $l$. For example, these data may be taken from the \textsf{ATLAS} of Group Representations \cite{AGRv3}. If $M$ is also a group for which the \textsf{ATLAS} of Group Representations contains generators and straight line programs, we may be interested in computing standard generators $l''$ for $M$ from $l'$. For that, a second straight line program may be needed, and it makes sense to encode the computation of $l''$ from $l$ via a gslp of ``compose'' kind. \item Suppose that we are in fact interested in a downward extension $H$ of $G$, and that $\pi$ is the natural epimorphism from $H$ to $G$, which maps a list $L$, say, of standard generators of $H$ to $l$. Then the above gslp for $G$ can be applied to $L$, but the result $L'$ may generate a proper subgroup of $\pi^{-1}(M)$ because some part of the kernel of $\pi$ is missing. A list $K$ of generators of the kernel of $\pi$ can be described by a straight line program that takes $L$ as its input, and it makes sense to encode the computation of the concatenation of $L'$ and $K$ from $L$ via a gslp of ``union'' kind. \end{enumerate} Gslps can be constructed using \texttt{GeneralizedStraightLineProgram} (\ref{GeneralizedStraightLineProgram:for kind and list}). Defining attributes for gslps are \texttt{NrInputsOfGeneralizedStraightLineProgram} (\ref{NrInputsOfGeneralizedStraightLineProgram}) and \texttt{DataOfGeneralizedStraightLineProgram} (\ref{DataOfGeneralizedStraightLineProgram}). The probably most interesting operation for gslps is \texttt{ResultOfGeneralizedStraightLineProgram} (\ref{ResultOfGeneralizedStraightLineProgram}). Currently we do not intend to provide methods applicable to generalized straight line programs for all operations that are defined for straight line programs. For example, there is no \texttt{IntermediateResultOfSLP} (\textbf{Reference: IntermediateResultOfSLP}) method for generalized straight line programs. Special methods applicable to gslps are installed for the operations \texttt{IsInternallyConsistent} (\ref{IsInternallyConsistent:for generalized straight line program}), \texttt{ViewString} (\textbf{Reference: ViewString}), and \texttt{String} (\textbf{Reference: String}). \section{\textcolor{Chapter }{Functions for Generalized Straight Line Programs}}\label{sec-gslp} \logpage{[ 10, 1, 0 ]} \hyperdef{L}{X7D1B00C979C8AEFD}{} { \subsection{\textcolor{Chapter }{IsGeneralizedStraightLineProgram}} \logpage{[ 10, 1, 1 ]}\nobreak \hyperdef{L}{X7D6F31797B8C3452}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsGeneralizedStraightLineProgram({\mdseries\slshape obj})\index{IsGeneralizedStraightLineProgram@\texttt{IsGeneralizedStraightLineProgram}} \label{IsGeneralizedStraightLineProgram} }\hfill{\scriptsize (category)}}\\ Each generalized straight line program in \textsf{GAP} lies in the category \texttt{IsGeneralizedStraightLineProgram}. Examples are straight line programs, that is, objects in the category \texttt{IsStraightLineProgram} (\textbf{Reference: IsStraightLineProgram}). \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@gslp:= GeneralizedStraightLineProgram( "union",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );| !gapprompt@gap>| !gapinput@IsGeneralizedStraightLineProgram( gslp );| true !gapprompt@gap>| !gapinput@slp:= StraightLineProgram( [[[1,2]]], 1 );| !gapprompt@gap>| !gapinput@IsGeneralizedStraightLineProgram( slp );| true !gapprompt@gap>| !gapinput@IsGeneralizedStraightLineProgram( [ slp, slp ] );| false \end{Verbatim} } \subsection{\textcolor{Chapter }{GeneralizedStraightLineProgram}}\logpage{[ 10, 1, 2 ]} \hyperdef{L}{X8503408985150E37}{} { \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{GeneralizedStraightLineProgram({\mdseries\slshape lines[, nrgens]})\index{GeneralizedStraightLineProgram@\texttt{GeneralizedStraightLineProgram}!for a list of lines (and the number of generators)} \label{GeneralizedStraightLineProgram:for a list of lines (and the number of generators)} }\hfill{\scriptsize (function)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{GeneralizedStraightLineProgram({\mdseries\slshape kind, list})\index{GeneralizedStraightLineProgram@\texttt{GeneralizedStraightLineProgram}!for kind and list} \label{GeneralizedStraightLineProgram:for kind and list} }\hfill{\scriptsize (function)}}\\ In the first form, \mbox{\texttt{\mdseries\slshape lines}} must be a list of lists that defines a unique straight line program (see{\nobreakspace}\texttt{IsStraightLineProgram} (\textbf{Reference: IsStraightLineProgram})); in this case \texttt{GeneralizedStraightLineProgram} delegates to \texttt{StraightLineProgram} (\textbf{Reference: StraightLineProgram for a list of lines (and the number of generators)}). In the second form, \mbox{\texttt{\mdseries\slshape kind}} must be one of the strings \texttt{"union"} or \texttt{"compose"}, and \mbox{\texttt{\mdseries\slshape list}} must be a nonempty list such that each of its entries is either a gslp or a list $l$, say, such that \texttt{CallFuncList} (\textbf{Reference: CallFuncList}) applied to \texttt{GeneralizedStraightLineProgram} and $l$ returns a gslp. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@GeneralizedStraightLineProgram( [[[1,2]]], 1 );| !gapprompt@gap>| !gapinput@GeneralizedStraightLineProgram( "union",| !gapprompt@>| !gapinput@[ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );| !gapprompt@gap>| !gapinput@GeneralizedStraightLineProgram( "compose",| !gapprompt@>| !gapinput@[ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );| \end{Verbatim} } \subsection{\textcolor{Chapter }{DataOfGeneralizedStraightLineProgram}} \logpage{[ 10, 1, 3 ]}\nobreak \hyperdef{L}{X7C5BD3777DBBB390}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DataOfGeneralizedStraightLineProgram({\mdseries\slshape gslp})\index{DataOfGeneralizedStraightLineProgram@\texttt{Data}\-\texttt{Of}\-\texttt{Generalized}\-\texttt{Straight}\-\texttt{Line}\-\texttt{Program}} \label{DataOfGeneralizedStraightLineProgram} }\hfill{\scriptsize (attribute)}}\\ For a generalized straight line program \mbox{\texttt{\mdseries\slshape gslp}} that is \emph{not} a straight line program, \texttt{DataOfGeneralizedStraightLineProgram} returns a list of length two, the first entry being either \texttt{"union"} or \texttt{"compose"} and the second being the list of defining generalized straight line programs. If \mbox{\texttt{\mdseries\slshape gslp}} is a straight line program then this attribute is not set in \mbox{\texttt{\mdseries\slshape gslp}}. There is no default method to compute the value if it is not stored. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@gslp:= GeneralizedStraightLineProgram( "union",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );| !gapprompt@gap>| !gapinput@DataOfGeneralizedStraightLineProgram( gslp );| [ "union", [ , ] ] \end{Verbatim} } \subsection{\textcolor{Chapter }{NrInputsOfGeneralizedStraightLineProgram}} \logpage{[ 10, 1, 4 ]}\nobreak \hyperdef{L}{X7F47B79F7D7A51AC}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NrInputsOfGeneralizedStraightLineProgram({\mdseries\slshape gslp})\index{NrInputsOfGeneralizedStraightLineProgram@\texttt{NrInputs}\-\texttt{Of}\-\texttt{Generalized}\-\texttt{Straight}\-\texttt{Line}\-\texttt{Program}} \label{NrInputsOfGeneralizedStraightLineProgram} }\hfill{\scriptsize (attribute)}}\\ For a generalized straight line program \mbox{\texttt{\mdseries\slshape gslp}}, this function returns the number of generators that are needed as input. If \mbox{\texttt{\mdseries\slshape gslp}} is a straight line program then it may be necessary that the value is set in the construction of \mbox{\texttt{\mdseries\slshape gslp}}, see \texttt{NrInputsOfStraightLineProgram} (\textbf{Reference: NrInputsOfStraightLineProgram}). If \mbox{\texttt{\mdseries\slshape gslp}} is not a straight line program then the value is determined by the (generalized) straight line programs from which \mbox{\texttt{\mdseries\slshape gslp}} is constructed. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@NrInputsOfGeneralizedStraightLineProgram(| !gapprompt@>| !gapinput@ GeneralizedStraightLineProgram( "union",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) );| 1 \end{Verbatim} In order to avoid the introduction of unnecessary filters, we define \texttt{NrInputsOfGeneralizedStraightLineProgram} just as a synonym of \texttt{NrInputsOfStraightLineProgram} (\textbf{Reference: NrInputsOfStraightLineProgram}). } \subsection{\textcolor{Chapter }{NrOutputsOfGeneralizedStraightLineProgram}} \logpage{[ 10, 1, 5 ]}\nobreak \hyperdef{L}{X7EFDD9F07F3AF218}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NrOutputsOfGeneralizedStraightLineProgram({\mdseries\slshape gslp})\index{NrOutputsOfGeneralizedStraightLineProgram@\texttt{NrOutputs}\-\texttt{Of}\-\texttt{Generalized}\-\texttt{Straight}\-\texttt{Line}\-\texttt{Program}} \label{NrOutputsOfGeneralizedStraightLineProgram} }\hfill{\scriptsize (attribute)}}\\ For a generalized straight line program \mbox{\texttt{\mdseries\slshape gslp}}, this function returns the number of elements returned by \texttt{ResultOfGeneralizedStraightLineProgram} (\ref{ResultOfGeneralizedStraightLineProgram}) when \mbox{\texttt{\mdseries\slshape gslp}} is evaluated. Note that the \textsf{GAP} library does not define a corresponding attribute for straight line programs. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@NrOutputsOfGeneralizedStraightLineProgram(| !gapprompt@>| !gapinput@ GeneralizedStraightLineProgram( "union",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) );| 2 !gapprompt@gap>| !gapinput@NrOutputsOfGeneralizedStraightLineProgram(| !gapprompt@>| !gapinput@ GeneralizedStraightLineProgram( "compose",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) );| 1 \end{Verbatim} } \subsection{\textcolor{Chapter }{ResultOfGeneralizedStraightLineProgram}} \logpage{[ 10, 1, 6 ]}\nobreak \hyperdef{L}{X785C69E2789B3985}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ResultOfGeneralizedStraightLineProgram({\mdseries\slshape gslp, gens})\index{ResultOfGeneralizedStraightLineProgram@\texttt{Result}\-\texttt{Of}\-\texttt{Generalized}\-\texttt{Straight}\-\texttt{Line}\-\texttt{Program}} \label{ResultOfGeneralizedStraightLineProgram} }\hfill{\scriptsize (operation)}}\\ \texttt{ResultOfGeneralizedStraightLineProgram} evaluates the generalized straight line program (see{\nobreakspace}\texttt{IsGeneralizedStraightLineProgram} (\ref{IsGeneralizedStraightLineProgram})) \mbox{\texttt{\mdseries\slshape gslp}} at the group elements in the list \mbox{\texttt{\mdseries\slshape gens}}, as follows. \begin{itemize} \item If \mbox{\texttt{\mdseries\slshape gslp}} is a straight line program then the value of \texttt{ResultOfStraightLineProgram} (\textbf{Reference: ResultOfStraightLineProgram}) is returned. \item If \mbox{\texttt{\mdseries\slshape gslp}} is of ``union'' kind then \texttt{ResultOfGeneralizedStraightLineProgram} is applied to each of the involved generalized straight line programs, with second argument \mbox{\texttt{\mdseries\slshape gens}}, and the concatenation of the results is returned. \item If \mbox{\texttt{\mdseries\slshape gslp}} is of ``compose'' kind then \texttt{ResultOfGeneralizedStraightLineProgram} is first called with the first involved generalized straight line program and \mbox{\texttt{\mdseries\slshape gens}}, then the operation is called with the second involved generalized straight line program and the result of this call, and so on; the last such result is returned. \end{itemize} \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@gens:= [ (1,2,3,4,5,6) ];;| !gapprompt@gap>| !gapinput@gslp:= GeneralizedStraightLineProgram( "union",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );| !gapprompt@gap>| !gapinput@ResultOfGeneralizedStraightLineProgram( gslp, gens );| [ (1,3,5)(2,4,6), (1,4)(2,5)(3,6) ] !gapprompt@gap>| !gapinput@gslp:= GeneralizedStraightLineProgram( "compose",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );| !gapprompt@gap>| !gapinput@ResultOfGeneralizedStraightLineProgram( gslp, gens );| [ () ] \end{Verbatim} In order to avoid the introduction of unnecessary operations, we define \texttt{ResultOfGeneralizedStraightLineProgram} just as a synonym of \texttt{ResultOfStraightLineProgram} (\textbf{Reference: ResultOfStraightLineProgram}). } \subsection{\textcolor{Chapter }{EquivalentStraightLineProgram}} \logpage{[ 10, 1, 7 ]}\nobreak \hyperdef{L}{X81E725087E481727}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{EquivalentStraightLineProgram({\mdseries\slshape gslp})\index{EquivalentStraightLineProgram@\texttt{EquivalentStraightLineProgram}} \label{EquivalentStraightLineProgram} }\hfill{\scriptsize (attribute)}}\\ For a generalized straight line program \mbox{\texttt{\mdseries\slshape gslp}}, \texttt{EquivalentStraightLineProgram} returns a straight line program such that evaluating \mbox{\texttt{\mdseries\slshape gslp}} and this straight line program with \texttt{ResultOfGeneralizedStraightLineProgram} (\ref{ResultOfGeneralizedStraightLineProgram}) yields the same output, for any list of input elements. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@gslp:= GeneralizedStraightLineProgram( "union",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );| !gapprompt@gap>| !gapinput@slp:= EquivalentStraightLineProgram( gslp );| !gapprompt@gap>| !gapinput@Display( slp );| # input: r:= [ g1 ]; # program: # return values: [ r[1]^2, r[1]^3 ] !gapprompt@gap>| !gapinput@gslp:= GeneralizedStraightLineProgram( "compose",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );| !gapprompt@gap>| !gapinput@slp:= EquivalentStraightLineProgram( gslp );| !gapprompt@gap>| !gapinput@Display( slp );| # input: r:= [ g1 ]; # program: r[2]:= r[1]^2; r[1]:= r[2]; # return values: [ r[1]^3 ] \end{Verbatim} } \subsection{\textcolor{Chapter }{IsInternallyConsistent (for generalized straight line program)}} \logpage{[ 10, 1, 8 ]}\nobreak \hyperdef{L}{X85E5CF147DAD5FA3}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IsInternallyConsistent({\mdseries\slshape gslp})\index{IsInternallyConsistent@\texttt{IsInternallyConsistent}!for generalized straight line program} \label{IsInternallyConsistent:for generalized straight line program} }\hfill{\scriptsize (method)}}\\ For a generalized straight line program \mbox{\texttt{\mdseries\slshape gslp}}, it is checked whether all (generalized) straight line programs from which \mbox{\texttt{\mdseries\slshape gslp}} is built are internally consistent, and whether their numbers of inputs and outputs are consistent and compatible with the numbers of inputs and outputs of \mbox{\texttt{\mdseries\slshape gslp}}. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@gslp:= GeneralizedStraightLineProgram( "union",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );;| !gapprompt@gap>| !gapinput@IsInternallyConsistent( gslp );| true !gapprompt@gap>| !gapinput@gslp:= GeneralizedStraightLineProgram( "compose",| !gapprompt@>| !gapinput@ [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );;| !gapprompt@gap>| !gapinput@IsInternallyConsistent( gslp );| true \end{Verbatim} } } } \chapter{\textcolor{Chapter }{Various other functions}}\label{chap-others} \logpage{[ 11, 0, 0 ]} \hyperdef{L}{X83EFC3178180D918}{} { \section{\textcolor{Chapter }{File operations}}\label{sec-log2html} \logpage{[ 11, 1, 0 ]} \hyperdef{L}{X81A0A4FF842B039B}{} { \subsection{\textcolor{Chapter }{Log2HTML}} \logpage{[ 11, 1, 1 ]}\nobreak \hyperdef{L}{X7B7ECADF85F748BE}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Log2HTML({\mdseries\slshape filename})\index{Log2HTML@\texttt{Log2HTML}} \label{Log2HTML} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{RCWA}. This function converts the \textsf{GAP} logfile \texttt{filename} to HTML. It appears that the logfile should be in your current directory. The extension of the input file must be \texttt{*.log}. The name of the output file is the same as the one of the input file except that the extension \texttt{*.log} is replaced by \texttt{*.html}. There is a sample CSS file in \texttt{utils/doc/gaplog.css}, which you can adjust to your taste. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@LogTo( "triv.log" );| !gapprompt@gap>| !gapinput@a := 33^5;| 39135393 !gapprompt@gap>| !gapinput@LogTo(); | !gapprompt@gap>| !gapinput@Log2HTML( "triv.log" ); | \end{Verbatim} } } \section{\textcolor{Chapter }{{\LaTeX} strings}}\label{sec-latex} \logpage{[ 11, 2, 0 ]} \hyperdef{L}{X84D2922D87EDE9E9}{} { \subsection{\textcolor{Chapter }{IntOrInfinityToLaTeX}} \logpage{[ 11, 2, 1 ]}\nobreak \hyperdef{L}{X85F11FFA7F036669}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{IntOrInfinityToLaTeX({\mdseries\slshape n})\index{IntOrInfinityToLaTeX@\texttt{IntOrInfinityToLaTeX}} \label{IntOrInfinityToLaTeX} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{ResClasses}. \texttt{IntOrInfinityToLaTeX} returns the {\LaTeX} string for \mbox{\texttt{\mdseries\slshape n}}. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@IntOrInfinityToLaTeX( 10^3 );| "1000" !gapprompt@gap>| !gapinput@IntOrInfinityToLaTeX( infinity );| "\\infty" \end{Verbatim} } \subsection{\textcolor{Chapter }{LaTeXStringFactorsInt}} \logpage{[ 11, 2, 2 ]}\nobreak \hyperdef{L}{X7DC642B97CD02F4E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{LaTeXStringFactorsInt({\mdseries\slshape n})\index{LaTeXStringFactorsInt@\texttt{LaTeXStringFactorsInt}} \label{LaTeXStringFactorsInt} }\hfill{\scriptsize (function)}}\\ This function has been transferred from package \textsf{RCWA}. It returns the prime factorization of the integer $n$ as a string in {\LaTeX} format. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@LaTeXStringFactorsInt( Factorial(12) );| "2^{10} \\cdot 3^5 \\cdot 5^2 \\cdot 7 \\cdot 11" \end{Verbatim} } } \section{\textcolor{Chapter }{Conversion to ${\sf Magma}$ strings}}\label{sec-magma} \logpage{[ 11, 3, 0 ]} \hyperdef{L}{X79F021B1830B68F6}{} { \subsection{\textcolor{Chapter }{ConvertToMagmaInputString}} \logpage{[ 11, 3, 1 ]}\nobreak \hyperdef{L}{X8768D7707B4CBBD4}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ConvertToMagmaInputString({\mdseries\slshape arg})\index{ConvertToMagmaInputString@\texttt{ConvertToMagmaInputString}} \label{ConvertToMagmaInputString} }\hfill{\scriptsize (function)}}\\ The function \texttt{ConvertToMagmaInputString( obj [, str] )} attempts to output a string \texttt{s} which can be read into ${\sf Magma}$ \cite{MAGMA} so as to produce the same group in that computer algebra system. In the second form the user specifies the name of the resulting object, so that the output string has the form \texttt{"str := ..."}. When \texttt{obj} is a permutation group, the operation \texttt{PermGroupToMagmaFormat(obj)} is called. \index{PermGroupToMagmaFormat} This function has been taken from \texttt{other.gi} in the main library where it was called \texttt{MagmaInputString}. When \texttt{obj} is a pc\texttt{\symbol{45}}group, the operation \texttt{PcGroupToMagmaFormat(obj)} is called. \index{PcGroupToMagmaFormat} This function was private code of Max Horn. When \texttt{obj} is a matrix group over a finite field, the operation \texttt{MatrixGroupToMagmaFormat(obj)} is called. \index{MatrixGroupToMagmaFormat} This function is a modification of private code of Frank L{\"u}beck. Hopefully code for other types of group will be added in due course. These functions should be considered \emph{experimental}, and more testing is desirable. \begin{Verbatim}[commandchars=@AB,fontsize=\small,frame=single,label=Example] @gappromptAgap>B @gapinputA## permutation groupsB @gappromptAgap>B @gapinputAConvertToMagmaInputString( Group( (1,2,3,4,5), (3,4,5) ) );B "PermutationGroup<5|(1,2,3,4,5),\n(3,4,5)>;\n" @gappromptAgap>B @gapinputAConvertToMagmaInputString( Group( (1,2,3,4,5) ), "c5" ); B "c5 := PermutationGroup<5|(1,2,3,4,5)>;\n" @gappromptAgap>B @gapinputA## pc-groupB @gappromptAgap>B @gapinputAConvertToMagmaInputString( DihedralGroup( IsPcGroup, 10 ) );B "PolycyclicGroup< f1,f2 |\nf1^2,\nf2^5,\nf2^f1 = f2^4\n>;\n" @gappromptAgap>B @gapinputA## fp-groupB @gappromptAgap>B @gapinputAF2 := FreeGroup( 2 );;B @gappromptAgap>B @gapinputAf := F2.1;; g := F2.2;;B @gappromptAgap>B @gapinputArelq8 := [ f^4, g^4, f*g*f*g^-1, f^2*g^2 ];; B @gappromptAgap>B @gapinputAq8 := F2/relq8;; B @gappromptAgap>B @gapinputAConvertToMagmaInputString( q8 );B no conversion function yet available for fp-groups fail @gappromptAgap>B @gapinputA## matrix groupB @gappromptAgap>B @gapinputAM := GL(2,5);; Size(M); B 480 @gappromptAgap>B @gapinputAs1 := ConvertToMagmaInputString( M );B "F := GF(5);\nP := GL(2,F);\ngens := [\nP![2,0,0,1],\nP![4,1,4,0]\n];\nsub

;\n" @gappromptAgap>B @gapinputAPrint( s1 );B F := GF(5); P := GL(2,F); gens := [ P![2,0,0,1], P![4,1,4,0] ]; sub

; @gappromptAgap>B @gapinputAn1 := [ [ Z(9)^0, Z(9)^0 ], [ Z(9)^0, Z(9) ] ];;B @gappromptAgap>B @gapinputAn2 := [ [ Z(9)^0, Z(9)^3 ], [ Z(9)^4, Z(9)^2 ] ];;B @gappromptAgap>B @gapinputAN := Group( n1, n2 );; Size( N );B 5760 @gappromptAgap>B @gapinputAs2 := ConvertToMagmaInputString( N, "gpN" );;B @gappromptAgap>B @gapinputAPrint( s2 );B F := GF(3^2); P := GL(2,F); w := PrimitiveElement(F); gens := [ P![ 1, 1, 1,w^1], P![ 1,w^3, 2,w^2] ]; gpN := sub

; \end{Verbatim} } } } \chapter{\textcolor{Chapter }{Obsolete functions}}\label{chap-obsolete} \logpage{[ 12, 0, 0 ]} \hyperdef{L}{X7F561B1D803182FF}{} { \section{\textcolor{Chapter }{Operations from AutoDoc}}\label{sec-obs-folders} \logpage{[ 12, 1, 0 ]} \hyperdef{L}{X7A6BB3D084912F35}{} { The file functions \texttt{FindMatchingFiles} \index{FindMatchingFiles} and \texttt{CreateDirIfMissing} \index{CreateDirIfMissing} were copied from package \textsf{AutoDoc} where they are named \texttt{AutoDoc{\textunderscore}FindMatchingFiles} and \texttt{AutoDoc{\textunderscore}CreateDirIfMissing}. The string function \texttt{StringDotSuffix} \index{StringDotSuffix} was also copied from package \textsf{AutoDoc}, where it is named \texttt{AUTODOC{\textunderscore}GetSuffix}. \index{GetSuffix} The function \texttt{SetIfMissing} \index{SetIfMissing} was also transferred from package \textsf{AutoDoc}, where it is called \texttt{AUTODOC{\textunderscore}SetIfMissing}. It writes into a record provided the position is not yet bound. As from version 0.61, all these functions became obsolete in \textsf{Utils}, but continue to be defined in \textsf{AutoDoc}. } \section{\textcolor{Chapter }{Functions for printing}}\label{sec-obs-print} \logpage{[ 12, 2, 0 ]} \hyperdef{L}{X86F322FC7DECE36F}{} { The function \texttt{PrintOneItemPerLine} \index{PrintOneItemPerLine} was used to prints lists vertically, rather than horizontally. Since a very similar result may be achieved using the \textsf{GAP} library functions \texttt{Perform} and \texttt{Display}, this function became obsolete in version 0.61. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@s3 := SymmetricGroup( 3 );; | !gapprompt@gap>| !gapinput@L := KnownPropertiesOfObject( GeneratorsOfGroup( s3 ) );;| !gapprompt@gap>| !gapinput@Perform( L, Display );| IsFinite IsSmallList IsGeneratorsOfMagmaWithInverses IsAssociative IsGeneratorsOfSemigroup IsSubsetLocallyFiniteGroup !gapprompt@gap>| !gapinput@Perform( s3, Display ); | () (2,3) (1,3) (1,3,2) (1,2,3) (1,2) \end{Verbatim} } \section{\textcolor{Chapter }{Other obsolete functions}}\label{sec-obs-others} \logpage{[ 12, 3, 0 ]} \hyperdef{L}{X84A4F0B281FA0F94}{} { \subsection{\textcolor{Chapter }{Applicable Methods}}\label{subsec-app-meth} \logpage{[ 12, 3, 1 ]} \hyperdef{L}{X78B7D1A982BE9866}{} { The function \index{PrintApplicableMethod} \texttt{PrintApplicableMethod}, which was included in versions from 0.41 to 0.58, has been removed since it was considered superfluous. The example shows how to print out a function. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 1, 1 );| #I Searching Method for IsCyclic with 1 argument: #I Total: 8 entries #I Method 5: ``IsCyclic'' at GAPROOT/lib/grp.gi: 34 , value: 36 function( G ) ... end !gapprompt@gap>| !gapinput@Print( last );| function ( G ) if Length( GeneratorsOfGroup( G ) ) = 1 then return true; else TryNextMethod(); fi; return; end !gapprompt@gap>| !gapinput@ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 0, 3 );| function( obj ) ... end !gapprompt@gap>| !gapinput@Print( last ); | function ( obj ) <> from GAPROOT/lib/oper1.g:767 end \end{Verbatim} } \subsection{\textcolor{Chapter }{ExponentOfPrime}}\label{subsec-exponent} \logpage{[ 12, 3, 2 ]} \hyperdef{L}{X7C1AF2467FB55D79}{} { The function \texttt{ExponentOfPrime} \index{ExponentOfPrime} was originally transferred from package \textsf{RCWA}. The command \texttt{ExponentOfPrime(\mbox{\texttt{\mdseries\slshape n}},\mbox{\texttt{\mdseries\slshape p}})} returned the exponent of the prime \mbox{\texttt{\mdseries\slshape p}} in the prime factorization of \mbox{\texttt{\mdseries\slshape n}}. Since the \textsf{GAP} function \texttt{PValuation} produces the same results, and does so more quickly, this function has been made obsolete. } } } \chapter{\textcolor{Chapter }{The transfer procedure}}\label{chap-transfer} \logpage{[ 13, 0, 0 ]} \hyperdef{L}{X84AC9613842F014C}{} { We consider here the process for transferring utility functions from a package \textsf{Home} to \textsf{Utils} which has to avoid the potential problem of duplicate declarations of a function causing loading problems in \textsf{GAP}. If the functions in \textsf{Home} all have names of the form \texttt{HOME{\textunderscore}FunctionName} then, in \textsf{Utils}, these functions are likely to be renamed as \texttt{FunctionName} or something similar. In this case the problem of duplicate declarations does not arise. This is what has happened with transfers from the \textsf{AutoDoc} package. The case where the function names are unchanged is more complicated. Initially we tried out a process which allowed repeated declarations and installations of the functions being transferred. This involved additions to the main library files \texttt{global.g} and \texttt{oper.g}. Since there were misgivings about interfering in this way with basic operations such as \texttt{BIND{\textunderscore}GLOBAL}, a simpler (but slightly less convenient) process has been adopted. Using this alternative procedure, the following steps will be followed when making transfers from \textsf{Home} to \textsf{Utils}. \begin{enumerate} \item (\textsf{Home}:) Offer functions for inclusion. This may be simply done by emailing a list of functions. More usefully, email the declaration, implementation, test and documentation files, e.g.: \texttt{home.gd}, \texttt{home.gi}, \texttt{home.tst} and \texttt{home.xml}. (All active authors should be involved.) \item (\textsf{Home}:) Declare that \textsc{m.n} is the last version of \textsf{Home} to contain these functions, so that \textsc{m.n+1} (or similar) will be the first version of \textsf{Home} to have all these functions removed, and to specify \textsf{Utils} as a required package. \item (\textsf{Utils}:) Add strings \mbox{\texttt{\mdseries\slshape "home"}} and \mbox{\texttt{\mdseries\slshape "m.n"}} to the list \texttt{UtilsPackageVersions} in the file \texttt{utils/lib/start.gd}. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] UtilsPackageVersions := [ "autodoc", "2016.01.31", "resclasses", "4.2.5", "home", "m.n", ..., ... ]; \end{Verbatim} While the transfers are being made, it is essential that any new versions of \textsf{Home} should be tested with the latest version of \textsf{Utils} before they are released, so as to avoid loading failures. \item (\textsf{Utils}:) Include the function declaration and implementation sections in suitable files, enclosed within a conditional clause of the form: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] if OKtoReadFromUtils( "Home" ) then . . . . . . . . . . . . fi; \end{Verbatim} \index{OKtoReadFromUtils} The function \texttt{OKtoReadFromUtils} returns \texttt{true} only if there is an installed version of \textsf{Home} and if this version is greater than \textsc{m.n}. So, at this stage, \emph{the copied code will not be read}, and the transferred functions can only be called if \textsf{Home} has been installed. \item (\textsf{Utils}:) Add the test and documentation material to the appropriate files. The copied code can be tested by temporarily moving \textsf{Home} away from \textsf{GAP}'s package directory. \item (\textsf{Utils}:) Release a new version of \textsf{Utils} containing all the transferred material. \item (\textsf{Home}:) Edit out the declarations and implementations of all the transferred functions, and remove references to them in the manual and tests. Possibly add a note to the manual that these functions have been transferred. Add \textsf{Utils} to the list of \textsf{Home}'s required packages in \texttt{PackageInfo.g}. Release a new version of \textsf{Home}. \item (\textsf{Utils}:) In due course, when the new version(s) of \textsf{Home} are well established, it may be safe to remove the conditional clauses mentioned in item 4 above. The entry for \textsf{Home} in \texttt{UtilsPackageLists} may then be removed. \end{enumerate} Finally, a note on the procedure for testing these functions. As long as a function being transferred still exists in the \textsf{Home} package, the code will not be read from \textsf{Utils}. So, when the tests are run, it is necessary to \texttt{LoadPackage("home")} before the function is called. The file \texttt{utils/tst/testall.g} makes sure that all the necessary packages are loaded before the individual tests are called. } \def\bibname{References\logpage{[ "Bib", 0, 0 ]} \hyperdef{L}{X7A6F98FD85F02BFE}{} } \bibliographystyle{alpha} \bibliography{bib.xml} \addcontentsline{toc}{chapter}{References} \def\indexname{Index\logpage{[ "Ind", 0, 0 ]} \hyperdef{L}{X83A0356F839C696F}{} } \cleardoublepage \phantomsection \addcontentsline{toc}{chapter}{Index} \printindex \immediate\write\pagenrlog{["Ind", 0, 0], \arabic{page},} \newpage \immediate\write\pagenrlog{["End"], \arabic{page}];} \immediate\closeout\pagenrlog \end{document} utils-0.94/doc/utils.xml0000644000000000000000000000131415174515600012166 0ustar00 ] > <#Include SYSTEM "title.xml"> <#Include SYSTEM "intro.xml"> <#Include SYSTEM "print.xml"> <#Include SYSTEM "lists.xml"> <#Include SYSTEM "number.xml"> <#Include SYSTEM "groups.xml"> <#Include SYSTEM "matrix.xml"> <#Include SYSTEM "iterator.xml"> <#Include SYSTEM "record.xml"> <#Include SYSTEM "download.xml"> <#Include SYSTEM "gslp.xml"> <#Include SYSTEM "others.xml"> <#Include SYSTEM "obsolete.xml"> <#Include SYSTEM "transfer.xml"> utils-0.94/init.g0000644000000000000000000000244215174515600010655 0ustar00############################################################################# ## #W init.g GAP package `Utils' Chris Wensley ## #Y Copyright (C) 2015-2023, The GAP Group, ## if not IsBound( PreImagesRepresentativeNC ) then BindGlobal( "PreImagesRepresentativeNC", PreImagesRepresentative ); fi; if not IsBound( IsMatrixOrMatrixObj ) then BindGlobal( "IsMatrixOrMatrixObj", IsMatrix ); fi; if not IsBound( MutableCopyMatrix ) then BindGlobal( "MutableCopyMatrix", ShallowCopy ); fi; ## read the function declarations ReadPackage( "utils", "lib/start.gd" ); ReadPackage( "utils", "lib/files.gd" ); ReadPackage( "utils", "lib/groups.gd" ); ReadPackage( "utils", "lib/iterator.gd" ); ReadPackage( "utils", "lib/latex.gd" ); ReadPackage( "utils", "lib/lcset.gd" ); ReadPackage( "utils", "lib/lists.gd" ); ReadPackage( "utils", "lib/magma.gd" ); ReadPackage( "utils", "lib/maps.gd" ); ReadPackage( "utils", "lib/matrix.gd" ); ReadPackage( "utils", "lib/number.gd" ); ReadPackage( "utils", "lib/print.gd" ); ReadPackage( "utils", "lib/record.gd" ); ReadPackage( "utils", "lib/string.gd" ); ReadPackage( "utils", "lib/gslp.gd" ); if not IsBound( Download ) then ReadPackage( "utils", "lib/download.gd" ); BindGlobal("DOWNLOAD_FROM_UTILS", true); fi; utils-0.94/lib/0000755000000000000000000000000015174515600010306 5ustar00utils-0.94/lib/download.gd0000644000000000000000000000321515174515600012432 0ustar00############################################################################## ## #W download.gd GAP4 package `Utils' Thomas Breuer ## #Y Copyright (C) 2022, The GAP Group ############################################################################# ## This function is intended to be used instead of similar ones from ## various packages (AtlasRep, FactInt, GAPDoc, PackageManager, ## StandardFF, ...) ## #O Download( [, ] ) ## DeclareOperation( "Download", [ IsString ] ); DeclareOperation( "Download", [ IsString, IsRecord ] ); ############################################################################# ## #U DownloadVerifyCertificate ## DeclareUserPreference( rec( name:= "DownloadVerifyCertificate", description:= [ "The value 'true' (the default) means that the server's certificate \ is checked in calls of 'Download' such that nothing gets downloaded \ if the certificate is invalid. \ If the value is 'false' then those download methods that are based on \ curl or wget will omit the check of the server's certificate." ], default:= true, values:= [ true, false ], multi:= false, package:= "utils", ) ); ############################################################################# ## #U DownloadMaxTime ## DeclareUserPreference( rec( name:= "DownloadMaxTime", description:= [ "The value '0' (the default) means that no timeout is set \ in calls of 'Download'. \ If the value is a positive integer 'n' then those download methods that \ support a timeout will give up after 'n' seconds." ], default:= 0, check:= val -> val = 0 or IsPosInt( val ), package:= "utils", ) ); utils-0.94/lib/download.gi0000644000000000000000000002114115174515600012435 0ustar00############################################################################## ## #W download.gi GAP4 package `Utils' Thomas Breuer ## #Y Copyright (C) 2022, The GAP Group ############################################################################# ## #V Download_Methods ## ## Use the following tools (in this order). ## ## - If the curlInterface package is available then call its ## 'DownloadURL' function. ## - If the URL starts with 'http://' and if the IO package is available ## then call the 'SingleHTTPRequest' function from this package. ## - If a 'wget' executable is available then call it. ## - If a 'curl' executable is available then call it. ## ## Note that currently the methods are *NOT* consistent in the case of ## failures: ## ## - The function 'SingleHTTPRequest' does not follow redirects as indicated ## by HTTP status codes 301 and 302. ## This happens for example if one asks for the file at ## 'http://www.gap-system.org/Packages/utils.html'. ## BindGlobal( "Download_Methods", [] ); Add( Download_Methods, rec( name:= "via DownloadURL (from the curlInterface package)", isAvailable:= {} -> IsPackageLoaded( "curlInterface" ) and CompareVersionNumbers( InstalledPackageVersion( "curlInterface" ), "2.3.0" ), download:= function( url, opt ) local res; opt:= ShallowCopy( opt ); if not IsBound( opt.failOnError ) then opt.failOnError:= true; fi; # 'DownloadURL' handles the options 'verifyCert' and 'maxTime'. res:= ValueGlobal( "DownloadURL" )( url, opt ); if res.success = true and IsBound( opt.target ) and IsString( opt.target ) then FileString( opt.target, res.result ); Unbind( res.result ); fi; return res; end ) ); Add( Download_Methods, rec( name:= "via SingleHTTPRequest (from the IO package)", isAvailable:= {} -> IsBoundGlobal( "SingleHTTPRequest" ), download:= function( url, opt ) local rurl, pos, domain, uri, res; if not StartsWith( url, "http://" ) then return rec( success:= false, error:= "protocol is not http" ); elif IsBound( opt.maxTime ) and opt.maxTime <> 0 then return rec( success:= false, error:= "no support for given timeout" ); fi; rurl:= ReplacedString( url, "http://", "" ); pos:= Position( rurl, '/' ); domain:= rurl{ [ 1 .. pos-1 ] }; uri:= rurl{ [ pos .. Length( rurl ) ] }; if IsBound( opt.target ) and IsString( opt.target ) then res:= ValueGlobal( "SingleHTTPRequest" )( domain, 80, "GET", uri, rec(), false, opt.target ); else res:= ValueGlobal( "SingleHTTPRequest" )( domain, 80, "GET", uri, rec(), false, false ); fi; if res.statuscode = 0 then return rec( success:= false, error:= res.status ); elif res.statuscode >= 400 then return rec( success:= false, error:= Concatenation( "HTTP error code ", String( res.statuscode ) ) ); elif not ( IsBound( opt.target ) and IsString( opt.target ) ) then return rec( success:= true, result:= res.body ); else return rec( success:= true ); fi; end ) ); Add( Download_Methods, rec( name:= "via wget", isAvailable:= function() local exec; exec:= Filename( DirectoriesSystemPrograms(), "wget" ); return exec <> fail and IsExecutableFile( exec ); end, download:= function( url, opt ) local res, outstream, exec, args, code; if IsBound( opt.maxTime ) and opt.maxTime <> 0 then # wget 1.20.3 ignores a given timeout. # (wget 1.21.3 would support timeout.) return rec( success:= false, error:= "no support for given timeout" ); fi; res:= ""; outstream:= OutputTextString( res, true ); exec:= Filename( DirectoriesSystemPrograms(), "wget" ); if IsBound( opt.target ) and IsString( opt.target ) then args:= [ "--quiet", "-O", opt.target, url ]; else args:= [ "--quiet", "-O", "-", url ]; fi; if IsBound( opt.verifyCert ) and opt.verifyCert = false then Add( args, "--no-check-certificate" ); fi; if IsBound( opt.maxTime ) and IsPosInt( opt.maxTime ) then Add( args, Concatenation( "--timeout=", String( opt.maxTime ) ) ); fi; code:= Process( DirectoryCurrent(), exec, InputTextNone(), outstream, args ); CloseStream( outstream ); if code <> 0 then # wget may have created the target file; try to remove it if IsBound( opt.target ) and IsString( opt.target ) and IsExistingFile( opt.target ) and RemoveFile( opt.target ) <> true then Error( "Download cannot remove unwanted file ", opt.target ); fi; return rec( success:= false, error:= Concatenation( "Process returned ", String( code ) ) ); elif not ( IsBound( opt.target ) and IsString( opt.target ) ) then return rec( success:= true, result:= res ); else return rec( success:= true ); fi; end ) ); Add( Download_Methods, rec( name:= "via curl", isAvailable:= function() local exec; exec:= Filename( DirectoriesSystemPrograms(), "curl" ); return exec <> fail and IsExecutableFile( exec ); end, download:= function( url, opt ) local res, outstream, exec, args, code; res:= ""; outstream:= OutputTextString( res, true ); exec:= Filename( DirectoriesSystemPrograms(), "curl" ); args:= [ "--silent", "-L", "--fail" ]; if IsBound( opt.verifyCert ) and opt.verifyCert = false then Add( args, "-k" ); fi; Add( args, "--output" ); if IsBound( opt.target ) and IsString( opt.target ) then Add( args, opt.target ); else Add( args, "-" ); fi; if IsBound( opt.maxTime ) and IsPosInt( opt.maxTime ) then Add( args, "--max-time" ); Add( args, opt.maxTime ); fi; Add( args, url ); code:= Process( DirectoryCurrent(), exec, InputTextNone(), outstream, args ); CloseStream( outstream ); if code <> 0 then return rec( success:= false, error:= Concatenation( "Process returned ", String( code ) ) ); elif not ( IsBound( opt.target ) and IsString( opt.target ) ) then return rec( success:= true, result:= res ); else return rec( success:= true ); fi; end ) ); ############################################################################# ## #M Download( [, ] ) ## ## Try to download the file described by the string , ## and return a record with the components 'success' ('true' or 'false'), ## and 'result' (a string, only if 'success' is 'true'), ## and 'error' (a string, only if 'success' is 'false'). ## InstallMethod( Download, [ "IsString" ], url -> Download( url, rec() ) ); InstallMethod( Download, [ "IsString", "IsRecord" ], function( url, opt ) local timeout, errors, r, res; # Set the default for 'verifyCert' if necessary. if not IsBound( opt.verifyCert ) and UserPreference( "utils", "DownloadVerifyCertificate" ) = false then opt.verifyCert:= false; fi; # Set the default for 'maxTime' if necessary. if not IsBound( opt.maxTime ) then timeout:= UserPreference( "utils", "DownloadMaxTime" ); if IsPosInt( timeout ) then opt.maxTime:= timeout; fi; fi; # Run over the methods. errors:= []; for r in Download_Methods do if r.isAvailable() then Info( InfoUtils, 2, "try Download method ", r.name ); res:= r.download( url, opt ); if res.success = true then return res; fi; Info( InfoUtils, 2, "Download method ", r.name, " failed with\n", "#I ", res.error ); Add( errors, Concatenation( r.name, ": ", res.error ) ); else Info( InfoUtils, 2, "Download method ", r.name, " is not available" ); fi; od; # No method was successful. if Length( errors ) = 0 then # No method was available, inform the user # that it is recommended to load or install some download tool. Info( InfoWarning, 1, "No 'Download' method is available.\n", "#I Please consider to install one of the tools, ", "see '?Download'" ); return rec( success:= false, error:= "no method was available" ); else # At least one method was tried but without success. if IsBound( opt.maxTime ) then Add( errors, Concatenation( "(maxTime option was set to ", String( opt.maxTime ), ")" ) ); fi; return rec( success:= false, error:= JoinStringsWithSeparator( errors, "; " ) ); fi; end ); utils-0.94/lib/files.gd0000644000000000000000000000207515174515600011730 0ustar00############################################################################## ## #W files.gd GAP4 package `Utils' Sebastian Gutsche ## Max Horn ## Stefan Kohl #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from RCWA ## #F Log2HTML ( logfilename ) ## ## Utility to convert GAP log files to XHTML 1.0 Strict. ## ## Usage: ## ## - Issue Log2HTML( ). The extension of the input file must ## be *.log. The name of the output file is the same as the one of the ## input file except that the extension *.log is replaced by *.html. ## ## - Adapt the style file rcwa/doc/gaplog.css to your taste. ## DeclareGlobalName( "Log2HTML" ); ############################################################################# ## #E files.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/files.gi0000644000000000000000000000701515174515600011734 0ustar00############################################################################# ## #W files.gi GAP4 package `Utils' Sebastian Gutsche ## Max Horn ## Stefan Kohl #Y Copyright (C) 2015-2025, The GAP Group, ############################################################################# ## this function has been transferred from RCWA ## #F Log2HTML ( logfilename ) . . . . convert GAP logfile to XHTML 1.0 Strict ## BindGlobal( "Log2HTML", function ( logfilename ) local outputname, s1, s2, header, footer, pos, lastlf, nextlf, crlf, prompt; if ARCH_IS_UNIX() then crlf := 1; else crlf := 2; fi; header := Concatenation( "\n\n", "\n\n\n\n ", logfilename, " \n \n", "\n\n\n\n

\n");
    footer := "
"; s1 := StringFile( logfilename ); pos := PositionSublist( s1, "gap>" ); prompt := "gap> "; s2 := ReplacedString( s1{[1..pos-1]}, "<", "<" ); while pos <> fail do s2 := Concatenation(s2,"",prompt,""); s2 := Concatenation(s2,""); nextlf := Position(s1,'\n',pos); prompt := "gap>"; if nextlf = fail then nextlf := Length(s1); fi; s2 := Concatenation(s2,ReplacedString(s1{[pos+5..nextlf-crlf]}, "<","<"),""); while nextlf < Length(s1) and s1[nextlf+1] = '>' do s2 := Concatenation(s2,"\n>", ""); lastlf := nextlf; nextlf := Position(s1,'\n',lastlf); if nextlf = fail then nextlf := Length(s1); fi; s2 := Concatenation(s2,ReplacedString(s1{[lastlf+2..nextlf-crlf]}, "<","<"),""); od; s2 := Concatenation( s2, "\n" ); pos := PositionSublist( s1, "\ngap>", nextlf-1 ); if pos = fail then pos := Length(s1); fi; if pos > nextlf then s2 := Concatenation(s2,"", ReplacedString( s1{[nextlf+1..pos-crlf]}, "<", "<"), "\n" ); fi; if pos > Length(s1) - 3 then break; fi; od; s2 := Concatenation( header, s2, footer ); logfilename := LowercaseString( logfilename ); if ( PositionSublist(logfilename,".log") <> fail ) then outputname := ReplacedString( logfilename, ".log", ".html" ); elif ( PositionSublist( logfilename, ".txt" ) <> fail ) then outputname := ReplacedString( logfilename, ".txt", ".html" ); else outputname := Concatenation( logfilename, ".html" ); fi; FileString( outputname, s2 ); end ); ############################################################################# ## #E files.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/groups.gd0000644000000000000000000000415015174515600012141 0ustar00############################################################################## ## #W groups.gd GAP4 package `Utils' Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from ResClasses ## #O IsCommuting( , ) . checks whether two group elements etc. commute ## DeclareOperation( "IsCommuting", [ IsMultiplicativeElement, IsMultiplicativeElement ] ); ############################################################################# ## these functions have been transferred from ResClasses ## #A UpperFittingSeries( ) . . . . . . . . . . upper fitting series of #A LowerFittingSeries( ) . . . . . . . . . . lower fitting series of #A FittingLength( ) . . . . . . . . . . . . . . . fitting length of ## ## The upper and lower Fitting series and the Fitting length of a solvable ## group, as described here: https://en.wikipedia.org/wiki/Fitting_length ## if not IsBound( UpperFittingSeries ) then DeclareAttribute( "UpperFittingSeries", IsGroup ); fi; if not IsBound( LowerFittingSeries ) then DeclareAttribute( "LowerFittingSeries", IsGroup ); fi; if not IsBound( FittingLength ) then DeclareAttribute( "FittingLength", IsGroup ); fi; ############################################################################# ## this function has been transferred from RCWA ## #F ListOfPowers( , ) . . . . . . list of powers ^1 .. ^ ## DeclareGlobalName( "ListOfPowers" ); ############################################################################# ## this function has been transferred from RCWA ## #O GeneratorsAndInverses( ) list of generators of and their inverses #M GeneratorsAndInverses( ) . . . . . . . . . . . . . . . . . for groups ## DeclareOperation( "GeneratorsAndInverses", [ IsMagmaWithInverses ] ); ############################################################################# ## #E groups.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/groups.gi0000644000000000000000000000737215174515600012157 0ustar00############################################################################# ## #W groups.gi GAP4 package `Utils' Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from ResClasses ## #M Comm( [ , ] ) . . . for arguments enclosed in list brackets ## InstallOtherMethod( Comm, "for arguments enclosed in list brackets (ResClasses)", true, [ IsList ], 0, LeftNormedComm ); ############################################################################# ## this function has been transferred from ResClasses ## #M IsCommuting( , ) . . . . . . . . . . . . . . . . . fallback method ## InstallMethod( IsCommuting, "fallback method (ResClasses)", IsIdenticalObj, [ IsMultiplicativeElement, IsMultiplicativeElement ], 0, function ( a, b ) return a*b = b*a; end ); ############################################################################# ## this function has been transferred from ResClasses ## #M UpperFittingSeries( ) . . . . . . . . . . . . . . . . default method ## InstallMethod( UpperFittingSeries, "default method", true, [ IsGroup ], 0, function ( G ) local series, F, phi; if IsTrivial(FittingSubgroup(G)) then return [ TrivialSubgroup(G) ]; fi; F := FittingSubgroup(G); series := [ TrivialSubgroup(G), F ]; while F <> G do phi := NaturalHomomorphismByNormalSubgroup(G,F); F := PreImage(phi,FittingSubgroup(Image(phi))); if series[Length(series)] = F then break; fi; Add(series,F); od; return series; end ); ############################################################################# ## this function has been transferred from ResClasses ## #M LowerFittingSeries( ) . . . . . . . . . . . . . . . . default method ## InstallMethod( LowerFittingSeries, "default method", true, [ IsGroup ], 0, function ( G ) local series, F; series := [ G ]; F := G; while not IsTrivial(F) do F := Reversed(LowerCentralSeries(F))[1]; if series[Length(series)] = F then break; fi; Add(series,F); od; return series; end ); ############################################################################# ## this function has been transferred from ResClasses ## #M FittingLength( ) . . . . . . . . . . . . . . . . . . . default method ## InstallMethod( FittingLength, "default method", true, [ IsGroup ], 0, function ( G ) if not IsSolvableGroup(G) then return infinity; fi; if HasUpperFittingSeries(G) then return Length(UpperFittingSeries(G)) - 1; else return Length(LowerFittingSeries(G)) - 1; fi; end ); ############################################################################# ## this function has been transferred from RCWA ## #F ListOfPowers( , ) . . . . . . list of powers ^1 .. ^ ## BindGlobal( "ListOfPowers", function ( g, exp ) local powers, n; powers := [g]; for n in [2..exp] do Add(powers,powers[n-1]*g); od; return powers; end ); ############################################################################# ## this function has been transferred from RCWA ## #M GeneratorsAndInverses( ) list of generators of and their inverses #M GeneratorsAndInverses( ) . . . . . . . . . . . . . . . . . for groups ## InstallMethod( GeneratorsAndInverses, "for groups", true, [ IsGroup ], 0, G -> Concatenation( GeneratorsOfGroup(G), List( GeneratorsOfGroup(G), g->g^-1 ) ) ); ############################################################################# ## #E groups.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/gslp.gd0000644000000000000000000002760115174515600011575 0ustar00############################################################################# ## #W gslp.gd GAP 4 package utils Thomas Breuer ## ## A remark on the name generalized straight line program: ## We could have taken the viewpoint that these objects are the ones that ## one wants to deal with, ## and that they should therefore be called straight line program, ## whereas &GAP;'s straight line programs could be called ## special straight line programs, ## However, ## several functions are applicable to &GAP;'s straight line programs ## (such as ) ## for which we do not intend to provide methods applicable to ## our generalized straight line programs. ## <#/GAPDoc> ## ############################################################################# ## #C IsGeneralizedStraightLineProgram( ) ## ## <#GAPDoc Label="IsGeneralizedStraightLineProgram"> ## ## ## ## ## Each generalized straight line program in &GAP; lies in the category ## . ## Examples are straight line programs, that is, objects in the category ## . ##

## If gslp is a straight line program then this attribute is not ## set in gslp. ## There is no default method to compute the value if it is not stored. ##

## gslp:= GeneralizedStraightLineProgram( "union", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); ## ## gap> DataOfGeneralizedStraightLineProgram( gslp ); ## [ "union", [ , ] ] ## ]]> ## ## ## <#/GAPDoc> ## DeclareAttribute( "DataOfGeneralizedStraightLineProgram", IsGeneralizedStraightLineProgram ); ############################################################################# ## #A NrInputsOfGeneralizedStraightLineProgram( ) ## ## <#GAPDoc Label="NrInputsOfGeneralizedStraightLineProgram"> ## ## ## ## ## For a generalized straight line program gslp, this function ## returns the number of generators that are needed as input. ##

## If gslp is a straight line program then it may be necessary that ## the value is set in the construction of gslp, ## see . ## If gslp is not a straight line program then the value is ## determined by the (generalized) straight line programs from which ## gslp is constructed. ##

## NrInputsOfGeneralizedStraightLineProgram( ## > GeneralizedStraightLineProgram( "union", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); ## 1 ## ]]> ##

## In order to avoid the introduction of unnecessary filters, ## we define just as ## a synonym of . ## ## ## <#/GAPDoc> ## DeclareSynonymAttr( "NrInputsOfGeneralizedStraightLineProgram", NrInputsOfStraightLineProgram ); ############################################################################# ## #A NrOutputsOfGeneralizedStraightLineProgram( ) ## ## <#GAPDoc Label="NrOutputsOfGeneralizedStraightLineProgram"> ## ## ## ## ## For a generalized straight line program gslp, this function ## returns the number of elements returned by ## when gslp ## is evaluated. ##

## Note that the &GAP; library does not define a corresponding attribute ## for straight line programs. ##

## NrOutputsOfGeneralizedStraightLineProgram( ## > GeneralizedStraightLineProgram( "union", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); ## 2 ## gap> NrOutputsOfGeneralizedStraightLineProgram( ## > GeneralizedStraightLineProgram( "compose", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); ## 1 ## ]]> ## ## ## <#/GAPDoc> ## DeclareAttribute( "NrOutputsOfGeneralizedStraightLineProgram", IsGeneralizedStraightLineProgram ); ############################################################################# ## #F GeneralizedStraightLineProgram( [, ] ) #F GeneralizedStraightLineProgram( , ) ## ## <#GAPDoc Label="GeneralizedStraightLineProgram"> ## ## GeneralizedStraightLineProgram ## ## ## ## ## In the first form, lines must be a list of lists that defines ## a unique straight line program ## (see ); ## in this case delegates to ## . ##

## In the second form, kind must be one of the strings "union" ## or "compose", and list must be a nonempty list such that ## each of its entries is either a gslp or a list l, say, ## such that ## applied to and ## l returns a gslp. ##

## GeneralizedStraightLineProgram( [[[1,2]]], 1 ); ## ## gap> GeneralizedStraightLineProgram( "union", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); ## ## gap> GeneralizedStraightLineProgram( "compose", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); ## ## ]]> ## ## ## <#/GAPDoc> ## DeclareGlobalFunction( "GeneralizedStraightLineProgram" ); ############################################################################# ## #O ResultOfGeneralizedStraightLineProgram( , ) ## ## <#GAPDoc Label="ResultOfGeneralizedStraightLineProgram"> ## ## ## ## ## evaluates the ## generalized straight line program ## (see ) gslp ## at the group elements in the list gens, as follows. ##

## ## ## If gslp is a straight line program then the value of ## is returned. ## ## ## If gslp is of union kind then ## is applied to ## each of the involved generalized straight line programs, with ## second argument gens, and the concatenation of the results ## is returned. ## ## ## If gslp is of compose kind then ## is first called ## with the first involved generalized straight line program and ## gens, ## then the operation is called with the second involved ## generalized straight line program and the result of this call, ## and so on; the last such result is returned. ## ## ##

## gens:= [ (1,2,3,4,5,6) ];; ## gap> gslp:= GeneralizedStraightLineProgram( "union", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); ## ## gap> ResultOfGeneralizedStraightLineProgram( gslp, gens ); ## [ (1,3,5)(2,4,6), (1,4)(2,5)(3,6) ] ## gap> gslp:= GeneralizedStraightLineProgram( "compose", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); ## ## gap> ResultOfGeneralizedStraightLineProgram( gslp, gens ); ## [ () ] ## ]]> ##

## In order to avoid the introduction of unnecessary operations, ## we define just as ## a synonym of . ## ## ## <#/GAPDoc> ## DeclareSynonym( "ResultOfGeneralizedStraightLineProgram", ResultOfStraightLineProgram ); DeclareOperation( "ResultOfGeneralizedStraightLineProgram", [ IsGeneralizedStraightLineProgram, IsHomogeneousList ] ); ############################################################################# ## #A EquivalentStraightLineProgram( ) ## ## <#GAPDoc Label="EquivalentStraightLineProgram"> ## ## ## ## ## For a generalized straight line program gslp, ## returns ## a straight line program such that evaluating gslp and this ## straight line program with ## yields the same ## output, for any list of input elements. ##

## gslp:= GeneralizedStraightLineProgram( "union", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); ## ## gap> slp:= EquivalentStraightLineProgram( gslp ); ## ## gap> Display( slp ); ## # input: ## r:= [ g1 ]; ## # program: ## # return values: ## [ r[1]^2, r[1]^3 ] ## gap> gslp:= GeneralizedStraightLineProgram( "compose", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); ## ## gap> slp:= EquivalentStraightLineProgram( gslp ); ## ## gap> Display( slp ); ## # input: ## r:= [ g1 ]; ## # program: ## r[2]:= r[1]^2; ## r[1]:= r[2]; ## # return values: ## [ r[1]^3 ] ## ]]> ## ## ## <#/GAPDoc> ## DeclareAttribute( "EquivalentStraightLineProgram", IsGeneralizedStraightLineProgram ); ############################################################################# ## #E utils-0.94/lib/gslp.gi0000644000000000000000000002123715174515600011601 0ustar00############################################################################# ## #W gslp.gi GAP 4 package utils Thomas Breuer ## ############################################################################# ## #V GeneralizedStraightLineProgramsFamily #V GeneralizedStraightLineProgramsDefaultType ## BindGlobal( "GeneralizedStraightLineProgramsFamily", NewFamily( "GeneralizedStraightLineProgramsFamily", IsGeneralizedStraightLineProgram ) ); BindGlobal( "GeneralizedStraightLineProgramsDefaultType", NewType( GeneralizedStraightLineProgramsFamily, IsGeneralizedStraightLineProgram and IsAttributeStoringRep ) ); ############################################################################# ## #F GeneralizedStraightLineProgram( [, ] ) #F GeneralizedStraightLineProgram( , ) ## InstallGlobalFunction( GeneralizedStraightLineProgram, function( arg ) local kind, list, data, i, nin, nout; if Length( arg ) = 1 or ( Length( arg ) = 2 and not IsString( arg[1] ) ) then # Delegate to `StraightLineProgram'. return CallFuncList( StraightLineProgram, arg ); elif Length( arg ) <> 2 then Error( "usage: GeneralizedStraightLineProgram( [, ] )", " or GeneralizedStraightLineProgram( , )" ); fi; kind:= arg[1]; list:= arg[2]; if not IsList( list ) or IsEmpty( list ) then Error( " must be a nonempty list" ); fi; data:= ShallowCopy( list ); for i in [ 1 .. Length( data ) ] do if not IsGeneralizedStraightLineProgram( data[i] ) then data[i]:= CallFuncList( GeneralizedStraightLineProgram, data[i] ); fi; od; if kind = "union" then # Check that the inputs are compatible. nin:= NrInputsOfGeneralizedStraightLineProgram( data[1] ); nout:= NrOutputsOfGeneralizedStraightLineProgram( data[1] ); for i in [ 2 .. Length( data ) ] do if NrInputsOfGeneralizedStraightLineProgram( data[i] ) <> nin then Error( "all entries of must have the same input number" ); fi; nout:= nout + NrOutputsOfGeneralizedStraightLineProgram( data[i] ); od; elif kind = "compose" then # Check that the inputs are compatible. nin:= NrOutputsOfGeneralizedStraightLineProgram( data[1] ); for i in [ 2 .. Length( data ) ] do if NrInputsOfGeneralizedStraightLineProgram( data[i] ) <> nin then Error( "inputs and outputs for are not compatible" ); fi; nin:= NrOutputsOfGeneralizedStraightLineProgram( data[i] ); od; nout:= nin; nin:= NrInputsOfGeneralizedStraightLineProgram( data[1] ); else Error( " must be one of \"union\", \"compose\"" ); fi; return ObjectifyWithAttributes( rec(), GeneralizedStraightLineProgramsDefaultType, DataOfGeneralizedStraightLineProgram, [ kind, data ], NrInputsOfGeneralizedStraightLineProgram, nin, NrOutputsOfGeneralizedStraightLineProgram, nout ); end ); ############################################################################# ## #M NrOutputsOfGeneralizedStraightLineProgram( ) ## InstallMethod( NrOutputsOfGeneralizedStraightLineProgram, [ "IsGeneralizedStraightLineProgram" ], function( gslp ) local data; if IsStraightLineProgram( gslp ) then # The value is in general not set in the construction. data:= Last( LinesOfStraightLineProgram( gslp ) ); if ForAll( data, IsList ) then return Length( data ); else return 1; fi; else # The value should get set in the construction. Error( "attribute value got lost?" ); fi; end ); ############################################################################# ## #M ResultOfGeneralizedStraightLineProgram( , ) ## InstallMethod( ResultOfGeneralizedStraightLineProgram, [ "IsGeneralizedStraightLineProgram", "IsHomogeneousList" ], function( gslp, gens ) local data, result, prg; # We may assume that the 'IsStraightLineProgram' method has higher rank. Assert( 1, not IsStraightLineProgram( gslp ) ); data:= DataOfGeneralizedStraightLineProgram( gslp ); if data[1] = "union" then result:= Concatenation( List( data[2], x -> ResultOfGeneralizedStraightLineProgram( x, gens ) ) ); else result:= gens; for prg in data[2] do result:= ResultOfGeneralizedStraightLineProgram( prg, result ); od; fi; return result; end ); ############################################################################# ## #M EquivalentStraightLineProgram( ) ## InstallMethod( EquivalentStraightLineProgram, [ "IsGeneralizedStraightLineProgram" ], function( gslp ) local data, result, i; if IsStraightLineProgram( gslp ) then return gslp; fi; data:= DataOfGeneralizedStraightLineProgram( gslp ); if data[1] = "union" then result:= IntegratedStraightLineProgram( List( data[2], EquivalentStraightLineProgram ) ); else data:= data[2]; result:= EquivalentStraightLineProgram( data[1] ); for i in [ 2 .. Length( data ) ] do result:= CompositionOfStraightLinePrograms( EquivalentStraightLineProgram( data[i] ), result ); od; fi; return result; end ); ############################################################################# ## #M ViewString( ) #M String( ) ## ## We want that 'View' shows '', ## and that 'Print' shows GAP readable information. ## (See '?Recommendations for the implementation' for the background.) ## InstallMethod( ViewString, [ "IsGeneralizedStraightLineProgram" ], gslp -> "" ); InstallMethod( ViewString, [ "IsStraightLineProgram" ], slp -> "" ); #T eventually move this to the GAP library InstallMethod( String, [ "IsGeneralizedStraightLineProgram" ], function( gslp ) local data; data:= DataOfGeneralizedStraightLineProgram( gslp ); return Concatenation( "GeneralizedStraightLineProgram( \"", data[1], "\", [ ", JoinStringsWithSeparator( List( data[2], String ), ", " ), " ] )" ); end ); InstallMethod( String, [ "IsStraightLineProgram" ], slp -> Concatenation( "StraightLineProgram( ", String( LinesOfStraightLineProgram( slp ) ), ", ", String( NrInputsOfStraightLineProgram( slp ) ), " )" ) ); #T eventually move this to the GAP library ############################################################################# ## #M IsInternallyConsistent( ) ## ## <#GAPDoc Label="IsInternallyConsistent_gslp"> ## ## ## ## ## For a generalized straight line program gslp, ## it is checked whether all (generalized) straight line programs ## from which gslp is built are internally consistent, ## and whether their numbers of inputs and outputs are consistent and ## compatible with the numbers of inputs and outputs of gslp. ##

## gslp:= GeneralizedStraightLineProgram( "union", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; ## gap> IsInternallyConsistent( gslp ); ## true ## gap> gslp:= GeneralizedStraightLineProgram( "compose", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; ## gap> IsInternallyConsistent( gslp ); ## true ## ]]> ## ## ## <#/GAPDoc> ## InstallMethod( IsInternallyConsistent, [ "IsGeneralizedStraightLineProgram" ], function( gslp ) local data, nrinp, constit; if IsStraightLineProgram( gslp ) then TryNextMethod(); fi; data:= DataOfGeneralizedStraightLineProgram( gslp ); if data[1] = "union" then nrinp:= NrInputsOfGeneralizedStraightLineProgram( gslp ); return ForAll( data[2], x -> IsInternallyConsistent( x ) and NrInputsOfGeneralizedStraightLineProgram( x ) = nrinp ); elif data[1] = "compose" then nrinp:= NrInputsOfGeneralizedStraightLineProgram( gslp ); for constit in data[2] do if ( not IsInternallyConsistent( constit ) ) or NrInputsOfGeneralizedStraightLineProgram( constit ) <> nrinp then return false; fi; nrinp:= NrOutputsOfGeneralizedStraightLineProgram( constit ); od; return true; else return false; fi; end ); ############################################################################# ## #E utils-0.94/lib/iterator.gd0000644000000000000000000000326015174515600012454 0ustar00############################################################################## ## #W iterator.gd GAP4 package `Utils' Chris Wensley ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## These functions complement AllHomomorphisms, AllEndomorphisms, and ## AllAutomorphisms in the main library. ## The code gives an example of an iterator preferrred to a list. ## #O AllIsomorphismsIterator( , ) #F DoAllIsomorphismsIterator #O AllIsomorphismsNumber( , ) #O AllIsomorphisms( , ) ## DeclareOperation( "AllIsomorphismsIterator", [ IsGroup, IsGroup ] ); DeclareGlobalName( "DoAllIsomorphismsIterator" ); DeclareOperation( "AllIsomorphismsNumber", [ IsGroup, IsGroup ] ); DeclareOperation( "AllIsomorphisms", [ IsGroup, IsGroup ] ); ############################################################################# ## These functions provide an iterator for all subgroups of a group. ## #O AllSubgroupsIterator( ) #F DoAllSubgroupsIterator ## DeclareOperation( "AllSubgroupsIterator", [ IsGroup ] ); DeclareGlobalName( "DoAllSubgroupsIterator" ); ############################################################################# ## These functions provide ways of combining two iterators into one ## #O CartesianIterator( ) #F DoCartesianIterator #O UnorderedPairsIterator( ) #F DoUnorderedPairsIterator ## DeclareOperation( "CartesianIterator", [ IsIterator, IsIterator ] ); DeclareGlobalName( "DoCartesianIterator" ); DeclareOperation( "UnorderedPairsIterator", [ IsIterator ] ); DeclareGlobalName( "DoUnorderedPairsIterator" ); utils-0.94/lib/iterator.gi0000644000000000000000000002064115174515600012463 0ustar00############################################################################# ## #W iterator.gi GAP4 package `Utils' Chris Wensley ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################## ## #M AllIsomorphismsIterator . . . . . . . . . . . . . . . for a pair of groups #M DoAllIsomorphismsIterator . . . . . . . . . . . . . . for a pair of groups #M AllIsomorphismsNumber . . . . . . . . . . . . . . . . for a pair of groups #M AllIsomorphisms . . . . . . . . . . . . . . . . . . . for a pair of groups ## BindGlobal( "NextIterator_AllIsomorphisms", function ( iter ) local a; if not IsDoneIterator( iter ) then a := NextIterator( iter!.autoIterator ); return CompositionMapping( iter!.firstiso, a ); fi; Error( "iterator is exhausted" ); end ); BindGlobal( "IsDoneIterator_AllIsomorphisms", iter -> IsDoneIterator( iter!.autoIterator ) ); BindGlobal( "ShallowCopy_AllIsomorphisms", iter -> rec( firstiso := iter!.firstiso, autoIterator := ShallowCopy( iter!.autoIterator ) ) ); BindGlobal( "DoAllIsomorphismsIterator", function( G, H ) local iso, autoiter, iter; if not IsGroup( G ) and IsGroup( H ) then Error( "G,H should be groups" ); fi; iso := IsomorphismGroups( G, H ); if ( iso = fail ) then ## there are no isomorphisms so return an empty iterator return IteratorList( [ ] ); fi; autoiter := Iterator( AutomorphismGroup( G ) ); iter := IteratorByFunctions( rec( firstiso := iso, autoIterator := ShallowCopy( autoiter ), NextIterator := NextIterator_AllIsomorphisms, IsDoneIterator := IsDoneIterator_AllIsomorphisms, ShallowCopy := ShallowCopy_AllIsomorphisms ) ); return iter; end ); InstallMethod( AllIsomorphismsIterator, "for a pair of groups", [ IsGroup, IsGroup ], 0, function( G, H ) return DoAllIsomorphismsIterator( G, H ); end ); InstallMethod( AllIsomorphisms, "for a pair of groups", [ IsGroup, IsGroup ], 0, function( G, H ) local iter, L, iso; iter := AllIsomorphismsIterator( G, H ); if IsDoneIterator( iter ) then return [ ]; fi; L := [ ]; for iso in iter do Add( L, iso ); od; return L; end ); InstallMethod( AllIsomorphismsNumber, "for a pair of groups", [ IsGroup, IsGroup ], 0, function( G, H ) local iter, n, iso; iter := AllIsomorphismsIterator( G, H ); if IsDoneIterator( iter ) then return 0; fi; n := 0; for iso in iter do n := n+1; od; return n; end ); ############################################################################## ## #M AllSubgroupsIterator . . . . . . . . . . . . . . . . . . . . . for a group #M DoAllSubgroupsIterator . . . . . . . . . . . . . . . . . . . . for a group ## BindGlobal( "NextIterator_AllSubgroups", function ( iter ) local class, i; if IsDoneIterator( iter!.subgpIterator ) then class := NextIterator( iter!.classIterator ); iter!.class := class; iter!.subgpIterator := IteratorList( [1..Size(class)] ); fi; i := NextIterator( iter!.subgpIterator ); return iter!.class[i]; end ); BindGlobal( "IsDoneIterator_AllSubgroups", iter -> IsDoneIterator( iter!.classIterator ) and IsDoneIterator( iter!.subgpIterator ) ); BindGlobal( "ShallowCopy_AllSubgroups", iter -> rec( class := iter!.class, classIterator := ShallowCopy( iter!.classIterator ), subgpIterator := ShallowCopy( iter!.subgpIterator ) ) ); BindGlobal( "DoAllSubgroupsIterator", function( G ) local lat, ccs, classIterator, subgpIterator, iter; lat := LatticeSubgroups( G ); ccs := ConjugacyClassesSubgroups( lat ); classIterator := IteratorList( ccs ); subgpIterator := 0; iter := IteratorByFunctions( rec( class := 0, classIterator := ShallowCopy( classIterator ), subgpIterator := IteratorList( [ ] ), NextIterator := NextIterator_AllSubgroups, IsDoneIterator := IsDoneIterator_AllSubgroups, ShallowCopy := ShallowCopy_AllSubgroups ) ); return iter; end ); InstallMethod( AllSubgroupsIterator, "for a group", [ IsGroup ], 0, function( G ) return DoAllSubgroupsIterator( G ); end ); ############################################################################## ## #M CartesianIterator . . . . . . . . . . . . . . . . . . . for two iterators #M DoCartesianIterator . . . . . . . . . . . . . . . . . . for two iterators ## BindGlobal( "NextIterator_CartesianIterator", function ( iter ) local first, second; if IsDoneIterator( iter!.Iterator2Copy ) then iter!.Iterator2Copy := ShallowCopy( iter!.Iterator2 ); first := NextIterator( iter!.Iterator1 ); iter!.first := first; else first := iter!.first; fi; second := NextIterator( iter!.Iterator2Copy ); return [ first, second ]; end ); BindGlobal( "IsDoneIterator_CartesianIterator", iter -> IsDoneIterator( iter!.Iterator1 ) and IsDoneIterator( iter!.Iterator2Copy ) ); BindGlobal( "ShallowCopy_CartesianIterator", iter -> rec( first := iter!.first, Iterator1 := ShallowCopy( iter!.Iterator1 ), Iterator2 := ShallowCopy( iter!.Iterator2 ), Iterator2Copy := ShallowCopy( iter!.Iterator2Copy ) ) ); BindGlobal( "DoCartesianIterator", function( iter1, iter2 ) local iter; if IsDoneIterator( iter1 ) or IsDoneIterator( iter2 ) then return IteratorList( [ ] ); fi; iter := IteratorByFunctions( rec( first := 0, Iterator1 := ShallowCopy( iter1 ), Iterator2 := ShallowCopy( iter2 ), Iterator2Copy := IteratorList( [ ] ), NextIterator := NextIterator_CartesianIterator, IsDoneIterator := IsDoneIterator_CartesianIterator, ShallowCopy := ShallowCopy_CartesianIterator ) ); return iter; end ); InstallMethod( CartesianIterator, "for two iterators", [ IsIterator, IsIterator ], 0, function( iter1, iter2 ) return DoCartesianIterator( iter1, iter2 ); end ); ############################################################################## ## #M UnorderedPairsIterator . . . . . . . . . . . . . . . . . . for an iterator #M DoUnorderedPairsIterator . . . . . . . . . . . . . . . . . for an iterator ## BindGlobal( "NextIterator_UnorderedPairs", function ( iter ) local first, second; if ( iter!.pos1 = iter!.pos2 ) then iter!.Iterator1Copy := ShallowCopy( iter!.Iterator1 ); iter!.pos1 := 0; second := NextIterator( iter!.Iterator2 ); iter!.pos2 := iter!.pos2 + 1; iter!.second := second; else second := iter!.second; fi; first := NextIterator( iter!.Iterator1Copy ); iter!.pos1 := iter!.pos1 + 1; return [ first, second ]; end ); BindGlobal( "IsDoneIterator_UnorderedPairs", iter -> IsDoneIterator( iter!.Iterator2 ) and IsDoneIterator( iter!.Iterator1Copy ) ); BindGlobal( "ShallowCopy_UnorderedPairs", iter -> rec( pos1 := iter!.pos1, pos2 := iter!.pos2, second := iter!.second, Iterator1 := ShallowCopy( iter!.Iterator1 ), Iterator2 := ShallowCopy( iter!.Iterator2 ), Iterator1Copy := ShallowCopy( iter!.Iterator1Copy ) ) ); BindGlobal( "DoUnorderedPairsIterator", function( iter0 ) local iter; if IsDoneIterator( iter0 ) then return IteratorList( [ ] ); fi; iter := IteratorByFunctions( rec( pos1 := 0, pos2 := 0, second := 0, Iterator1 := ShallowCopy( iter0 ), Iterator2 := ShallowCopy( iter0 ), Iterator1Copy := ShallowCopy( iter0 ), NextIterator := NextIterator_UnorderedPairs, IsDoneIterator := IsDoneIterator_UnorderedPairs, ShallowCopy := ShallowCopy_UnorderedPairs ) ); return iter; end ); InstallMethod( UnorderedPairsIterator, "for an iterator", [ IsIterator ], 0, function( iter0 ) return DoUnorderedPairsIterator( iter0 ); end ); utils-0.94/lib/latex.gd0000644000000000000000000000165015174515600011741 0ustar00############################################################################## ## #W latex.gd GAP4 package `Utils' Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from ResClasses ## #F IntOrInfinityToLaTeX( n ) . LaTeX string representing integer or infinity ## DeclareGlobalName( "IntOrInfinityToLaTeX" ); ############################################################################# ## this function has been transferred from RCWA ## #F LaTeXStringFactorsInt( ) ## ## Returns the prime factorization of the integer as a string in LaTeX ## format. ## DeclareGlobalName( "LaTeXStringFactorsInt" ); ############################################################################# ## #E latex.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/latex.gi0000644000000000000000000000320215174515600011741 0ustar00############################################################################# ## #W latex.gi GAP4 package `Utils' Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from ResClasses ## #F IntOrInfinityToLaTeX( n ) . LaTeX string for a given integer or infinity ## BindGlobal( "IntOrInfinityToLaTeX", function( n ) if IsInt(n) then return String(n); elif IsInfinity(n) then return "\\infty"; else return fail; fi; end ); ############################################################################# ## this function has been transferred from RCWA ## #F LaTeXStringFactorsInt( ) . . . . prime factorization in LaTeX format ## BindGlobal( "LaTeXStringFactorsInt", function ( n ) local facts, str, i; if not IsInt(n) then Error("usage: LaTeXStringFactorsInt( ) for an integer "); fi; if n < 0 then str := "-"; n := -n; else str := ""; fi; facts := Collected(Factors(n)); for i in [1..Length(facts)] do Append(str,String(facts[i][1])); if facts[i][2] > 1 then Append(str,"^"); if facts[i][2] >= 10 then Append(str,"{"); fi; Append(str,String(facts[i][2])); if facts[i][2] >= 10 then Append(str,"}"); fi; fi; if i < Length(facts) then Append(str," \\cdot "); fi; od; return str; end ); ############################################################################# ## #E latex.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/lcset.gd0000644000000000000000000000264215174515600011740 0ustar00############################################################################## ## #W lcset.gd GAP4 package `Utils' Chris Wensley ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## #C IsLeftCoset( ) . . . . . . . . . . . . . . coset of the form gU #R IsLeftCosetDefaultRep #V IsLeftCosetFamily #T IsLeftCosetType ## DeclareCategory( "IsLeftCoset", IsDomain and IsExternalOrbit ); DeclareRepresentation( "IsLeftCosetDefaultRep", IsComponentObjectRep and IsAttributeStoringRep and IsLeftCoset, [ "Representative", "ActingDomain" ] ); BindGlobal( "IsLeftCosetFamily", NewFamily( "IsLeftCosetFamily", IsMultiplicativeElementWithInverse ) ); BindGlobal( "IsLeftCosetType", NewType( IsLeftCosetFamily, IsLeftCosetDefaultRep ) ); ############################################################################# ## #O LeftCoset( , ) . . . . . . . element g acts on the left of group U ## DeclareOperation( "LeftCoset", [ IsObject, IsGroup ] ); ############################################################################# ## #O LeftCosets( , ) . . . . . . . . . . . . . . . cosets gU for g in G #O LeftCosetsNC( , ) . . . . . . . . . . . . . . cosets gU for g in G ## DeclareGlobalName( "LeftCosets" ); DeclareOperation( "LeftCosetsNC", [ IsGroup, IsGroup ] ); utils-0.94/lib/lcset.gi0000644000000000000000000001125215174515600011742 0ustar00############################################################################## ## #W lcset.gi GAP4 package `Utils' Chris Wensley ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## #O LeftCoset( , ) . . . . . . . . forms a left coset of U by g \in G ## InstallMethod( LeftCoset, "generic method for left cosets", true, [ IsObject, IsGroup ], 0, function( g, U ) local lc, fam; fam := FamilyObj( U ); if not IsBound( fam!.leftCosetsDefaultType ) then fam!.leftCosetsDefaultType := NewType( fam, IsLeftCosetDefaultRep and HasActingDomain and HasFunctionAction and HasRepresentative ); fi; lc := rec(); ObjectifyWithAttributes( lc, fam!.leftCosetsDefaultType, Representative, g, ActingDomain, U, FunctionAction, OnRight, IsLeftCoset, true ); if HasSize( U ) then SetSize( lc, Size( U ) ); fi; return lc; end); ############################################################################# ## #A Inverse( ) . . . . . forms the right coset Ug^-1 corresponding to gU #A Inverse( ) . . . . . forms the left coset g^-1U corresponding to Ug ## InstallOtherMethod( Inverse, "generic method for left cosets", true, [ IsLeftCoset ], 0, function( lc ) local g, U, rc; g := Representative( lc ); U := ActingDomain( lc ); rc := RightCoset( U, g^-1 ); SetInverse( rc, lc ); return rc; end); InstallOtherMethod( Inverse, "generic method for right cosets", true, [ IsRightCoset ], 0, function( rc ) local g, U, lc; g := Representative( rc ); U := ActingDomain( rc ); lc := LeftCoset( g^-1, U ); SetInverse( lc, rc ); return lc; end); InstallMethod( PrintString, "for a left coset", true, [ IsLeftCoset ], 0, function( d ) return STRINGIFY( "LeftCoset(\<", PrintString( Representative(d) ), ",\>", PrintString( ActingDomain(d) ), ")" ); end); InstallMethod( PrintObj, "for a left coset", true, [ IsLeftCoset ], 0, function( d ) Print( PrintString( d ) ); end); InstallMethod( ViewString, "for a left coset", true, [ IsLeftCoset ], 0, function( d ) return STRINGIFY( "LeftCoset(\<", ViewString( Representative(d) ), ",\>", ViewString( ActingDomain(d) ), ")" ); end); InstallMethod( ViewObj, "for a left coset", true, [ IsLeftCoset ], 0, function( d ) Print( ViewString( d ) ); end); InstallMethod( \=, "for two left cosets", IsIdenticalObj, [ IsLeftCoset, IsLeftCoset ], 0, function( lc1, lc2 ) return ( ActingDomain( lc1 ) = ActingDomain( lc2 ) ) and ( Representative(lc1)/Representative(lc2) in ActingDomain( lc1 ) ); end); InstallMethod( \in, "element and LeftCoset", true, [ IsMultiplicativeElementWithInverse, IsLeftCoset ], 100, function( g, lc ) return ( Representative(lc)^-1 * g ) in ActingDomain( lc ); end); InstallOtherMethod( \*, "element and LeftCoset", true, [ IsMultiplicativeElementWithInverse, IsLeftCoset ], 0, function( g, lc ) return LeftCoset( g * Representative( lc ), ActingDomain( lc ) ); end); InstallOtherMethod( \^, "LeftCoset and element", true, [ IsLeftCoset, IsMultiplicativeElementWithInverse ], 0, function( lc, g ) return g^-1 * lc; end); InstallMethod( Size, "for a left coset", true, [ IsLeftCoset ], 0, function( lc ) return Size( ActingDomain( lc ) ); end); InstallOtherMethod( IsBiCoset, "for a left coset", true, [ IsLeftCoset ], 0, function( lc ) return IsBiCoset( Inverse( lc ) ); end); InstallOtherMethod( AsSet, "for a left coset", true, [ IsLeftCoset ], 0, function( lc ) local L; L := AsSet( Inverse( lc ) ); return Set( L, g -> g^-1 ); end); InstallOtherMethod( Intersection2, "for two left cosets", true, [ IsLeftCoset, IsLeftCoset ], 0, function( lc1, lc2 ) local L; L := Intersection2( Inverse( lc1 ), Inverse( lc2 ) ); return Set( L, g -> g^-1 ); ## return Inverse( L ); to be used once 4r12 is out end); ############################################################################# ## #F LeftCosets( ) . . . . . . . . . . . . left cosets of U by g \in G #O LeftCosetsNC( ) . . . . . . . . . . . left cosets of U by g \in G ## BindGlobal( "LeftCosets", function( G, U ) if not IsSubset( G, U ) then Error("not contained"); fi; return LeftCosetsNC( G, U ); end ); InstallMethod( LeftCosetsNC, "generic", IsIdenticalObj, [ IsGroup, IsGroup ], 0, function( G, U ) local L; L := RightCosetsNC( G, U ); return List( L, Inverse ); end); utils-0.94/lib/lists.gd0000644000000000000000000000371715174515600011770 0ustar00############################################################################## ## #W lists.gd GAP4 package `Utils' Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## these functions have been transferred from ResClasses ## #F DifferencesList( ) . . . . differences of consecutive list entries #F QuotientsList( ) . . . . . . quotients of consecutive list entries #F FloatQuotientsList( ) . . . . . . . . . . . . dito, but as floats ## DeclareGlobalName( "DifferencesList" ); DeclareGlobalName( "QuotientsList" ); DeclareGlobalName( "FloatQuotientsList" ); ############################################################################# ## this function has been transferred from ResClasses ## #F RandomCombination( S, k ) ## ## Returns a random unordered -tuple of distinct elements of the set . ## DeclareOperation( "RandomCombination", [ IsListOrCollection, IsPosInt ] ); ############################################################################# ## this function has been transferred from RCWA ## #F SearchCycle( ) . . . a utility function for detecting cycles in lists ## DeclareGlobalName( "SearchCycle" ); ############################################################################# ## these functions have been have been transferred from XMod ## #O DistinctRepresentatives( ) #O CommonRepresentatives( , ) #O CommonTransversal( , ) #O IsCommonTransversal( , , ) ## DeclareOperation( "DistinctRepresentatives", [ IsList ] ); DeclareOperation( "CommonRepresentatives", [ IsList, IsList ] ); DeclareOperation( "CommonTransversal", [ IsGroup, IsGroup ] ); DeclareOperation( "IsCommonTransversal", [ IsGroup, IsGroup, IsList ] ); ############################################################################# ## #E lists.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/lists.gi0000644000000000000000000002315315174515600011771 0ustar00############################################################################# ## #W lists.gi GAP4 package `Utils' Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## these functions have been transferred from ResClasses ## #F DifferencesList( ) . . . . differences of consecutive list entries #F QuotientsList( ) . . . . . . quotients of consecutive list entries #F FloatQuotientsList( ) . . . . . . . . . . . . dito, but as floats ## BindGlobal( "DifferencesList", list -> List( [ 2..Length(list) ], pos -> list[ pos ] - list[ pos-1 ] ) ); BindGlobal( "QuotientsList", function( list ) local len, pos, quot; len := Length( list ); quot := ListWithIdenticalEntries( len-1, 0 ); for pos in [1..len-1] do if IsZero( list[pos] ) then quot[pos] := fail; else quot[pos] := list[pos+1]/list[pos]; fi; od; return quot; end ); BindGlobal( "FloatQuotientsList", list -> List( QuotientsList( list ), Float ) ); ############################################################################# ## this function has been transferred from ResClasses ## #M RandomCombination( S, k ) . . . . . . . . . . . . . . . . default method ## InstallMethod( RandomCombination, "default method", ReturnTrue, [ IsListOrCollection, IsPosInt ], function ( S, k ) local c, elm, i; if k > Size(S) then return fail; fi; c := []; for i in [1..k] do repeat elm := Random(S); until not elm in c; Add(c,elm); od; return Set(c); end ); ############################################################################# ## this function has been transferred from RCWA ## #F SearchCycle( ) . a utility function for detecting cycles in lists ## BindGlobal( "SearchCycle", function ( list ) local preperiod, cycle, startpos, mainpart, mainpartdiffs, elms, inds, min, n, d, i, j; n := Length(list); mainpart := list{[Int(n/3)..n]}; elms := Set(mainpart); cycle := [elms[1]]; startpos := Filtered(Positions(list,elms[1]),i->i>n/3); if Length(elms) = 1 then if ValueOption("alsopreperiod") <> true then return cycle; else i := Length(list); repeat i := i - 1; until i = 0 or list[i] <> elms[1]; preperiod := list{[1..i]}; return [preperiod,cycle]; fi; fi; i := 0; repeat i := i + 1; inds := Intersection(startpos+i,[1..n]); if inds = [] then return fail; fi; min := Minimum(list{inds}); Add(cycle,min); startpos := Filtered(startpos,j->j+i<=n and list[j+i]=min); if Length(startpos) <= 1 then return fail; fi; mainpartdiffs := DifferencesList(Intersection(startpos,[Int(n/3)..n])); if mainpartdiffs = [] then return fail; fi; d := Maximum(mainpartdiffs); until Length(cycle) = d; if Minimum(startpos) > n/2 or n-Maximum(startpos)-d+1 > d or list{[Maximum(startpos)+d..n]}<>cycle{[1..n-Maximum(startpos)-d+1]} then return fail; fi; if ValueOption("alsopreperiod") <> true then return cycle; else i := Minimum(startpos) + Length(cycle); repeat i := i - Length(cycle); until i <= 0 or list{[i..i+Length(cycle)-1]} <> cycle; preperiod := list{[1..i+Length(cycle)-1]}; return [preperiod,cycle]; fi; end ); ############################################################################## ## this function has been transferred from XMod ## #M DistinctRepresentatives( ) ## InstallMethod( DistinctRepresentatives, "for a list of sets", true, [ IsList ], 0, function( L ) local n, rep, U, len, i, j, k, used, found, S, T, M, P, x, y, z; if not ( IsList( L ) and ( ForAll( L, IsList ) or ForAll( L, IsSet ) ) ) then Error( "argument should be a list of sets" ); fi; n := Length( L ); U := [1..n]; len := 0 * U; for i in U do S := L[i]; if IsList( S ) then S := Set( S ); fi; len[i] := Length( S ); if ( len[i] = 0 ) then Error( "subsets must be non-empty" ); fi; if not ForAll( S, j -> ( j in U ) ) then Error( "each set must be a subset of [1..n]" ); fi; od; rep := 0 * U; used := 0 * U; rep[1] := L[1][1]; used[ rep[1] ] := 1; for i in [2..n] do found := false; S := L[i]; j := 0; while ( ( j < len[i] ) and not found ) do j := j+1; x := S[j]; if ( used[x] = 0 ) then rep[i] := x; used[x] := i; found := true; fi; od; # construct the graph component T := ShallowCopy( S ); M := List( T ); P := 0 * U; for x in M do P[x] := i; od; j := 0; while not found do j := j+1; x := M[j]; k := used[x]; if ( k = 0 ) then # reassign representatives y := P[x]; while ( y <> i ) do z := rep[y]; rep[y] := x; used[x] := y; x := z; y := P[x]; od; rep[i] := x; used[x] := i; found := true; else for y in L[k] do if not ( y in T ) then Add( M, y ); P[y] := k; T := Union( T, [y] ); fi; od; fi; if ( ( not found ) and ( j = Length( M ) ) ) then Print( "Hall condition not satisfied!\n" ); return false; fi; od; od; return rep; end ); ############################################################################## ## this function has been transferred from XMod ## #M CommonRepresentatives( , ) ## InstallMethod( CommonRepresentatives, "for a pair of lists/sets", true, [ IsList, IsList ], 0, function( J, K ) local U, i, j, k, m, n, lenJ, lenK, S, L, I, rep, perm, common; if not ( ForAll( J, IsList ) or ForAll( J, IsSet ) ) then Error( "first argument should be a list of sets" ); fi; m := Length( J ); if not ( ForAll( K, IsList ) or ForAll( K, IsSet ) ) then Error( "second argument should be a list of sets" ); fi; n := Length( K ); if not ( m = n ) then Error( "lists and have unequal length" ); fi; U := [1..n]; lenJ := 0 * U; lenK := 0 * U; for i in U do S := J[i]; if IsList( S ) then S := Set( S ); fi; lenJ[i] := Length( S ); if ( lenJ[i] = 0 ) then Error( "sets must be non-empty" ); fi; S := K[i]; if IsList( S ) then S := Set( S ); fi; lenK[i] := Length( S ); if ( lenK[i] = 0 ) then Error( "sets must be non-empty" ); fi; od; L := List( U, x -> [ ] ); for i in U do S := J[i]; for j in U do I := Intersection( S, K[j] ); if ( Length( I ) > 0 ) then Add( L[i], j ); fi; od; od; rep := DistinctRepresentatives( L ); perm := PermList( rep ); K := Permuted( K, perm^-1 ); common := 0 * U; for i in U do I := Intersection( J[i], K[i] ); common[i] := I[1]; od; return [ common, rep ]; end ); ############################################################################## ## this function has been transferred from XMod ## #M CommonTransversal ## InstallMethod( CommonTransversal, "for left and right cosets of a subgroup", true, [ IsGroup, IsGroup ], 0, function( G, H ) local R, ER, EL, T; if not IsSubgroup( G, H ) then Error( " must be a subgroup of " ); fi; R := RightCosets( G, H ); ER := List( R, Elements ); EL := List( ER, C -> List( C, Inverse ) ); Info( InfoUtils, 3, "right cosets: ", ER ); Info( InfoUtils, 3, " left cosets: ", EL ); T := CommonRepresentatives( EL, ER ); return T[1]; end ); ############################################################################## ## this function has been transferred from XMod ## #M IsCommonTransversal ## InstallMethod( IsCommonTransversal, "for group, subgroup, list", true, [ IsGroup, IsGroup, IsList ], 0, function( G, H, T ) local eG, eH, oG, oH, g, h, t, pos, ind, found; if not IsSubgroup( G, H ) then Print( "second group must be subgroup of first\n" ); return fail; fi; oG := Size( G ); oH := Size( H ); eG := Elements( G ); eH := Elements( H ); ind := oG/oH; found := 0 * [1..oG]; for t in T do if not ( t in eG ) then Print( "element of T not in G\n" ); return false; fi; for h in eH do g := t*h; pos := Position( eG, g ); found[pos] := found[pos] +1; g := h*t; pos := Position( eG, g ); found[pos] := found[pos] + 1; od; od; for t in [1..oG] do if not ( found[t] = 2 ) then Print( eG[t], " found ", found[t], " times\n" ); return false; fi; od; return true; end ); ############################################################################# ## #E lists.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/magma.gd0000644000000000000000000000320715174515600011706 0ustar00############################################################################## ## #W magma.gd GAP4 package `Utils' Max Horn ## Alexander Hulpke ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function is new in Utils but calls functions which have been ## transferred from the main library or from private code ## #F ConvertToMagmaInputString( ) . . output a string readable by Magma ## DeclareGlobalName( "ConvertToMagmaInputString" ); ############################################################################# ## this function was originally authored by Alexander Hulpke; ## it has been transferred from other.gd in the main library; ## and was originally named MagmaInputString ## #O PermGroupToMagmaFormat( ) ## DeclareOperation( "PermGroupToMagmaFormat", [ IsPermGroup ] ); ############################################################################# ## this function was private code of Max Horn ## #O PcGroupToMagmaFormat( ) ## DeclareOperation( "PcGroupToMagmaFormat", [ IsPcGroup ] ); ############################################################################# ## this function was private code of Frank Lübeck ## #O MatrixGroupToMagmaFormat( ) ## DeclareOperation( "MatrixGroupToMagmaFormat", [ IsMatrixGroup ] ); ############################################################################# ## #E magma.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/magma.gi0000644000000000000000000002034115174515600011711 0ustar00############################################################################# ## #W magma.gi GAP4 package `Utils' Max Horn ## Alexander Hulpke ## Frank Lübeck #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## #F ConvertToMagmaInputString( ) . . output a string readable by Magma ## BindGlobal( "ConvertToMagmaInputString", function ( arg ) local len, obj, s, str; len := Length( arg ); obj := arg[1]; if not IsGroup( obj ) then Error( "input obj should be a group" ); elif IsPcGroup( obj ) then str := PcGroupToMagmaFormat( obj ); elif IsPermGroup( obj ) then str := PermGroupToMagmaFormat( obj ); elif IsMatrixGroup( obj ) then str := MatrixGroupToMagmaFormat( obj ); elif IsFpGroup( obj ) then Print( "no conversion function yet available for fp-groups\n" ); return fail; ## str := FpGroupToMagmaFormat( obj ); else Print( "no conversion function yet available for this group\n" ); return fail; fi; if ( len > 1 ) then s := arg[2]; if IsMatrixGroup( obj ) then str := ReplacedString( str, "sub", Concatenation(s," := sub") ); else str := Concatenation( s, " := ", str ); fi; fi; return str; end ); ############################################################################# ## this function was originally authored by Alexander Hulpke; ## has been transferred from other.gi in the main library; ## and was originally named MagmaInputString ## InstallMethod( PermGroupToMagmaFormat, "perm group", true, [IsPermGroup], 0, function( g ) local s, i, nf; ## s := ShallowCopy(s); ## Append(s,":=PermutationGroup<"); s := "PermutationGroup<"; Append( s, String( LargestMovedPoint(g) ) ); Add( s, '|' ); nf := false; for i in GeneratorsOfGroup(g) do if nf then Append( s, ",\n" ); fi; nf:=true; Append( s, String(i) ); od; Append( s, ">;\n" ); return s; end ); ############################################################################# ## this function was private code of Max Horn ## InstallMethod( PcGroupToMagmaFormat, "pc-group", true, [IsPcGroup], 0, function(G) local str, g, n, r, gens, rels, i, j; g := Pcgs(G); n := Length(g); r := RelativeOrders(g); gens := List(g,String); str := "PolycyclicGroup< "; Append(str, JoinStringsWithSeparator(gens)); Append(str, " |\n"); rels := []; for i in [1..n] do if r[i] = 0 then continue; fi; if IsOne(g[i]^r[i]) then Add(rels, Concatenation(String(g[i]), "^", String(r[i]))); else Add(rels, Concatenation(String(g[i]), "^", String(r[i]), " = ", String(g[i]^r[i]))); fi; od; for i in [2..n] do for j in [1..i-1] do if g[i]*g[j] <> g[j]*g[i] then Add(rels, Concatenation(String(g[i]), "^", String(g[j]), " = ", String(g[i]^g[j]))); if r[j] = 0 then Add(rels, Concatenation(String(g[i]), "^", String(g[j]), "^-1 = ", String(g[i]^(g[j]^-1)))); fi; fi; od; od; Append(str, JoinStringsWithSeparator(rels, ",\n")); Append(str, "\n>;\n"); return str; end ); ############################################################################### ## This function has been converted from private code of Frank Lübeck. ## His GapToMagma(file,mats) wrote Magma code to a file 'file' for the group ## generated by a list 'mats' of matrices over same finite field. ## In this revised form the function inputs a matrix group over a finite ## field and outputs a string which can be read by Magma. ## InstallMethod( MatrixGroupToMagmaFormat, "matrix group over a finite field", true, [ IsMatrixGroup ], 0, function(G) local mats, nr, nc, F, tab, p, q, e, w, wp, pow, zero, one, val, cpn, npl, NmrIter, FinalIter, i, j, cno, isint, matrix, str; mats := GeneratorsOfGroup( G ); F := Field( Flat( mats ) ); if not IsFinite( F ) then TryNextMethod(); fi; p := Characteristic( F ); e := DegreeOverPrimeField( F ); q := Size( F ); w := PrimitiveRoot( F ); zero := Zero( F ); one := One( F ); matrix := mats[1]; nr := Length( matrix ); nc := Length( matrix[1] ); str := Concatenation( "F := ", String(F), ";\n" ); Append( str, Concatenation( "P := GL(", String(nr), ",F);\n" ) ); matrix := mats; if ( e > 1 ) then Append( str, "w := PrimitiveElement(F);\n" ); fi; pow := (q-1)/(p-1); wp := w^pow; tab := [ ]; for i in [1..p-1] do tab[ LogFFE( i*one, wp ) + 1 ] := i; od; if ( p < 10 ) then cpn := 3; elif ( p < 100 ) then cpn := 4; elif ( p < 1000 ) then cpn := 5; elif ( p < 10000 ) then cpn := 6; else cpn := 7; fi; if ( e > 1 ) then cpn := cpn + 2; fi; npl := Int(76/(cpn)); ## should be 78, but it overflowed. Append( str, "gens := [\n"); FinalIter := Length( mats ); NmrIter := 0; for matrix in mats do NmrIter := NmrIter + 1; nr := Length( matrix ); nc := Length( matrix[1] ); Append( str, "P![" ); for i in [1..nr] do cno := 0; for j in [1..nc] do if ( matrix[i][j] = zero ) then val := 0; isint := true; else val := LogFFE( matrix[i][j], w ); if ( val mod pow = 0 ) then val := tab[ LogFFE( matrix[i][j], wp ) + 1]; isint := true; else isint := false; fi; fi; if ( q<10 ) or ( q<100 and val>=10 ) or ( q<1000 and val>=100 ) or ( q<10000 and val>=1000 ) or ( val>=10000 ) then if not (i = 1 and j = 1) then Append( str, "," ); fi; elif ( q<100 ) or ( q<1000 and val>=10 ) or ( q<10000 and val>=100 ) or ( val>=1000 ) then if not (i = 1 and j = 1) then Append( str, " , " ); fi; elif ( q<1000 ) or ( q<10000 and val>=10 ) or ( val>=100 ) then if not (i = 1 and j = 1) then Append( str, " , " ); fi; elif ( q<10000 ) or ( val>=10 ) then if not (i = 1 and j = 1) then Append( str, " , " ); fi; else if not (i = 1 and j = 1) then Append( str, " , " ); fi; fi; if ( e > 1 ) then if isint then Append( str, " " ); else Append( str, "w^" ); fi; fi; Append( str, String(val) ); cno := cno+1; if ( cno>=npl and j FinalIter ) then Append( str, "],\n" ); else Append( str, "]\n" ); fi; od; Append( str, "];\n" ); Append( str, "sub

;\n" ); return str; end ); ############################################################################# ## #E magma.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/maps.gd0000644000000000000000000000437115174515600011567 0ustar00############################################################################## ## #W maps.gd GAP4 package `Utils' Stefan Kohl ## Chris Wensley #Y Copyright (C) 2015-2019, The GAP Group ############################################################################# ## these three functions were in RCWA and were initially transferred but, ## to simplify the situation, just EpimorphismByGenerators has been retained ## #O EpimorphismByGenerators( , ) . epi: gen's of ->gen's of #O EpimorphismByGeneratorsNC( , ) . . NC version as underlying oper #M EpimorphismByGeneratorsNC( , ) . . . . . . . . . . . . for groups ## DeclareOperation( "EpimorphismByGenerators", [ IsDomain, IsDomain ] ); ############################################################################# ## #O Pullback( , ) #A PullbackInfo( ) ## DeclareOperation( "Pullback", [ IsGroupHomomorphism, IsGroupHomomorphism ] ); DeclareAttribute( "PullbackInfo", IsGroup, "mutable" ); ############################################################################# ## #O CentralProduct( , , , ) #A CentralProductInfo( ) ## DeclareOperation( "CentralProduct", [ IsGroup, IsGroup, IsGroup, IsGroupHomomorphism ] ); DeclareAttribute( "CentralProductInfo", IsGroup, "mutable" ); ############################################################################# ## these functions compute idempotent endomorphisms on G with image R ## #O IdempotentEndomorphisms( ) #A IdempotentEndomorphismsWithImage( , ) #A IdempotentEndomorphismsData( ) ## DeclareOperation( "IdempotentEndomorphisms", [ IsGroup ] ); DeclareOperation( "IdempotentEndomorphismsWithImage", [ IsList, IsGroup ] ); DeclareAttribute( "IdempotentEndomorphismsData", IsGroup ); ############################################################################# ## #O DirectProductOfFunctions( , , , ) #O DirectProductOfAutomorphismGroups( , ) ## DeclareOperation( "DirectProductOfFunctions", [ IsGroup, IsGroup, IsGroupHomomorphism, IsGroupHomomorphism ] ); DeclareOperation( "DirectProductOfAutomorphismGroups", [ IsGroup, IsGroup ] ); utils-0.94/lib/maps.gi0000644000000000000000000002113215174515600011566 0ustar00############################################################################# ## #W maps.gi GAP4 package `Utils' Stefan Kohl ## Chris Wensley #Y Copyright (C) 2015-2019, The GAP Group ############################################################################# ## #F EpimorphismByGenerators( , ) . epi: gen's of ->gen's of ## InstallMethod( EpimorphismByGenerators, "for groups", ReturnTrue, [ IsGroup, IsGroup ], 0, function( G, H ) if not ( IsFreeGroup( G ) ) then Print( "Warning: calling GroupHomomorphismByImagesNC without checks\n" ); fi; return GroupHomomorphismByImagesNC( G, H, GeneratorsOfGroup(G), GeneratorsOfGroup(H) ); end ); ############################################################################## ## #M Pullback . . . . . . . . . for two group homomorphisms with a common range ## InstallMethod( Pullback, "for two group homomorphisms", true, [ IsGroupHomomorphism, IsGroupHomomorphism ], 0, function( nu, mu ) local M, N, P, NxM, projM, pmu, projN, pnu, genNxM, e, genL, L, imphi, phi, impsi, psi, info; M := Source( mu ); P := Range( mu ); N := Source( nu ); if not ( Range(nu) = P ) then Error( "homs nu,mu should have a common range" ); fi; NxM := DirectProduct( N, M ); genNxM := GeneratorsOfGroup( NxM ); projN := Projection( NxM, 1 ); pnu := projN * nu; projM := Projection( NxM, 2 ); pmu := projM * mu; if IsFinite( NxM ) then genL := [ ]; L := Subgroup( NxM, [ One(NxM) ] ); for e in NxM do if ImageElm( pnu, e ) = ImageElm( pmu, e ) then if not ( e in L ) then Add( genL, e ); L := Group( genL ); fi; fi; od; else return fail; fi; imphi := List( genL, g -> ImageElm( projN, g ) ); phi := GroupHomomorphismByImages( L, N, genL, imphi ); impsi := List( genL, g -> ImageElm( projM, g ) ); psi := GroupHomomorphismByImages( L, M, genL, impsi ); info := rec( directProduct := NxM, projections := [phi,psi] ); SetPullbackInfo( L, info ); return L; end ); ############################################################################# ## #M CentralProduct( , , , ) ## InstallMethod( CentralProduct, [ "IsGroup", "IsGroup", "IsGroup", "IsGroupHomomorphism" ], function( G1, G2, Z1, Phi ) local gens, imgs, dp, emb1, emb2, N, proj, G; if not ( IsSubset( G1, Z1 ) and IsCentral( G1, Z1 ) ) then Error( " must be a central subgroup of " ); fi; gens:= GeneratorsOfGroup( Z1 ); imgs:= List( gens, x -> (x^-1)^Phi ); if not ( IsSubset( G2, imgs ) and ForAll( imgs, x -> IsCentral( G2, x ) ) ) then Error( " must map to a central subgroup of " ); fi; dp:= DirectProduct( G1, G2 ); emb1:= Embedding( dp, 1 ); emb2:= Embedding( dp, 2 ); N:= SubgroupNC( dp, List( [ 1 .. Length( gens ) ], i -> gens[i]^emb1 * imgs[i]^emb2 ) ); proj:= NaturalHomomorphismByNormalSubgroup( dp, N ); G:= Image( proj ); SetCentralProductInfo( G, rec( projection:= proj, phi:= Phi ) ); return G; end ); ############################################################################## ## #M IdempotentEndomorphisms . . . . . . . . . . . . . . . . . . . for a group #M IdempotentEndomorphismsData . . . . . . . . . . . . . . . . . for a group #M IdempotentEndomorphismsWithImage . . . . . for a group and a chosen image ## InstallMethod( IdempotentEndomorphismsWithImage, "for a list of group generators and a chosen image", [ IsList, IsGroup ], 0, function( genG, R ) local G, numG, r, q, norm, n, reps, i, j, rc; G := Group( genG ); if not IsSubgroup( G, R ) then Error( "R should be a subgroup of G" ); fi; numG := Length( genG ); r := Size( R ); q := Size( G )/r; norm := Filtered( NormalSubgroups( G ), N -> ( Size( N ) = q ) and IsTrivial( Intersection( N, R ) ) ); n := Length( norm ); reps := [ ]; for i in [1..n] do Add( reps, [ ] ); for j in [1..numG] do rc := norm[i]*genG[j]; Add( reps[i], First( rc, g -> g in R ) ); od; od; return reps; end ); InstallMethod( IdempotentEndomorphismsData, "for a group", [ IsGroup ], 0, function( G ) local genG, R, data, images; genG := SmallGeneratingSet( G ); images := [ ]; for R in AllSubgroups( G ) do data := IdempotentEndomorphismsWithImage( genG, R ); if ( data <> [ ] ) then Add( images, data ); fi; od; return rec( gens := genG, images := images ); end ); InstallMethod( IdempotentEndomorphisms, "for a group", [ IsGroup ], 0, function( G ) local data, genG, images, len, L, i, im; data := IdempotentEndomorphismsData( G ); genG := data!.gens; G := Group( genG ); images := data!.images; len := Length( images ); L := [ ]; for i in [1..len] do for im in images[i] do Add( L, GroupHomomorphismByImages( G, G, genG, im ) ); od; od; return L; end ); ############################################################################## ## #M DirectProductOfFunctions . . . . . . for two groups and two homomorphisms ## InstallMethod( DirectProductOfFunctions, "for two groups and two homs", [ IsGroup, IsGroup, IsGroupHomomorphism, IsGroupHomomorphism ], 0, function( G, H, f1, f2 ) local infoG, gpsG, G1, G2, infoH, gpsH, H1, H2, eG1, eG2, eH1, eH2, mgi1, mgi2, genG, imH1, imH2, imH; if not HasDirectProductInfo( G ) and HasDirectProductInfo( H ) then Error( "first two parameters should be direct products" ); fi; infoG := DirectProductInfo( G ); gpsG := infoG!.groups; G1 := gpsG[1]; G2 := gpsG[2]; if not ( ( G1 = Source( f1 ) ) and ( G2 = Source( f2 ) ) ) then Error( "f1,f2 should have source G1,G2" ); fi; eG1 := Embedding( G, 1 ); eG2 := Embedding( G, 2 ); mgi1 := MappingGeneratorsImages( f1 ); mgi2 := MappingGeneratorsImages( f2 ); infoH := DirectProductInfo( H ); gpsH := infoH!.groups; H1 := gpsH[1]; H2 := gpsH[2]; if not ( ( H1 = Range( f1 ) ) and ( H2 = Range( f2 ) ) ) then Error( "f1,f2 should have range H1,H2" ); fi; eH1 := Embedding( H, 1 ); eH2 := Embedding( H, 2 ); genG := Concatenation( List( mgi1[1], g -> ImageElm( eG1, g ) ), List( mgi2[1], g -> ImageElm( eG2, g ) ) ); imH1 := List( mgi1[2], h -> ImageElm( eH1, h ) ); imH2 := List( mgi2[2], h -> ImageElm( eH2, h ) ); imH := Concatenation( imH1, imH2 ); return GroupHomomorphismByImagesNC( G, H, genG, imH ); end ); ############################################################################## ## #M DirectProductOfAutomorphismGroups . . . . . . for two automorphism groups ## InstallMethod( DirectProductOfAutomorphismGroups, "for two groups", [ IsGroup, IsGroup ], 0, function( A1, A2 ) local gen1, gen2, G1, G2, id1, id2, dp, dp1, dp2, gen12, A12, em1, em2, pr1, pr2, info; if not ( IsGroupOfAutomorphisms(A1) and IsGroupOfAutomorphisms(A2) ) then Error( "A1,A2 should be automorphism groups" ); fi; gen1 := GeneratorsOfGroup( A1 ); gen2 := GeneratorsOfGroup( A2 ); G1 := Source( gen1[1] ); G2 := Source( gen2[1] ); if not ( IsGroup( G1 ) and IsGroup( G2 ) ) then Error( "A1,A2 should be automorphism groups of groups G1,G2" ); fi; id1 := IdentityMapping( G1 ); id2 := IdentityMapping( G2 ); dp := DirectProduct( G1, G2 ); dp1 := List( gen1, g -> DirectProductOfFunctions( dp, dp, g, id2 ) ); dp2 := List( gen2, g -> DirectProductOfFunctions( dp, dp, id1, g ) ); gen12 := Concatenation( dp1, dp2 ); A12 := Group( gen12 ); em1 := GroupHomomorphismByImages( A1, A12, gen1, dp1 ); em2 := GroupHomomorphismByImages( A2, A12, gen2, dp2 ); pr1 := GroupHomomorphismByImages( A12, A1, gen12, Concatenation( gen1, List( gen2, g -> id1 ) ) ); pr2 := GroupHomomorphismByImages( A12, A2, gen12, Concatenation( List( gen1, g -> id2 ), gen2 ) ); info := rec( embeddings := [ em1, em2 ], groups := [ A1, A2 ], projections := [ pr1, pr2 ] ); SetDirectProductInfo( A12, info ); return A12; end ); utils-0.94/lib/matrix.gd0000644000000000000000000000102315174515600012122 0ustar00############################################################################ ## #W matrix.gd GAP4 package `Utils' Chris Wensley ## #Y Copyright (C) 2023, The GAP Group ############################################################################# ## This function ... ## #O DirectSumDecompositionMatrices( ) ## DeclareOperation( "DirectSumDecompositionMatrices", [ IsMatrixOrMatrixObj ] ); DeclareOperation( "DirectSumBlock", [ IsMatrixOrMatrixObj, IsInt, IsList, IsList ] ); utils-0.94/lib/matrix.gi0000644000000000000000000001705115174515600012137 0ustar00############################################################################# ## #W matrix.gi GAP4 package `Utils' Pedro A. Garcia-Sanchez ## #Y Copyright (C) 2023, The GAP Group InstallMethod( DirectSumBlock, "for a matrix", [ IsMatrixOrMatrixObj, IsInt, IsList, IsList ], 0, function( M, level, blocks, answer ) local nrM, ncM, nM, nr0, nc0, found, nlzr, nlzc, ntzr, ntzc, nlz, ntz, B, nrB, ncB, nB, nr, nc, i, j, k, i0, j0, nzr, nzc, rest, sub, bls, nrbls, ncbls, pr1, diag0, up0, low0, imax, jmax, len1, ok, ans; nrM := NumberRows( M ); ncM := NumberColumns( M ); nM := Minimum( [ nrM, ncM ] ); ## deal with the diagonal case first if IsDiagonalMatrix( M ) then bls := List( [1..nM], i -> [ [ M[i,i] ] ] ); if ( ncM > nM ) then sub := ExtractSubMatrix( M, [nM], [nM..ncM] )[1]; bls[nM] := [ sub ]; fi; if ( nrM > nM ) then sub := ExtractSubMatrix( M, [nM..nrM], [nM] )[1]; bls[ nM] := [ sub ]; fi; blocks[1] := Concatenation( blocks[1], bls ); ans := Concatenation( blocks[1], blocks[2] ); if not ( ans in answer ) then Add( answer, ans ); fi; return 0; fi; ## check for leading or trailing rows or columns of zeros nlzr := 0; found := false; i := 0; while not found do i := i+1; if ForAll( [1..ncM], j -> M[i,j] = 0 ) then nlzr := nlzr + 1; else found := true; fi; od; nlzc := 0; found := false; j := 0; while not found do j := j+1; if ForAll( [1..nrM], i -> M[i,j] = 0 ) then nlzc := nlzc + 1; else found := true; fi; od; ntzr := 0; found := false; i := nrM + 1; while not found do i := i-1; if ForAll( [1..ncM], j -> M[i,j] = 0 ) then ntzr := ntzr + 1; else found := true; fi; od; ntzc := 0; found := false; j := ncM + 1; while not found do j := j-1; if ForAll( [1..nrM], i -> M[i,j] = 0 ) then ntzc := ntzc + 1; else found := true; fi; od; ## add any leading or trailing blocks [ [0] ] nlz := Minimum( [ nlzr, nlzc ] ); if ( nlz > 0 ) then blocks[1] := Concatenation( blocks[1], ListWithIdenticalEntries( nlz, [ [0] ] ) ); fi; ntz := Minimum( [ ntzr, ntzc ] ); if ( ntz > 0 ) then blocks[2] := Concatenation( ListWithIdenticalEntries( ntz, [ [0] ] ), blocks[2] ); fi; B := ExtractSubMatrix( M, [nlz+1..nrM-ntz], [nlz+1..ncM-ntz] ); nrB := NumberRows( B ); ncB := NumberColumns( B ); nB := Minimum( [nrB, ncB] ); bls := [ ]; if ( nrB = 1 ) or ( ncB = 1 ) then Add( blocks[1], B ); ans := Concatenation( blocks[1], blocks[2] ); if not ( ans in answer ) then Add( answer, ans ); fi; return 0; fi; ## find first non-zero entry in column 1 found := false; pr1 := 0; while ( not found ) and ( pr1 < nrB-1 ) do pr1 := pr1 + 1; found := B[pr1,1] <> 0; od; ## determine ranges for i0 and j0 diag0 := nB+1; i := nB+1; while ( i > 1 ) do i := i-1; if ( B[i,i] <> 0 ) then diag0 := i; fi; od; up0 := [diag0,diag0]; j := 1; found := false; while ( not found ) and ( j < ncB ) do j := j+1; k := Minimum( [ j-1, nrB ] ); for i in [1..k] do if ( B[i,j] <> 0 ) then up0 := [i,j]; found := true; fi; od; od; low0 := [diag0,diag0]; i := 1; found := false; while ( not found ) and ( i < nrB ) do i := i+1; k := Minimum( [ i-1, ncB ] ); for j in [1..k] do if ( B[i,j] <> 0 ) then low0 := [i,j]; found := true; fi; od; od; imax := diag0; jmax := diag0; if ( up0[2] < low0[2] ) then jmax := low0[2] - 1; fi; if ( low0[1] < up0[1] ) then imax := up0[1] - 1; fi; if ( up0[1] < low0[1] ) then imax := Minimum( imax, low0[1] - 1 ); fi; if ( low0[2] < up0[2] ) then jmax := Minimum( jmax, up0[2] - 1 ); fi; if ( low0[1] > nrB ) then imax := up0[1]; fi; if ( up0[1] > ncM ) then jmax := low0[2]; fi; i0 := 0; while ( i0 < imax ) do i0 := i0 + 1; i := i0; j0 := 0; while ( j0 < jmax ) do found := false; j0 := j0 + 1; if ( j0 <= pr1 ) then j := j0; rest := MutableCopyMatrix( B ); nr := NumberRows( rest ); nc := NumberColumns( rest ); i := i0; j := j0; nzr := true; nzc := true; while nzr or nzc do nzr := ForAny( [1..i], i1 -> ForAny( [j+1..nc], j1->rest[i1][j1]<>0 ) ); nzc := ForAny( [i+1..nr], i1 -> ForAny( [1..j], j1->rest[i1][j1]<>0 ) ); if nzr then j := j+1; fi; if nzc then i := i+1; fi; od; bls := List( [1..i], i1 -> rest[i1]{[1..j]} ); ## check if we have filled all columns and rows nzc := ntzc - ntz; nrbls := NumberRows( bls ); ncbls := NumberColumns( bls ); if ( nzc > 0 ) and ( ncbls + nzc = ncB ) then ## add zero columns at the end of the block j := j + nzc; bls := List( [1..i], i1 -> rest[i1]{[1..j]} ); fi; nzr := ntzr - ntz; if ( nzr > 0 ) and ( nrbls + nzr = nrB ) then ## add zero rows at the end of the block i := i + nzr; bls := List( [1..i], i1 -> rest[i1]{[1..j]} ); fi; Add( blocks[1], bls ); len1 := Length( blocks[1] ); rest := List( [i+1..nr], i1 -> rest[i1]{[j+1..nc]} ); if ( rest <> [ ] ) then ok := DirectSumBlock( rest,level+1,blocks,answer ); else ans := Concatenation( blocks[1], blocks[2] ); if not ( ans in answer ) then Add( answer, ans ); fi; fi; blocks := [ blocks[1]{[1..len1-1]}, blocks[2] ]; fi; od; od; return Length( answer ); end ); InstallMethod( DirectSumDecompositionMatrices, "for a matrix", [ IsMatrixOrMatrixObj ], 0, function( M ) local L, blocks, answer, a, ma; blocks := [ [], [] ]; answer := [ ]; L := DirectSumBlock( M, 1, blocks, answer ); ## check that the answers are correct for a in answer do ma := DirectSumMat( a ); if not ( ma = M ) then Display( ma ); Error( "direct sum of decomposition <> original matrix" ); fi; od; return answer; end ); utils-0.94/lib/number.gd0000644000000000000000000000471715174515600012123 0ustar00############################################################################## ## #W number.gd GAP4 package `Utils' Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from RCWA ## #F NextProbablyPrimeInt( ) . . next integer passing `IsProbablyPrimeInt' ## ## Returns the smallest integer larger than which passes GAP's ## probabilistic primality test. ## ## The function `NextProbablyPrimeInt' does the same as `NextPrimeInt', ## except that for reasons of performance it tests numbers only for ## `IsProbablyPrimeInt' instead of `IsPrimeInt'. ## For large , this function is much faster than `NextPrimeInt'. ## DeclareGlobalName( "NextProbablyPrimeInt" ); ############################################################################# ## this function has been transferred from RCWA ## #F AllSmoothIntegers( , ) ## ## Returns the set of all integers in the range [1..] which have only ## prime divisors in the range [2..]. ## DeclareGlobalName( "AllSmoothIntegers" ); ############################################################################# ## this function has been transferred from RCWA ## #F PrimeNumbersIterator( ) #F PrimeNumbersIterator( chunksize ) ## ## Iterator running through the prime numbers in ascending order. ## DeclareGlobalName( "PrimeNumbersIterator" ); ############################################################################# ## this function has been transferred from RCWA ## #F RestrictedPartitionsWithoutRepetitions( , ) ## ## Given a positive integer n and a set of positive integers S, this func- ## tion returns a list of all partitions of n into distinct elements of S. ## The only difference to `RestrictedPartitions' is that no repetitions are ## allowed. ## DeclareGlobalName( "RestrictedPartitionsWithoutRepetitions" ); ############################################################################# ## this function has been transferred from RCWA ## #O AllProducts( , ) . . all products of -tuples of elements of #M AllProducts( , ) . . . . . . . . . . . . . . . . . . . . for lists ## DeclareOperation( "AllProducts", [ IsListOrCollection, IsPosInt ] ); ############################################################################# ## #E number.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/number.gi0000644000000000000000000001511415174515600012121 0ustar00############################################################################# ## #W number.gi GAP4 package `Utils' Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from RCWA ## #F AllSmoothIntegers( , ) #F AllSmoothIntegers( , ) ## BindGlobal( "AllSmoothIntegers", function ( maxp, maxn ) local extend, nums, primes, p; extend := function ( n, mini ) local i; if n > maxn then return; fi; Add(nums,n); for i in [mini..Length(primes)] do extend(primes[i]*n,i); od; end; if IsInt(maxp) then primes := Filtered([2..maxp],IsPrimeInt); elif IsList(maxp) and ForAll(maxp,p->IsInt(p) and IsPrimeInt(p)) then primes := maxp; else return fail; fi; if not IsPosInt(maxn) then return fail; fi; nums := []; extend(1,1); return Set(nums); end ); ############################################################################# ## this function has been transferred from RCWA ## #F NextProbablyPrimeInt( ) . . next integer passing `IsProbablyPrimeInt' ## BindGlobal( "NextProbablyPrimeInt", function ( n ) if -3 = n then n := -2; elif -3 < n and n < 2 then n := 2; elif n mod 2 = 0 then n := n+1; else n := n+2; fi; while not IsProbablyPrimeInt(n) do if n mod 6 = 1 then n := n+4; else n := n+2; fi; od; return n; end ); ############################################################################# ## this function has been transferred from RCWA ## #F RestrictedPartitionsWithoutRepetitions( , ) ## ## Given a positive integer n and a set of positive integers S, this func- ## tion returns a list of all partitions of n into distinct elements of S. ## The only difference to `RestrictedPartitions' is that no repetitions are ## allowed. ## BindGlobal( "RestrictedPartitionsWithoutRepetitions", function ( n, S ) local look, comps; look := function ( comp, remaining_n, remaining_S ) local newcomp, newremaining_n, newremaining_S, part, l; l := Reversed(remaining_S); for part in l do newcomp := Concatenation(comp,[part]); newremaining_n := remaining_n - part; if newremaining_n = 0 then Add(comps,newcomp); else newremaining_S := Set(Filtered(remaining_S, s->s [] then look(newcomp,newremaining_n,newremaining_S); fi; fi; od; end; comps := []; look([],n,S); return comps; end ); ############################################################################# ## this function has been transferred from RCWA ## #F PrimeNumbersIterator( ) #F PrimeNumbersIterator( chunksize ) ## BindGlobal( "PrimeNumbersIterator", function ( arg ) local next, copy, chunksize, maxdiv, nrdivs, offset; if Length(arg) >= 1 and IsPosInt(arg[1]) then chunksize := Maximum(arg[1],100); # must be bigger than largest else chunksize := 10000000; fi; # prime gap in range looped over maxdiv := RootInt(chunksize); offset := List(Filtered([2..maxdiv],IsPrimeInt),p->[p,0]); nrdivs := Length(offset); return IteratorByFunctions( rec( NextIterator := function ( iter ) local sieve, range, p, q, pos, endpos, maxdiv_old, maxdiv, i, j; if iter!.index = 0 then sieve := ListWithIdenticalEntries(iter!.chunksize,0); if iter!.n = 0 then sieve[1] := 1; fi; for i in [1..iter!.nrdivs] do p := iter!.offset[i][1]; if p > iter!.n then pos := 2 * p; else pos := iter!.offset[i][2]; fi; if pos = 0 then pos := p; fi; endpos := pos + Int((iter!.chunksize-pos)/p) * p; if pos <= iter!.chunksize then range := [pos,pos+p..endpos]; if IsRangeRep(range) then ADD_TO_LIST_ENTRIES_PLIST_RANGE(sieve,range,1); else for j in range do sieve[j] := sieve[j] + 1; od; fi; fi; if endpos <= iter!.chunksize then iter!.offset[i][2] := endpos + p - iter!.chunksize; else iter!.offset[i][2] := iter!.offset[i][2] - iter!.chunksize; fi; od; iter!.primepos := Positions(sieve,0); fi; iter!.index := iter!.index + 1; p := iter!.n + iter!.primepos[iter!.index]; iter!.p := p; iter!.pi := iter!.pi + 1; if iter!.index = Length(iter!.primepos) then iter!.index := 0; iter!.n := iter!.n + iter!.chunksize; maxdiv_old := iter!.maxdiv; iter!.maxdiv := RootInt(iter!.n + iter!.chunksize); for q in Filtered([maxdiv_old+1..iter!.maxdiv],IsPrimeInt) do Add(iter!.offset,[q,(q-iter!.n) mod q]); od; iter!.nrdivs := Length(iter!.offset); fi; return p; end, ShallowCopy := function ( iter ) return rec( chunksize := iter!.chunksize, n := iter!.n, p := iter!.p, pi := iter!.pi, index := iter!.index, primepos := ShallowCopy(iter!.primepos), nrdivs := iter!.nrdivs, maxdiv := iter!.maxdiv, offset := StructuralCopy(iter!.offset) ); end, IsDoneIterator := ReturnFalse, chunksize := chunksize, n := 0, p := 0, pi := 0, index := 0, primepos := [], nrdivs := nrdivs, maxdiv := maxdiv, offset := offset ) ); end ); ############################################################################# ## this function has been transferred from RCWA ## #M AllProducts( , ) . . all products of -tuples of elements of #M AllProducts( , ) . . . . . . . . . . . . . . . . . . . . for lists ## InstallMethod( AllProducts, "for lists (RCWA)", ReturnTrue, [ IsList, IsPosInt ], 0, function(l,k) return List(Tuples(l,k),Product); end ); ############################################################################# ## #E number.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/print.gd0000644000000000000000000000164015174515600011757 0ustar00############################################################################## ## #W print.gd GAP4 package `Utils' Chris Wensley ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################## ## added global function and methods to print subsets of lists/iterators ## DeclareGlobalName( "PrintSelection" ); DeclareOperation( "PrintSelectionFromList", [ IsList, IsPosInt, IsPosInt, IsPosInt ] ); DeclareOperation( "PrintSelectionFromIterator", [ IsIterator, IsPosInt, IsPosInt, IsAdditiveElement ] ); DeclareOperation( "PrintSelectionFromListByList", [ IsList, IsList ] ); DeclareOperation( "PrintSelectionFromIteratorByList", [ IsIterator, IsList ] ); ############################################################################# ## #E print.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/print.gi0000644000000000000000000001117115174515600011764 0ustar00############################################################################# ## #W print.gi GAP4 package `Utils' Chris Wensley ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## these operations have not been transferred from any other package ## #M PrintSelection( ) #M PrintSelectionFromList( , , , ) #M PrintSelectionFromIterator( , , , ) ## BindGlobal( "PrintSelection", function( arg ) local nargs, obj, first, step, last, L, ok; nargs := Length( arg ); obj := arg[1]; if ( ( nargs = 1 ) or ( nargs > 4 ) ) then Error( "expecting 2, 3 or 4 arguments" ); elif ( nargs = 2 ) then L := arg[2]; if IsList( L ) then ok := ForAll( L, IsPosInt ); if not ok then Error( "L must only contain positive integers" ); fi; if IsList( obj ) then PrintSelectionFromListByList( obj, L ); elif IsIterator( obj ) then PrintSelectionFromIteratorByList( obj, L ); else PrintSelectionFromIteratorByList( Iterator( obj ), L ); fi; else Error( "second argument not a list" ); fi; else first := arg[2]; step := arg[3]; if ( nargs = 3 ) then if IsList( obj ) then last := Length( obj ); else last := infinity; fi; else last := arg[4]; fi; if IsList( obj ) then PrintSelectionFromList( obj, first, step, last ); elif IsIterator( obj ) then PrintSelectionFromIterator( obj, first, step, last ); else PrintSelectionFromIterator( Iterator( obj ), first, step, last ); fi; fi; end ); InstallMethod( PrintSelectionFromList, "generic method for lists", true, [ IsList, IsPosInt, IsPosInt, IsPosInt ], 0, function( L, first, step, last ) local len, i; len := Minimum( Length( L ), last ); if ( first <= len ) then Print( first, " : ", L[first], "\n" ); len := len-first; i := first; while ( len >= step ) do i := i+step; Print( i, " : ", L[i], "\n" ); len := len-step; od; fi; end ); InstallOtherMethod( PrintSelectionFromIterator, "generic method for iterators", true, [ IsIterator, IsPosInt, IsPosInt, IsAdditiveElement ], 0, function( iter0, first, step, last ) local iter, pos, i, x; if ( last < first ) then Error( "expecting first <= last" ); fi; iter := ShallowCopy( iter0 ); i := 0; while( ( i < first ) and not IsDoneIterator( iter ) ) do i := i+1; x := NextIterator( iter ); od; if ( i = first ) then pos := first; Print( pos, " : ", x, "\n" ); fi; while ( not IsDoneIterator( iter ) and ( pos < last ) ) do while ( not IsDoneIterator( iter ) and ( pos < last ) ) do i := 0; while( ( i ) ## ## This auxiliary function assigns the record components of to ## global variables with the same names. ## DeclareGlobalName( "AssignGlobals" ); ############################################################################# ## this function has been contributed by Christopher Jefferson ## #F OptionRecordWithDefaults( arg1, arg2, ..., ) ## ## This auxiliary function assigns the record components of to ## global variables with the same names. ## DeclareGlobalName( "OptionRecordWithDefaults" ); ############################################################################# ## #E record.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/record.gi0000644000000000000000000000433715174515600012114 0ustar00############################################################################## ## #W record.gi GAP4 package `Utils' Sebastian Gutsche ## Max Horn ## Stefan Kohl #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from RCWA ## #F AssignGlobals( ) ## ## This auxiliary function assigns the record components of ## to global variables with the same names. ## BindGlobal( "AssignGlobals", function ( record ) local names, name; names := RecNames(record); for name in names do if IsBoundGlobal(name) then if IsReadOnlyGlobal(name) then MakeReadWriteGlobal(name); Info(InfoWarning,1,"The read-only global variable ",name, " has been overwritten."); else Info(InfoUtils,1,"The global variable ",name, " has been overwritten."); fi; UnbindGlobal(name); fi; BindGlobal(name,record.(name)); MakeReadWriteGlobal(name); od; Print("The following global variables have been assigned:\n", Set(names),"\n"); end ); BindGlobal( "OptionRecordWithDefaults", function(default, useroptions) local name, ret; ret := rec(); if IsList(useroptions) then if IsEmpty(useroptions) then return default; elif Length(useroptions) = 1 then useroptions := useroptions[1]; else ErrorNoReturn("Too many arguments for function"); fi; fi; if not IsRecord(useroptions) then ErrorNoReturn("Options should be a record"); fi; ret := ShallowCopy(default); for name in RecNames(useroptions) do if not IsBound(default.(name)) then ErrorNoReturn(Concatenation("Unknown option: " , name)); else ret.(name) := useroptions.(name); fi; od; return ret; end); ############################################################################# ## #E record.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/start.gd0000644000000000000000000000455215174515600011765 0ustar00############################################################################## ## #W start.gd GAP4 package `Utils' Chris Wensley ## #Y Copyright (C) 2015-2022, The GAP Group DeclareInfoClass( "InfoUtils" ); ## these version numbers refer to the latest package releases ## containing the code which is to be transferred UtilsPackageVersions := [ "autodoc", "2016.01.31", ## latest is 2017.09.08 "resclasses", "4.2.5", ## latest is 4.7.1, 18/12/17 "rcwa", "4.1.5" ## latest is 4.6.2, 26/06/18 ]; ## (04/09/18) removed QPA from this list - no functions transferred ## (02/06/18) removed xmod from this list ## functions being transferred cannot be used until the Home packages have ## been loaded: when this has been done the following variable is set true UtilsLoadingComplete := false; ############################################################################# ## #F OKtoReadFromUtils( ) . . . tests whether name still contains the ## code to be transferred to Utils #F OKtoReadFromUtilsSpec( , ) . . . special case of above ## BindGlobal( "OKtoReadFromUtils", function( Name ) local name, ver, ver0, pos, ok; name := LowercaseString( Name ); pos := Position( UtilsPackageVersions, name ); if ( pos = fail ) then Error( "package 'name' not in the list UtilsPackageVersions" ); fi; ver0 := UtilsPackageVersions[ pos+1 ]; ver := InstalledPackageVersion( name ); ok := ( ( ver = fail ) ## name is not installed on the system or ( ver > ver0 ) ); ## name still contains the code return ok; end ); BindGlobal( "OKtoReadFromUtilsSpec", function( Name, oldver ) local name, ver, pos, ok; name := LowercaseString( Name ); pos := Position( UtilsPackageVersions, name ); if ( pos = fail ) then Error( "package 'name' not in the list UtilsPackageVersions" ); fi; ver := InstalledPackageVersion( name ); ok := ( ( ver = fail ) ## name is not installed on the system or ( ver > oldver ) ); ## name still contains the code return ok; end ); ############################################################################# ## #E start.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/string.gd0000644000000000000000000000136515174515600012135 0ustar00############################################################################## ## #W string.gd GAP4 package `Utils' Sebastian Gutsche ## Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from ResClasses ## #F BlankFreeString( ) . . . . . . . . . . . . . string without blanks ## DeclareGlobalName( "BlankFreeString" ); ############################################################################# ## #E string.gd . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/lib/string.gi0000644000000000000000000000154715174515600012144 0ustar00############################################################################# ## #W string.gi GAP4 package `Utils' Sebastian Gutsche ## Stefan Kohl ## #Y Copyright (C) 2015-2025, The GAP Group ############################################################################# ## this function has been transferred from ResClasses ## #F BlankFreeString( ) . . . . . . . . . . . . . string without blanks ## BindGlobal( "BlankFreeString", function ( obj ) local str; str := String(obj); RemoveCharacters(str," "); return str; end ); ############################################################################# ## #E string.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/makedoc.g0000644000000000000000000000236115174515600011315 0ustar00## makedoc.g for the package Utils ## This builds the documentation of the Utils package. ## Needs: GAPDoc & AutoDoc packages, latex, pdflatex, mkindex ## call this with GAP from within the package root directory ## LoadPackage( "GAPDoc" ); LoadPackage( "AutoDoc" ); AutoDoc( rec( extract_examples := true, scaffold := rec( ## MainPage := false, includes := [ "intro.xml", "print.xml", "lists.xml", "number.xml", "groups.xml", "matrix.xml", "iterator.xml", "record.xml", "download.xml", "gslp.xml", "others.xml", "obsolete.xml", "transfer.xml" ], bib := "bib.xml", entities := rec( AutoDoc := "AutoDoc", ResClasses := "ResClasses", RCWA := "RCWA", XMod := "XMod", Home := "Home", Magma := "{\\sf Magma}", MathJax := "{\\sf MathJax}" ) ) )); utils-0.94/read.g0000644000000000000000000000157515174515600010633 0ustar00############################################################################# ## #W read.g The Utils package Chris Wensley ## #Y Copyright (C) 2015-2023, The GAP Group, ## ## read the actual code ReadPackage( "utils", "lib/files.gi" ); ReadPackage( "utils", "lib/groups.gi" ); ReadPackage( "utils", "lib/iterator.gi" ); ReadPackage( "utils", "lib/latex.gi" ); ReadPackage( "utils", "lib/lcset.gi" ); ReadPackage( "utils", "lib/lists.gi" ); ReadPackage( "utils", "lib/magma.gi" ); ReadPackage( "utils", "lib/maps.gi" ); ReadPackage( "utils", "lib/matrix.gi" ); ReadPackage( "utils", "lib/number.gi" ); ReadPackage( "utils", "lib/print.gi" ); ReadPackage( "utils", "lib/record.gi" ); ReadPackage( "utils", "lib/string.gi" ); ReadPackage( "utils", "lib/gslp.gi" ); if IsBound(DOWNLOAD_FROM_UTILS) then ReadPackage( "utils", "lib/download.gi" ); fi; utils-0.94/tst/0000755000000000000000000000000015174515600010352 5ustar00utils-0.94/tst/download.tst0000644000000000000000000001006415174515600012716 0ustar00#@local meths, i, urls, pair, url, expected, res1, good1, n, file, res2, good2, contents, r, res3, good3, bad ############################################################################ ## #W download.tst Utils Package Thomas Breuer ## #Y Copyright (C) 2022, The GAP Group ## gap> START_TEST( "download.tst" ); ## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true ## Test the available Download methods gap> meths:= List( Filtered( Download_Methods, r -> r.isAvailable() ), > ShallowCopy );; gap> for i in [ 1 .. Length( meths ) ] do > meths[i].position:= String( i ); > od; gap> urls:= [ # a http url that gets redirected to https > [ "http://www.gap-system.org/index.html", true ], > # a http url that works as such > [ "http://www.math.rwth-aachen.de/index.html", true ], > # a https url that exists > [ "https://www.gap-system.org/index.html", true ], > # a https url that does not exist > [ "https://www.gap-system.org/indexxxxx.html", false ], > ];; ## The problem is that the methods do not behave consistently ## in the case of failure. ## (Well, they even do not agree what failure means.) ## The test results depend on which methods are available at runtime, ## which makes them useless as automatic tests. ## Thus we test only working http and https urls. gap> urls:= urls{ [ 2, 3 ] };; gap> for pair in urls do > url:= pair[1]; > expected:= pair[2]; > res1:= List( meths, r -> [ r.download( url, rec() ), r.position ] );; > good1:= Filtered( res1, r -> r[1].success = true );; > if expected = false and Length( good1 ) > 0 then > Print( "success for url ", url, "?\n" ); > fi; > n:= Length( Set( good1, r -> r[1].result ) ); > if n > 1 then > Print( "different results (", n, ") for url ", url, "\n" ); > fi; > file:= Filename( DirectoryTemporary(), "test" ); > res2:= List( meths, > r -> [ r.download( url, > rec( target:= Concatenation( file, r.position ) ) ), > r.position ] );; > good2:= Filtered( res2, r -> r[1].success = true );; > if expected = false and Length( good2 ) > 0 then > Print( "success for url ", url, "?\n" ); > fi; > if List( good1, x -> x[2] ) <> List( good2, x -> x[2] ) then > Print( "different success cases for url ", url, ":\n", > List( good1, x -> x[2] ), " vs. ", List( good2, x -> x[2] ), > "\n" ); > fi; > if Length( good1 ) > 0 then > contents:= good1[1][1].result; > for r in good2 do > if contents <> StringFile( Concatenation( file, r[2] ) ) then > Print( "different files and contents for url ", url, "\n" ); > fi; > od; > fi; > res3:= List( meths, > r -> [ r.download( url, > rec( maxTime:= 10 ) ), > r.position ] );; > good3:= Filtered( res3, r -> r[1].success = true );; > if expected = false and Length( good3 ) > 0 then > Print( "success for url ", url, "?\n" ); > fi; > # The IO and wget based methods are available. > # They cannot handle the 'maxTime' parameter. > bad:= Filtered( meths, > x -> StartsWith( x.name, "via SingleHTTPRequest" ) or > StartsWith( x.name, "via wget" ) ); > bad:= List( bad, x -> x.position ); > good1:= Filtered( good1, x -> not x[2] in bad ); > if List( good1, x -> x[2] ) <> List( good3, x -> x[2] ) then > Print( "different success cases for url ", url, ":\n", > List( good1, x -> x[2] ), " vs. ", List( good3, x -> x[2] ), > "\n" ); > fi; > od; ## test timeout gap> res1:= Download( "https://httpbun.com/delay/3", rec( maxTime:= 1 ) );; gap> res1.success = false; true gap> res1:= Download( "https://httpbun.com/delay/3", rec( maxTime:= 5 ) );; gap> res1.success = true; true ## gap> STOP_TEST( "download.tst" ); utils-0.94/tst/groups.tst0000644000000000000000000002126615174515600012434 0ustar00#@local A, a, ac9, aq8, b, c, c1, c2, c2c6, c3, c4, c4c3, c6, c9 #@local cp1, cp2, cp3, d, D12, d8, data, dp, epi, f, f1, f2, G, g #@local g1, g2, g3, genA, gens, i, idcopy, idem, idemc2, idemim, idemim2 #@local im2, image2, images, imi, info, info2, info3, lc1, lc2, lc3, lc4 #@local len, lfs, ok, Pfi, phi, q8, rc1, rc4, s3, S4, s4, UFS, ufs ############################################################################## ## #W groups.tst Utils Package ## #Y Copyright (C) 2015-2022, The GAP Group ## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true ## SubSection 5.1.1 gap> Comm( [ (1,2), (2,3) ] ); (1,2,3) gap> Comm( [(1,2),(2,3),(3,4),(4,5),(5,6)] ); (1,5,6) gap> Comm(Comm(Comm(Comm((1,2),(2,3)),(3,4)),(4,5)),(5,6)); ## the same (1,5,6) ## SubSection 5.1.2 gap> D12 := DihedralGroup( 12 ); gap> SetName( D12, "D12" ); gap> a := D12.1;; b := D12.2;; gap> IsCommuting( a, b ); false ## SubSection 5.1.3 gap> ListOfPowers( 2, 20 ); [ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 ] gap> ListOfPowers( (1,2,3)(4,5), 12 ); [ (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), (), (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), () ] gap> ListOfPowers( D12.2, 6 ); [ f2, f3, f2*f3, f3^2, f2*f3^2, of ... ] ## SubSection 5.1.4 gap> GeneratorsAndInverses( D12 ); [ f1, f2, f3, f1, f2*f3^2, f3^2 ] gap> GeneratorsAndInverses( SymmetricGroup(5) ); [ (1,2,3,4,5), (1,2), (1,5,4,3,2), (1,2) ] ## SubSection 5.1.5 gap> UFS := UpperFittingSeries( D12 );; gap> Set( GeneratorsOfGroup( UFS[2] ) ); [ f3, f2*f3 ] gap> Set( GeneratorsOfGroup( UFS[3] ) ); [ f1, f3, f2*f3 ] gap> LowerFittingSeries( D12 ); [ D12, Group([ f3 ]), Group([ ]) ] gap> FittingLength( D12 ); 2 gap> S4 := SymmetricGroup( 4 );; gap> ufs := UpperFittingSeries( S4 );; gap> List( ufs, StructureDescription ); [ "1", "C2 x C2", "A4", "S4" ] gap> lfs := LowerFittingSeries( S4 );; gap> List( lfs, StructureDescription ); [ "S4", "A4", "C2 x C2", "1" ] gap> FittingLength( S4); 3 ## SubSection 5.2.1 gap> lc1 := LeftCoset( (1,2,3), Group( [ (1,2), (3,4) ] ) ); LeftCoset((1,2,3),Group([ (1,2), (3,4) ])) gap> Representative( lc1 ); (1,2,3) gap> ActingDomain( lc1 ); Group([ (1,2), (3,4) ]) gap> AsSet( lc1 ); [ (2,3), (2,4,3), (1,2,3), (1,2,4,3) ] gap> (1,2,3) in lc1; true gap> lc2 := (2,4,3) * lc1; LeftCoset((1,2,4),Group([ (1,2), (3,4) ])) gap> lc3 := lc1^(2,3,4);; gap> lc2 = lc3; true ## SubSection 5.2.2 gap> rc1 := Inverse( lc1 ); RightCoset(Group([ (1,2), (3,4) ]),(1,3,2)) gap> rc4 := RightCoset( Group( (1,2), (2,3) ), (3,4) ); RightCoset(Group([ (1,2), (2,3) ]),(3,4)) gap> lc4 := Inverse( rc4 ); LeftCoset((3,4),Group([ (1,2), (2,3) ])) gap> Intersection( lc2, lc4 ); [ (2,3,4), (1,2,3,4) ] ## SubSection 5.3.1 gap> G := Group( (1,2,3), (3,4,5), (5,6,7), (7,8,9) );; gap> phi := EpimorphismByGenerators( FreeGroup("a","b","c","d"), G ); [ a, b, c, d ] -> [ (1,2,3), (3,4,5), (5,6,7), (7,8,9) ] gap> PreImagesRepresentativeNC( phi, (1,2,3,4,5,6,7,8,9) ); d*c*b*a gap> a := G.1;; b := G.2;; c := G.3;; d := G.4;; gap> d*c*b*a; (1,2,3,4,5,6,7,8,9) gap> ## note that it is easy to produce nonsense: gap> epi := EpimorphismByGenerators( Group((1,2,3)), Group((8,9)) ); Warning: calling GroupHomomorphismByImagesNC without checks [ (1,2,3) ] -> [ (8,9) ] gap> IsGroupHomomorphism( epi ); true gap> Image(epi,(1,2,3)); () gap> Image(epi,(1,3,2)); (8,9) ## SubSection 5.3.2 gap> s4 := Group( (1,2),(2,3),(3,4) );; gap> s3 := Group( (5,6),(6,7) );; gap> c3 := Subgroup( s3, [ (5,6,7) ] );; gap> f := GroupHomomorphismByImages( s4, s3, > [(1,2),(2,3),(3,4)], [(5,6),(6,7),(5,6)] );; gap> i := GroupHomomorphismByImages( c3, s3, [(5,6,7)], [(5,6,7)] );; gap> Pfi := Pullback( f, i ); Group([ (2,3,4)(5,7,6), (1,2)(3,4) ]) gap> StructureDescription( Pfi ); "A4" gap> info := PullbackInfo( Pfi ); rec( directProduct := Group([ (1,2), (2,3), (3,4), (5,6,7) ]), projections := [ [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (2,3,4), (1,2)(3,4) ], [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (5,7,6), () ] ] ) gap> g := (1,2,3)(5,6,7);; gap> ImageElm( info!.projections[1], g ); (1,2,3) gap> ImageElm( info!.projections[2], g ); (5,6,7) gap> dp := info!.directProduct;; gap> a := ImageElm( Embedding( dp, 1 ), (1,4,3) );; gap> b := ImageElm( Embedding( dp, 2 ), (5,7,6) );; gap> a*b in Pfi; true ## SubSection 5.3.3 gap> g1 := DihedralGroup( 8 ); gap> c1 := Centre( g1 ); Group([ f3 ]) gap> cp1 := CentralProduct( g1, g1, c1, IdentityMapping( c1 ) ); Group([ f1, f2, f5, f3, f4, f5 ]) gap> IdGroup( cp1 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) ); true gap> g2 := QuaternionGroup( 8 ); gap> c2 := Centre( g2 ); Group([ y2 ]) gap> cp2 := CentralProduct( g2, g2, c2, IdentityMapping( c2 ) ); Group([ f1, f2, f5, f3, f4, f5 ]) gap> IdGroup( cp2 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) ); true gap> info2 := CentralProductInfo( cp2 ); rec( phi := IdentityMapping( Group([ y2 ]) ), projection := [ f1, f2, f3, f4, f5, f6 ] -> [ f1, f2, f5, f3, f4, f5 ] ) gap> Source( Embedding( Source( info2.projection ), 1 ) ) = g2; true gap> g3 := SymmetricGroup( 3 ); Sym( [ 1 .. 3 ] ) gap> c3 := TrivialSubgroup( g3 ); Group(()) gap> cp3 := CentralProduct( g3, g3, c3, IdentityMapping( c3 ) ); Group([ (1,2,3), (1,2), (4,5,6), (4,5) ]) gap> info3 := CentralProductInfo( cp3 ); rec( phi := IdentityMapping( Group(()) ), projection := IdentityMapping( Group([ (1,2,3), (1,2), (4,5,6), (4,5) ]) ) ) gap> Source( Embedding( Source( info3.projection ), 1 ) ) = g3; true ## SubSection 5.3.4 gap> gens := [ (1,2,3,4), (1,2)(3,4) ];; gap> d8 := Group( gens );; gap> SetName( d8, "d8" ); gap> c2 := Subgroup( d8, [ (2,4) ] );; gap> idemc2 := IdempotentEndomorphismsWithImage( gens, c2 );; gap> idcopy := [ [ (), (2,4) ], [ (2,4), () ] ];; gap> Sort( idemc2 ); gap> Sort( idcopy ); gap> idemc2 = idcopy; true gap> ## depending on packages loaded, the order of images can vary gap> ## so we introduce a convoluted way of checking the images gap> data := IdempotentEndomorphismsData( d8 );; gap> data!.gens; [ (1,2,3,4), (1,2)(3,4) ] gap> images := data!.images;; gap> len := Length( images ); 6 gap> image2 := [ [ [ (), () ] ], [ [ (), (2,4) ], [ (2,4), () ] ], > [ [ (), (1,3) ], [ (1,3), () ] ], > [ [ (), (1,2)(3,4) ], [ (1,2)(3,4), (1,2)(3,4) ] ], > [ [ (), (1,4)(2,3) ], [ (1,4)(2,3), (1,4)(2,3) ] ], > [ [ (1,2,3,4), (1,2)(3,4) ] ] ];; gap> ok := true;; gap> ## new in gapdev - the test 'im in im2' is parsed before the for loop gap> ## so that im2 is an 'unbound global variable' if not declared first gap> im2 := [ ];; gap> for i in [1..len] do > imi := images[i]; > im2 := image2[i]; > if not ForAll( imi, im -> ( im in im2 ) ) then > ok := false; > fi; > od; gap> ok; true gap> List( images, L -> Length(L) ); [ 1, 2, 2, 2, 2, 1 ] gap> idem := IdempotentEndomorphisms( d8 );; gap> idemim := List( idem, m -> MappingGeneratorsImages(m)[2] );; gap> idemim2 := > [ [ (), () ], [ (), (2,4) ], [ (2,4), () ], [ (), (1,3) ], [ (1,3), () ], > [ (), (1,2)(3,4) ], [ (1,2)(3,4), (1,2)(3,4) ], [ (), (1,4)(2,3) ], > [ (1,4)(2,3), (1,4)(2,3) ], [ (1,2,3,4), (1,2)(3,4) ] ];; gap> ForAll( idemim, m -> ( m in idemim2 ) ); true ## SubSection 5.3.5 gap> c4 := Group( (1,2,3,4) );; gap> c2 := Group( (5,6) );; gap> f1 := GroupHomomorphismByImages( c4, c2, [(1,2,3,4)], [(5,6)] );; gap> c3 := Group( (1,2,3) );; gap> c6 := Group( (1,2,3,4,5,6) );; gap> f2 := GroupHomomorphismByImages( c3, c6, [(1,2,3)], [(1,3,5)(2,4,6)] );; gap> c4c3 := DirectProduct( c4, c3 ); Group([ (1,2,3,4), (5,6,7) ]) gap> c2c6 := DirectProduct( c2, c6 ); Group([ (1,2), (3,4,5,6,7,8) ]) gap> f := DirectProductOfFunctions( c4c3, c2c6, f1, f2 ); [ (1,2,3,4), (5,6,7) ] -> [ (1,2), (3,5,7)(4,6,8) ] gap> ImageElm( f, (1,4,3,2)(5,7,6) ); (1,2)(3,7,5)(4,8,6) ## SubSection 5.3.6 gap> c9 := Group( (1,2,3,4,5,6,7,8,9) );; gap> ac9 := AutomorphismGroup( c9 );; gap> q8 := QuaternionGroup( IsPermGroup, 8 );; gap> aq8 := AutomorphismGroup( q8 );; gap> A := DirectProductOfAutomorphismGroups( ac9, aq8 ); gap> genA := GeneratorsOfGroup( A );; gap> G := Source( genA[1] ); Group([ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13) (14,15,16,17) ]) gap> a := genA[1]*genA[5]; [ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13)(14,15,16,17) ] -> [ (1,3,5,7,9,2,4,6,8), (10,16,12,14)(11,15,13,17), (10,11,12,13)(14,15,16,17) ] gap> ImageElm( a, (1,9,8,7,6,5,4,3,2)(10,14,12,16)(11,17,13,15) ); (1,8,6,4,2,9,7,5,3)(10,16,12,14)(11,15,13,17) utils-0.94/tst/gslp.tst0000644000000000000000000000453315174515600012060 0ustar00#@local prg, data ############################################################################ ## #W gslp.tst Utils Package Thomas Breuer ## #Y Copyright (C) 2026, The GAP Group ## gap> START_TEST( "gslp.tst" ); # gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true # test inconsistent input for `GeneralizedStraightLineProgram` gap> GeneralizedStraightLineProgram( "union", [[[1,2]]], 1 ); Error, usage: GeneralizedStraightLineProgram( [, ] ) or General\ izedStraightLineProgram( , ) gap> GeneralizedStraightLineProgram( "union", [] ); Error, must be a nonempty list gap> GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 2 ] ] ); Error, all entries of must have the same input number gap> GeneralizedStraightLineProgram( "compose", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 2 ] ] ); Error, inputs and outputs for are not compatible gap> GeneralizedStraightLineProgram( "other", [[[1,2]]] ); Error, must be one of "union", "compose" # test cases of `NrOutputsOfGeneralizedStraightLineProgram` gap> prg:= StraightLineProgram( [ [1,2,2,3], [3,-1] ], 2 );; gap> NrOutputsOfGeneralizedStraightLineProgram( prg ); 1 # test `false` cases of `IsInternallyConsistent` gap> prg:= GeneralizedStraightLineProgram( "compose", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; gap> ResetFilterObj( prg, HasNrInputsOfGeneralizedStraightLineProgram ); gap> SetNrInputsOfGeneralizedStraightLineProgram( prg, 3 ); gap> IsInternallyConsistent( prg ); false gap> data:= ShallowCopy( DataOfGeneralizedStraightLineProgram( prg ) );; gap> data[1]:= "other";; gap> ResetFilterObj( prg, HasDataOfGeneralizedStraightLineProgram ); gap> SetDataOfGeneralizedStraightLineProgram( prg, data ); gap> IsInternallyConsistent( prg ); false # `ViewString` and `String` gap> ViewString( StraightLineProgram( [[[1,2]]], 1 ) ); "" gap> ViewString( GeneralizedStraightLineProgram( "union", [ [[[1,2]]] ] ) ); "" gap> String( StraightLineProgram( [[[1,2]]], 1 ) ); "StraightLineProgram( [ [ [ 1, 2 ] ] ], 1 )" gap> String( GeneralizedStraightLineProgram( "union", [ [[[1,2]]] ] ) ); "GeneralizedStraightLineProgram( \"union\", [ StraightLineProgram( [ [ 1, 2 ] \ ], 1 ) ] )" # gap> STOP_TEST( "gslp.tst" ); utils-0.94/tst/iterator.tst0000644000000000000000000000525015174515600012741 0ustar00#@local c3c3, cart, G, h, it1, it2, iter, iter0, iter4, iterL #@local L, n, pairs0, pairs4, pairsL, s3, s4 ############################################################################## ## #W iterator.tst Utils Package ## #Y Copyright (C) 2015-2022, The GAP Group ## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true ## SubSection 7.1.1 gap> G := SmallGroup( 6,1);; gap> s3 := Group( (5,6), (6,7) );; gap> iter := AllIsomorphismsIterator( G, s3 );; gap> NextIterator( iter ); [ f1, f2 ] -> [ (6,7), (5,6,7) ] gap> n := AllIsomorphismsNumber( G, s3 ); 6 gap> AllIsomorphisms( G, s3 ); [ [ f1, f2 ] -> [ (6,7), (5,6,7) ], [ f1, f2 ] -> [ (5,7), (5,6,7) ], [ f1, f2 ] -> [ (5,6), (5,7,6) ], [ f1, f2 ] -> [ (6,7), (5,7,6) ], [ f1, f2 ] -> [ (5,7), (5,7,6) ], [ f1, f2 ] -> [ (5,6), (5,6,7) ] ] gap> iter := AllIsomorphismsIterator( G, s3 );; gap> for h in iter do Print( ImageElm( h, G.1 ) = (6,7), ", " ); od; true, false, false, true, false, false, gap> s4 := Group( (1,2),(2,3),(3,4) );; gap> AllIsomorphismsNumber( s3, s4 ); 0 gap> AllIsomorphisms( s3, s4 ); [ ] ## SubSection 7.1.2 gap> c3c3 := Group( (1,2,3), (4,5,6) );; gap> iter := AllSubgroupsIterator( c3c3 ); gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od; Group( () ) Group( [ (4,5,6) ] ) Group( [ (1,2,3) ] ) Group( [ (1,2,3)(4,5,6) ] ) Group( [ (1,3,2)(4,5,6) ] ) Group( [ (4,5,6), (1,2,3) ] ) ## Subsection 7.2.1 gap> it1 := Iterator( [ 1, 2, 3 ] );; gap> it2 := Iterator( [ 4, 5, 6 ] );; gap> iter := CartesianIterator( it1, it2 );; gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od; [ 1, 4 ] [ 1, 5 ] [ 1, 6 ] [ 2, 4 ] [ 2, 5 ] [ 2, 6 ] [ 3, 4 ] [ 3, 5 ] [ 3, 6 ] gap> ## try some trivial cases gap> iter0 := IteratorList( [ ] );; gap> iter4 := IteratorList( [ 4 ] );; gap> cart := CartesianIterator( iter0, iter0 );; gap> IsDoneIterator( cart ); true gap> cart := CartesianIterator( iter0, iter4 );; gap> IsDoneIterator( cart ); true gap> cart := CartesianIterator( iter4, iter0 );; gap> IsDoneIterator( cart ); true ## Subsection 6.2.2 gap> L := [6,7,8,9];; gap> iterL := IteratorList( L );; gap> pairsL := UnorderedPairsIterator( iterL );; gap> while not IsDoneIterator(pairsL) do Print(NextIterator(pairsL),"\n"); od; [ 6, 6 ] [ 6, 7 ] [ 7, 7 ] [ 6, 8 ] [ 7, 8 ] [ 8, 8 ] [ 6, 9 ] [ 7, 9 ] [ 8, 9 ] [ 9, 9 ] gap> iter4 := IteratorList( [ 4 ] ); gap> pairs4 := UnorderedPairsIterator(iter4); gap> NextIterator( pairs4 ); [ 4, 4 ] gap> IsDoneIterator( pairs4 ); true gap> pairs0 := UnorderedPairsIterator( iter0 );; gap> IsDoneIterator( pairs0 ); true utils-0.94/tst/lcset.tst0000644000000000000000000001377515174515600012235 0ustar00#@local a4, k4, rc, lc, a, b, d, f, g, h, H1, H2, H3, K1, K2, K3, lc1, lc4, M, matcyc, rc5, s ############################################################################# ## adapted from gapdev/tst/tstinstall/cset.tst for left cosets ## ## test of group intersection and LeftCoset ## gap> START_TEST("lcset.tst"); # section 5.2.1: basic coset tests gap> a4 := Group( (1,2,3), (2,3,4) );; SetName( a4, "a4" ); gap> k4 := Group( (1,2)(3,4), (1,3)(2,4) );; SetName( k4, "k4" ); gap> rc := RightCosets( a4, k4 ); [ RightCoset(k4,()), RightCoset(k4,(2,3,4)), RightCoset(k4,(2,4,3)) ] gap> lc := LeftCosets( a4, k4 ); [ LeftCoset((),k4), LeftCoset((2,4,3),k4), LeftCoset((2,3,4),k4) ] gap> AsSet( lc[2] ); [ (2,4,3), (1,2,3), (1,3,4), (1,4,2) ] gap> LeftCoset( (1,4,2), k4 ) = lc[2]; true gap> Representative( lc[2] ); (2,4,3) gap> ActingDomain( lc[2] ); k4 gap> (1,4,3) in lc[3]; true gap> (1,2,3)*lc[2] = lc[3]; true gap> lc[2]^(1,3,2) = lc[3]; true # section 5.2.2 gap> Inverse( rc[3] ) = lc[3]; true gap> Inverse( lc[2] ) = rc[2]; true # many further tests gap> LeftCoset( (1,2), a4 ) = LeftCoset( (2,3), a4 ); true gap> () in LeftCoset( (1,2), Group([(1,2,3,4)]) ); false gap> (1,2) in LeftCoset( (5,6), SymmetricGroup(12) ); true gap> Length( LeftCosets( SymmetricGroup(5), AlternatingGroup(4) ) ); 10 gap> (1,2,3) * LeftCoset( (), AlternatingGroup(4) ) > = LeftCoset( (), AlternatingGroup(4) ); true gap> IsBiCoset( LeftCoset( (1,2), AlternatingGroup(6) ) ); true gap> IsBiCoset( LeftCoset( (1,7), AlternatingGroup(6) ) ); false gap> IsLeftCoset( LeftCoset( (1,2,3), MathieuGroup(12) ) ); true gap> g:=SymmetricGroup(3);; gap> h:=Group((1,2));; gap> List(LeftCosets(g,h), SSortedList); [ [ (), (1,2) ], [ (1,3,2), (1,3) ], [ (2,3), (1,2,3) ] ] # test intersecting permutation cosets gap> H1 := Group( [ (), (2,7,6)(3,4,5), (1,2,7,5,6,4,3) ] );; gap> H2 := Group( [ (1,2,3,4,5,6,7), (5,6,7) ] );; gap> H3 := Group( [ (1,2,3,4,5,6,8), (1,3,2,6,4,5), (1,6)(2,3)(4,5)(7,8) ] );; gap> AsSet( LeftCoset( (1,5,7,3)(4,6), H1 ) ) = > Intersection( LeftCoset( (3,6)(4,7), H2 ), > LeftCoset( (1,5,3,8,6,7), H3 ) ); true gap> AsSet( LeftCoset( (1,2,5,6,7,4,3,8), Group(()) ) ) = > Intersection( LeftCoset( (1,5,6,7)(3,8,4), > Group( [ (1,4)(2,5), (1,3,5)(2,4,6), (1,5)(2,4)(3,6) ] ) ), > LeftCoset( (1,2,6,8)(3,7), > Group( [ (3,4), (5,6,7,8), (5,6) ] ) ) ); true gap> [] = Intersection( LeftCoset( (), SymmetricGroup(4) ), > LeftCoset( (4,7), SymmetricGroup([3..6]) ) ); true gap> [] = Intersection( LeftCoset( (4,5), Group( [ (1,2,3,4,5) ] ) ), > LeftCoset( (), AlternatingGroup(4) ) ); true gap> AsSet( LeftCoset( (7,9), SymmetricGroup([3..5]) ) ) = > Intersection( LeftCoset( (1,2)(7,9), SymmetricGroup(5) ), > LeftCoset( (7,9), SymmetricGroup([3..7]) ) ); true gap> [] = Intersection( LeftCoset( (1,4)(3,5), Group([(1,2,3,4,5)]) ), > LeftCoset( (), SymmetricGroup(3) ) ); true gap> AsSet( LeftCoset( (4,5), Group( [(5,6)] ) ) ) = > Intersection( LeftCoset( (), SymmetricGroup(6) ), > LeftCoset( (4,5), SymmetricGroup([5..8]) ) ); true gap> AsSet( LeftCoset( (1,4,5), SymmetricGroup(5) ) ) = > Intersection( LeftCoset( (), SymmetricGroup(5) ), > LeftCoset( (1,2), SymmetricGroup(5) ) ); true gap> [] = > Intersection( LeftCoset( (1,2), Group( (1,2,3,4,5) ) ), > LeftCoset( (), Group( (1,2,3,5,4) ) ) ); true gap> [] = > Intersection( LeftCoset( (1,2,3), Group( (1,2,3,4,5) ) ), > LeftCoset( (), Group( (1,2,3,5,4) ) ) ); true gap> AsSet( LeftCoset( (1,2), Group( [ (1,2,3,5,4) ] ) ) ) = > Intersection( LeftCoset( (), SymmetricGroup(7) ), > LeftCoset( (1,2), Group( (1,2,3,5,4) ) ) ); true gap> [] = > Intersection( LeftCoset( (), SymmetricGroup([3..7]) ), > LeftCoset( (1,2), Group( (1,2,3,5,4) ) ) ); true # test trivial cases gap> Intersection( LeftCoset( (), Group([],()) ), > LeftCoset( (1,2), Group([],()) ) ) = []; true gap> Intersection( LeftCoset( (), Group( (1,2,3) ) ), > LeftCoset( (1,2), Group( (1,2,3) ) ) ) = []; true gap> Intersection( LeftCoset( (), AlternatingGroup(6) ), > LeftCoset( (1,2), AlternatingGroup(6) ) ) = []; true gap> Intersection( LeftCoset( (1,2), AlternatingGroup([1..5]) ), > LeftCoset( (1,2), AlternatingGroup([6..10]) ) ) > = AsSet( LeftCoset( (1,2), Group(()) ) ); true #coset of pc-group gap> d := DihedralGroup( 24 ); gap> List( GeneratorsOfGroup(d), x -> Order(x) ); [ 2, 12, 6, 3 ] gap> s := Subgroup( d, [ d.1, d.4 ] );; gap> SetName( s, "s" ); gap> lc4 := LeftCoset( d.2, s ); LeftCoset(,s) gap> AsSet( lc4 ); [ f2, f2*f4, f1*f2*f3, f2*f4^2, f1*f2*f3*f4, f1*f2*f3*f4^2 ] gap> d.2 * d.4 in lc4; true # coset of fp-group gap> f := FreeGroup(2);; a := f.1;; b := f.2;; gap> g := f / [ a^5, b^4, a*b*a^2*b^3 ]; gap> Size(g); 20 gap> h := Subgroup( g, [g.1] );; gap> SetName( h, "C5" ); gap> rc5 := LeftCoset( g.2, h ); LeftCoset(,C5) gap> AsSet( rc5 ); [ f2, f2*f1, f2*f1^2, f2*f1^3, f2*f1^4 ] # test intersection non-permutation cosets gap> K1 := Group( [ [[-1,0],[0,-1]] ] );; gap> K2 := Group( [ [[-1,0],[0,1]], [[0,1],[1,0]] ] );; gap> K3 := Group( [ - IdentityMat(2) ] );; gap> AsSet( LeftCoset( [ [0,1],[1,0] ], K1 ) ) = > Intersection( LeftCoset( IdentityMat(2), K2 ), > LeftCoset( [[0,1],[1,0]], K1 ) ); true gap> AsSet( LeftCoset( [[0,1],[1,0]], K3 ) ) = > Intersection( LeftCoset( [[0,-1],[-1,0]], K3 ), > LeftCoset( [[0,1],[1,0]], K3 ) ); true gap> matcyc := CyclicGroup( IsMatrixGroup, GF(3), 4 );; gap> M := GeneratorsOfGroup( matcyc )[1];; gap> lc1 := LeftCoset( M^2, matcyc );; gap> Representative(lc1); [ [ 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3) ], [ 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0 ], [ Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3) ] ] # gap> STOP_TEST("lcset.tst", 1); utils-0.94/tst/lists.tst0000644000000000000000000000767615174515600012264 0ustar00#@local C, c4, d16, gens, i, J, K, L, n, P, trans ############################################################################## ## #W lists.tst Utils Package ## #Y Copyright (C) 2015-2022, The GAP Group ## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true ## SubSection 3.1.1 gap> List( [1..12], n->n^3 ); [ 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728 ] gap> DifferencesList( last ); [ 7, 19, 37, 61, 91, 127, 169, 217, 271, 331, 397 ] gap> DifferencesList( last ); [ 12, 18, 24, 30, 36, 42, 48, 54, 60, 66 ] gap> DifferencesList( last ); [ 6, 6, 6, 6, 6, 6, 6, 6, 6 ] gap> L := [ 0 ];; gap> DifferencesList( L ); [ ] gap> L := [ ];; gap> DifferencesList( L ); [ ] ## SubSection 3.1.2 gap> List( [0..10], n -> Factorial(n) ); [ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 ] gap> QuotientsList( last ); [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] gap> L := [ 1, 3, 5, -1, -3, -5 ];; gap> QuotientsList( L ); [ 3, 5/3, -1/5, 3, 5/3 ] gap> FloatQuotientsList( L ); [ 3., 1.66667, -0.2, 3., 1.66667 ] gap> QuotientsList( [ 2, 1, 0, -1, -2 ] ); [ 1/2, 0, fail, 2 ] gap> FloatQuotientsList( [1..10] ); [ 2., 1.5, 1.33333, 1.25, 1.2, 1.16667, 1.14286, 1.125, 1.11111 ] gap> Product( last ); 10. ## SubSection 3.1.3 gap> L := [1..20];; L[1]:=13;; gap> for i in [1..19] do > if IsOddInt(L[i]) then L[i+1]:=3*L[i]+1; else L[i+1]:=L[i]/2; fi; > od; gap> L; [ 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4 ] gap> SearchCycle( L ); [ 1, 4, 2 ] gap> n := 1;; L := [n];; gap> for i in [1..100] do n:=(n^2+1) mod 1093; Add(L,n); od; gap> L; [ 1, 2, 5, 26, 677, 363, 610, 481, 739, 715, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004 ] gap> C := SearchCycle( L ); [ 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754 ] gap> P := Positions( L, 157 ); [ 14, 26, 38, 50, 62, 74, 86, 98 ] gap> Length( C ); DifferencesList( P ); 12 [ 12, 12, 12, 12, 12, 12, 12 ] ## SubSection 3.1.4 ## this manual example not tested as answers vary from run to run ## gap> RandomCombination( [1..49], 6 ); ## [ 3, 5, 21, 24, 27, 31 ] ## SubSection 3.2.1 gap> J := [ [1,2,3], [3,4], [3,4], [1,2,4] ];; gap> DistinctRepresentatives( J ); [ 1, 3, 4, 2 ] gap> K := [ [3,4], [1,2], [2,3], [2,3,4] ];; gap> CommonRepresentatives( J, K ); [ [ 3, 3, 3, 1 ], [ 1, 3, 4, 2 ] ] gap> d16 := DihedralGroup( IsPermGroup, 16 ); SetName( d16, "d16" ); Group([ (1,2,3,4,5,6,7,8), (2,8)(3,7)(4,6) ]) gap> c4 := Subgroup( d16, [ d16.1^2 ] ); SetName( c4, "c4" ); Group([ (1,3,5,7)(2,4,6,8) ]) gap> RightCosets( d16, c4 ); [ RightCoset(c4,()), RightCoset(c4,(2,8)(3,7)(4,6)), RightCoset(c4,(1,8,7,6,5, 4,3,2)), RightCoset(c4,(1,8)(2,7)(3,6)(4,5)) ] gap> trans := CommonTransversal( d16, c4 ); [ (), (2,8)(3,7)(4,6), (1,2,3,4,5,6,7,8), (1,2)(3,8)(4,7)(5,6) ] gap> IsCommonTransversal( d16, c4, trans ); true ## SubSection 3.3.1 gap> gens := GeneratorsOfGroup( DihedralGroup(12) ); [ f1, f2, f3 ] gap> String( gens ); "[ f1, f2, f3 ]" gap> BlankFreeString( gens ); "[f1,f2,f3]" ############################################################################# ## #E lists.tst . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/tst/loadall.g0000755000000000000000000000123615174515600012137 0ustar00############################################################################## ## #W loadall.g Utils Package Chris Wensley ## #Y Copyright (C) 2015-2016, The GAP Group ## ## first make sure that, if the transferred code has not been read, ## then the appropriate packages are loaded. if not UtilsLoadingComplete then len := Length( UtilsPackageVersions ); j := 0; while ( j < len ) do j := j+1; name := UtilsPackageVersions[j]; if not OKtoReadFromUtils( name ) then LoadPackage( name ); fi; j := j+1; od; UtilsLoadingComplete := true; fi; utils-0.94/tst/matrix.tst0000644000000000000000000000513015174515600012411 0ustar00#@local M6, L6, M4, L4, M8, L8, L, A, M3, L3, M5, L5; ############################################################################## ## #W matrix.tst Utils Package ## #Y Copyright (C) 2015-2023, The GAP Group ## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true ## SubSection 9.1.1 gap> M6 := [ [1,2,0,0,0,0], [3,4,0,0,0,0], [5,6,0,0,0,0], > [0,0,9,0,0,0], [0,0,0,1,2,3], [0,0,0,4,5,6] ];; gap> Display( M6 ); [ [ 1, 2, 0, 0, 0, 0 ], [ 3, 4, 0, 0, 0, 0 ], [ 5, 6, 0, 0, 0, 0 ], [ 0, 0, 9, 0, 0, 0 ], [ 0, 0, 0, 1, 2, 3 ], [ 0, 0, 0, 4, 5, 6 ] ] gap> L6 := DirectSumDecompositionMatrices( M6 ); [ [ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ], [ [ 9 ] ], [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] ] ] gap> M4 := [ [0,3,0,0], [0,0,0,0], [0,0,0,0], [0,0,4,0] ];; gap> Display( M4 ); [ [ 0, 3, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 4, 0 ] ] gap> L4 := DirectSumDecompositionMatrices( M4 ); [ [ [ [ 0, 3 ] ], [ [ 0, 0 ], [ 0, 0 ], [ 4, 0 ] ] ], [ [ [ 0, 3 ], [ 0, 0 ] ], [ [ 0, 0 ], [ 4, 0 ] ] ], [ [ [ 0, 3 ], [ 0, 0 ], [ 0, 0 ] ], [ [ 4, 0 ] ] ] ] gap> for L in L4 do > A := DirectSumMat( L );; > if ( A = M4 ) then Print( "yes, A = M4\n" ); fi; > od; yes, A = M4 yes, A = M4 yes, A = M4 gap> M8 := DirectSumMat( M4, M4 );; gap> Display( M8 ); [ [ 0, 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, 4, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 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, 4, 0 ] ] gap> L8 := DirectSumDecompositionMatrices( M8 );; gap> Length( L8 ); 16 gap> M3 := [ [0,0,0,7,0,0,0], [0,0,0,0,8,0,0], [0,0,0,0,0,9,0] ];; gap> Display( M3 ); [ [ 0, 0, 0, 7, 0, 0, 0 ], [ 0, 0, 0, 0, 8, 0, 0 ], [ 0, 0, 0, 0, 0, 9, 0 ] ] gap> L3 := DirectSumDecompositionMatrices( M3 ); [ [ [ [ 0, 0, 0, 7 ] ], [ [ 8 ] ], [ [ 9, 0 ] ] ] ] gap> M5 := [ [1,2,0,0,0], [3,4,0,0,0], [0,0,0,0,0], > [0,0,0,6,7], [0,0,0,8,9] ];; gap> Display(M5); [ [ 1, 2, 0, 0, 0 ], [ 3, 4, 0, 0, 0 ], [ 0, 0, 0, 0, 0 ], [ 0, 0, 0, 6, 7 ], [ 0, 0, 0, 8, 9 ] ] gap> L5 := DirectSumDecompositionMatrices( M5 ); [ [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 0 ] ], [ [ 6, 7 ], [ 8, 9 ] ] ] ] ############################################################################# ## #E matrix.tst . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/tst/number.tst0000644000000000000000000000542315174515600012402 0ustar00#@local i, iter, n, p, sum ############################################################################## ## #W number.tst Utils Package Stefan Kohl ## #Y Copyright (C) 2015-2022, The GAP Group ## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true ## SubSection 4.1.1 gap> AllSmoothIntegers( 3, 1000 ); [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96, 108, 128, 144, 162, 192, 216, 243, 256, 288, 324, 384, 432, 486, 512, 576, 648, 729, 768, 864, 972 ] gap> AllSmoothIntegers( [5,11,17], 1000 ); [ 1, 5, 11, 17, 25, 55, 85, 121, 125, 187, 275, 289, 425, 605, 625, 935 ] gap> Length( last ); 16 gap> List( [3..20], n -> Length( AllSmoothIntegers( [5,11,17], 10^n ) ) ); [ 16, 29, 50, 78, 114, 155, 212, 282, 359, 452, 565, 691, 831, 992, 1173, 1374, 1595, 1843 ] ## SubSection 4.1.2 gap> AllProducts([1..4],3); [ 1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16, 2, 4, 6, 8, 4, 8, 12, 16, 6, 12, 18, 24, 8, 16, 24, 32, 3, 6, 9, 12, 6, 12, 18, 24, 9, 18, 27, 36, 12, 24, 36, 48, 4, 8, 12, 16, 8, 16, 24, 32, 12, 24, 36, 48, 16, 32, 48, 64 ] gap> Set(last); [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 64 ] gap> AllProducts( [(1,2,3),(2,3,4)], 2 ); [ (2,4,3), (1,2)(3,4), (1,3)(2,4), (1,3,2) ] ## SubSection 4.1.3 gap> RestrictedPartitions( 20, [4..10] ); [ [ 4, 4, 4, 4, 4 ], [ 5, 5, 5, 5 ], [ 6, 5, 5, 4 ], [ 6, 6, 4, 4 ], [ 7, 5, 4, 4 ], [ 7, 7, 6 ], [ 8, 4, 4, 4 ], [ 8, 6, 6 ], [ 8, 7, 5 ], [ 8, 8, 4 ], [ 9, 6, 5 ], [ 9, 7, 4 ], [ 10, 5, 5 ], [ 10, 6, 4 ], [ 10, 10 ] ] gap> RestrictedPartitionsWithoutRepetitions( 20, [4..10] ); [ [ 10, 6, 4 ], [ 9, 7, 4 ], [ 9, 6, 5 ], [ 8, 7, 5 ] ] gap> RestrictedPartitionsWithoutRepetitions( 10^2, List([1..10], n->n^2 ) ); [ [ 100 ], [ 64, 36 ], [ 49, 25, 16, 9, 1 ] ] ## SubSection 4.1.4 gap> n := 2^251;; gap> NextProbablyPrimeInt( n ); 3618502788666131106986593281521497120414687020801267626233049500247285301313 ## SubSection 4.1.6 gap> iter := PrimeNumbersIterator();; gap> for i in [1..100] do p := NextIterator(iter); od; gap> p; 541 gap> sum := 0;; gap> ## "prime number race" 1 vs. 3 mod 4 gap> for p in PrimeNumbersIterator() do > if p <> 2 then sum := sum + E(4)^(p-1); fi; > if sum > 0 then break; fi; > od; gap> p; 26861 ## this final example takes quite a while: use examples/number.g ## gap> sum := 0;; ## gap> ## "prime number race" 1 vs. 5 mod 8 ## gap> for p in PrimeNumbersIterator() do ## > if p mod 8 in [1,5] then sum := sum + E(4)^((p-1)/2); fi; ## > if sum > 0 then break; fi; ## > od; ## gap> p; ## 588067889 ############################################################################# ## #E number.tst . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/tst/others.tst0000644000000000000000000000426215174515600012416 0ustar00#@local a, F2, f, g, relq8, q8, M, s1, n1, n2, N, s2; ############################################################################ ## #W others.tst Utils Package ## #Y Copyright (C) 2015-2025, The GAP Group ## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true ## SubSection 10.1.1 ## this manual example is not tested to avoid creating files triv.* ## gap> LogTo( "triv.log" ); ## gap> a := 33^5; ## 39135393 ## gap> LogTo(); ## gap> Log2HTML( "triv.log" ); ## SubSection 10.2.1 gap> IntOrInfinityToLaTeX( 10^3 ); "1000" gap> IntOrInfinityToLaTeX( infinity ); "\\infty" ## SubSection 10.2.2 gap> LaTeXStringFactorsInt( Factorial(12) ); "2^{10} \\cdot 3^5 \\cdot 5^2 \\cdot 7 \\cdot 11" ## SubSection 10.3.1 gap> ## permutation groups gap> ConvertToMagmaInputString( Group( (1,2,3,4,5), (3,4,5) ) ); "PermutationGroup<5|(1,2,3,4,5),\n(3,4,5)>;\n" gap> ConvertToMagmaInputString( Group( (1,2,3,4,5) ), "c5" ); "c5 := PermutationGroup<5|(1,2,3,4,5)>;\n" gap> ## pc-group gap> ConvertToMagmaInputString( DihedralGroup( IsPcGroup, 10 ) ); "PolycyclicGroup< f1,f2 |\nf1^2,\nf2^5,\nf2^f1 = f2^4\n>;\n" gap> ## fp-group gap> F2 := FreeGroup( 2 );; gap> f := F2.1;; g := F2.2;; gap> relq8 := [ f^4, g^4, f*g*f*g^-1, f^2*g^2 ];; gap> q8 := F2/relq8;; gap> ConvertToMagmaInputString( q8 ); no conversion function yet available for fp-groups fail gap> ## matrix group gap> M := GL(2,5);; Size(M); 480 gap> s1 := ConvertToMagmaInputString( M ); "F := GF(5);\nP := GL(2,F);\ngens := [\nP![2,0,0,1],\nP![4,1,4,0]\n];\nsub

;\n" gap> Print( s1 ); F := GF(5); P := GL(2,F); gens := [ P![2,0,0,1], P![4,1,4,0] ]; sub

; gap> n1 := [ [ Z(9)^0, Z(9)^0 ], [ Z(9)^0, Z(9) ] ];; gap> n2 := [ [ Z(9)^0, Z(9)^3 ], [ Z(9)^4, Z(9)^2 ] ];; gap> N := Group( n1, n2 );; Size( N ); 5760 gap> s2 := ConvertToMagmaInputString( N, "gpN" );; gap> Print( s2 ); F := GF(3^2); P := GL(2,F); w := PrimitiveElement(F); gens := [ P![ 1, 1, 1,w^1], P![ 1,w^3, 2,w^2] ]; gpN := sub

; ############################################################################# ## #E others.tst . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/tst/print.tst0000644000000000000000000000202715174515600012243 0ustar00#@local L, s5 ############################################################################## ## #W print.tst Utils Package ## #Y Copyright (C) 2015-2022, The GAP Group ## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true ## SubSection 2.1.1 gap> L := List( [1..20], n -> n^5 );; gap> PrintSelection( L, [18..20] ); 18 : 1889568 19 : 2476099 20 : 3200000 gap> PrintSelection( L, 2, 9 ); 2 : 32 11 : 161051 20 : 3200000 gap> PrintSelection( L, 2, 3, 11 ); 2 : 32 5 : 3125 8 : 32768 11 : 161051 gap> s5 := SymmetricGroup( 5 );; gap> PrintSelection( s5, [30,31,100,101] ); 30 : (1,5)(3,4) 31 : (1,5,2) 100 : (1,4,3) 101 : (1,4)(3,5) gap> PrintSelection( s5, 1, 30 ); 1 : () 31 : (1,5,2) 61 : (1,2,3) 91 : (1,3,5,2,4) gap> PrintSelection( s5, 9, 11, 43 ); 9 : (2,5,3) 20 : (2,4) 31 : (1,5,2) 42 : (1,5,2,3,4) ############################################################################# ## #E print.tst . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here utils-0.94/tst/record.tst0000644000000000000000000000454115174515600012370 0ustar00#@local r, defaults, PrintDimensions, mydim ############################################################################## ## #W record.tst Utils Package ## #Y Copyright (C) 2015-2022, The GAP Group ## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true ## SubSection 8.1.1 gap> r := rec( a := 1, b := 2, c := 3 );; gap> AssignGlobals( r ); The following global variables have been assigned: [ "a", "b", "c" ] gap> [ a, b, c ]; [ 1, 2, 3 ] ## SubSection 8.2.1 gap> defaults := rec( a := 1, b := 2, c := 3 );; gap> OptionRecordWithDefaults( defaults, rec( a := 6) ); rec( a := 6, b := 2, c := 3 ) gap> OptionRecordWithDefaults( defaults, rec( b := 7, c := 8 ) ); rec( a := 1, b := 7, c := 8 ) gap> OptionRecordWithDefaults( defaults, [ ] ); rec( a := 1, b := 2, c := 3 ) gap> OptionRecordWithDefaults( defaults, [ rec( c := 8 ) ] ); rec( a := 1, b := 2, c := 8 ) gap> OptionRecordWithDefaults( defaults, rec( d := 9 ) ); Error, Unknown option: d gap> OptionRecordWithDefaults( defaults, [ rec( b := 7 ), rec( c := 8 ) ] ); Error, Too many arguments for function gap> OptionRecordWithDefaults( defaults, 5 ); Error, Options should be a record gap> OptionRecordWithDefaults( defaults, [6,7,8] ); Error, Too many arguments for function gap> PrintDimensions := function( arg ) > local nargs, dim, order, V, L, len, K, i; > nargs := Length( arg ); > dim := [ arg[1]!.height, arg[1]!.width, arg[1]!.depth ]; > order := rec( h := 1, w := 2, d := 3 ); > V := [ "height", "width", "depth" ]; > if ( nargs > 1 ) and IsRecord( arg[2] ) then > order := OptionRecordWithDefaults( order, arg[2] ); > fi; > L := [ order!.h, order!.w, order!.d ]; > len := Length( L ); > K := [ 1..len ]; > SortParallel( L, K ); > Print( "dimensions: " ); > Print( V[K[1]], " = ", dim[K[1]], ", " ); > Print( V[K[2]], " = ", dim[K[2]], ", " ); > Print( V[K[3]], " = ", dim[K[3]], "\n" ); > end;; gap> mydim := rec( height := 45, width := 31, depth := 17 ); rec( depth := 17, height := 45, width := 31 ) gap> PrintDimensions( mydim ); dimensions: height = 45, width = 31, depth = 17 gap> PrintDimensions( mydim, rec( h:=3, w:=1, d:=2 ) ); dimensions: width = 31, depth = 17, height = 45 utils-0.94/tst/testall.g0000755000000000000000000000147615174515600012205 0ustar00############################################################################ ## #W testall.g Utils Package Chris Wensley ## #Y Copyright (C) 2015-2023, The GAP Group ## LoadPackage( "utils" ); ## first make sure that, if the transferred code has not been read, ## then the appropriate packages are loaded. if not UtilsLoadingComplete then ReadPackage( "utils", "tst/loadall.g" ); fi; # Create/update the testfiles containing the manual examples. # (The "nopdf" option informs AutoDoc that it can skip generating # PDF files, which makes this much faster) ReadPackage( "utils", "makedoc.g" : nopdf ); dir := DirectoriesPackageLibrary( "utils", "tst" ); TestDirectory(dir, rec(exitGAP := true, testOptions:=rec(compareFunction := "uptowhitespace"))); FORCE_QUIT_GAP(1); utils-0.94/tst/utils01.tst0000644000000000000000000000104515174515600012407 0ustar00# utils, chapter 1 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils01.tst"); # doc/intro.xml:23-26 gap> LoadPackage( "utils" ); true # gap> STOP_TEST("utils01.tst", 1); utils-0.94/tst/utils02.tst0000644000000000000000000000207515174515600012414 0ustar00# utils, chapter 2 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils02.tst"); # doc/print.xml:47-78 gap> L := List( [1..20], n -> n^5 );; gap> PrintSelection( L, [18..20] ); 18 : 1889568 19 : 2476099 20 : 3200000 gap> PrintSelection( L, 2, 9 ); 2 : 32 11 : 161051 20 : 3200000 gap> PrintSelection( L, 2, 3, 11 ); 2 : 32 5 : 3125 8 : 32768 11 : 161051 gap> s5 := SymmetricGroup( 5 );; gap> PrintSelection( s5, [30,31,100,101] ); 30 : (1,5)(3,4) 31 : (1,5,2) 100 : (1,4,3) 101 : (1,4)(3,5) gap> PrintSelection( s5, 1, 30 ); 1 : () 31 : (1,5,2) 61 : (1,2,3) 91 : (1,3,5,2,4) gap> PrintSelection( s5, 9, 11, 43 ); 9 : (2,5,3) 20 : (2,4) 31 : (1,5,2) 42 : (1,5,2,3,4) # gap> STOP_TEST("utils02.tst", 1); utils-0.94/tst/utils03.tst0000644000000000000000000000727715174515600012426 0ustar00# utils, chapter 3 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils03.tst"); # doc/lists.xml:30-39 gap> List( [1..12], n->n^3 ); [ 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728 ] gap> DifferencesList( last ); [ 7, 19, 37, 61, 91, 127, 169, 217, 271, 331, 397 ] gap> DifferencesList( last ); [ 12, 18, 24, 30, 36, 42, 48, 54, 60, 66 ] gap> DifferencesList( last ); [ 6, 6, 6, 6, 6, 6, 6, 6, 6 ] # doc/lists.xml:56-72 gap> List( [0..10], n -> Factorial(n) ); [ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 ] gap> QuotientsList( last ); [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] gap> L := [ 1, 3, 5, -1, -3, -5 ];; gap> QuotientsList( L ); [ 3, 5/3, -1/5, 3, 5/3 ] gap> FloatQuotientsList( L ); [ 3., 1.66667, -0.2, 3., 1.66667 ] gap> QuotientsList( [ 2, 1, 0, -1, -2 ] ); [ 1/2, 0, fail, 2 ] gap> FloatQuotientsList( [1..10] ); [ 2., 1.5, 1.33333, 1.25, 1.2, 1.16667, 1.14286, 1.125, 1.11111 ] gap> Product( last ); 10. # doc/lists.xml:90-116 gap> L := [1..20];; L[1]:=13;; gap> for i in [1..19] do > if IsOddInt(L[i]) then L[i+1]:=3*L[i]+1; else L[i+1]:=L[i]/2; fi; > od; gap> L; [ 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4 ] gap> SearchCycle( L ); [ 1, 4, 2 ] gap> n := 1;; L := [n];; gap> for i in [1..100] do n:=(n^2+1) mod 1093; Add(L,n); od; gap> L; [ 1, 2, 5, 26, 677, 363, 610, 481, 739, 715, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754, 157, 604, 848, 1004 ] gap> C := SearchCycle( L ); [ 157, 604, 848, 1004, 271, 211, 802, 521, 378, 795, 272, 754 ] gap> P := Positions( L, 157 ); [ 14, 26, 38, 50, 62, 74, 86, 98 ] gap> Length( C ); DifferencesList( P ); 12 [ 12, 12, 12, 12, 12, 12, 12 ] # doc/lists.xml:174-194 gap> J := [ [1,2,3], [3,4], [3,4], [1,2,4] ];; gap> DistinctRepresentatives( J ); [ 1, 3, 4, 2 ] gap> K := [ [3,4], [1,2], [2,3], [2,3,4] ];; gap> CommonRepresentatives( J, K ); [ [ 3, 3, 3, 1 ], [ 1, 3, 4, 2 ] ] gap> d16 := DihedralGroup( IsPermGroup, 16 ); Group([ (1,2,3,4,5,6,7,8), (2,8)(3,7)(4,6) ]) gap> SetName( d16, "d16" ); gap> c4 := Subgroup( d16, [ d16.1^2 ] ); Group([ (1,3,5,7)(2,4,6,8) ]) gap> SetName( c4, "c4" ); gap> RightCosets( d16, c4 ); [ RightCoset(c4,()), RightCoset(c4,(2,8)(3,7)(4,6)), RightCoset(c4,(1,8,7,6,5, 4,3,2)), RightCoset(c4,(1,8)(2,7)(3,6)(4,5)) ] gap> trans := CommonTransversal( d16, c4 ); [ (), (2,8)(3,7)(4,6), (1,2,3,4,5,6,7,8), (1,2)(3,8)(4,7)(5,6) ] gap> IsCommonTransversal( d16, c4, trans ); true # doc/lists.xml:216-223 gap> gens := GeneratorsOfGroup( DihedralGroup(12) ); [ f1, f2, f3 ] gap> String( gens ); "[ f1, f2, f3 ]" gap> BlankFreeString( gens ); "[f1,f2,f3]" # gap> STOP_TEST("utils03.tst", 1); utils-0.94/tst/utils04.tst0000644000000000000000000000527315174515600012421 0ustar00# utils, chapter 4 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils04.tst"); # doc/number.xml:38-50 gap> AllSmoothIntegers( 3, 1000 ); [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96, 108, 128, 144, 162, 192, 216, 243, 256, 288, 324, 384, 432, 486, 512, 576, 648, 729, 768, 864, 972 ] gap> AllSmoothIntegers( [5,11,17], 1000 ); [ 1, 5, 11, 17, 25, 55, 85, 121, 125, 187, 275, 289, 425, 605, 625, 935 ] gap> Length( last ); 16 gap> List( [3..20], n -> Length( AllSmoothIntegers( [5,11,17], 10^n ) ) ); [ 16, 29, 50, 78, 114, 155, 212, 282, 359, 452, 565, 691, 831, 992, 1173, 1374, 1595, 1843 ] # doc/number.xml:65-75 gap> AllProducts([1..4],3); [ 1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16, 2, 4, 6, 8, 4, 8, 12, 16, 6, 12, 18, 24, 8, 16, 24, 32, 3, 6, 9, 12, 6, 12, 18, 24, 9, 18, 27, 36, 12, 24, 36, 48, 4, 8, 12, 16, 8, 16, 24, 32, 12, 24, 36, 48, 16, 32, 48, 64 ] gap> Set(last); [ 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 64 ] gap> AllProducts( [(1,2,3),(2,3,4)], 2 ); [ (2,4,3), (1,2)(3,4), (1,3)(2,4), (1,3,2) ] # doc/number.xml:90-100 gap> RestrictedPartitions( 20, [4..10] ); [ [ 4, 4, 4, 4, 4 ], [ 5, 5, 5, 5 ], [ 6, 5, 5, 4 ], [ 6, 6, 4, 4 ], [ 7, 5, 4, 4 ], [ 7, 7, 6 ], [ 8, 4, 4, 4 ], [ 8, 6, 6 ], [ 8, 7, 5 ], [ 8, 8, 4 ], [ 9, 6, 5 ], [ 9, 7, 4 ], [ 10, 5, 5 ], [ 10, 6, 4 ], [ 10, 10 ] ] gap> RestrictedPartitionsWithoutRepetitions( 20, [4..10] ); [ [ 10, 6, 4 ], [ 9, 7, 4 ], [ 9, 6, 5 ], [ 8, 7, 5 ] ] gap> RestrictedPartitionsWithoutRepetitions( 10^2, List([1..10], n->n^2 ) ); [ [ 100 ], [ 64, 36 ], [ 49, 25, 16, 9, 1 ] ] # doc/number.xml:117-124 gap> n := 2^251; 3618502788666131106986593281521497120414687020801267626233049500247285301248 gap> NextProbablyPrimeInt( n ); 3618502788666131106986593281521497120414687020801267626233049500247285301313 gap> NextPrimeInt( n ); # same result, just faster 3618502788666131106986593281521497120414687020801267626233049500247285301313 # doc/number.xml:142-155 gap> iter := PrimeNumbersIterator();; gap> for i in [1..100] do p := NextIterator(iter); od; gap> p; 541 gap> sum := 0;; gap> ## "prime number race" 1 vs. 3 mod 4 gap> for p in PrimeNumbersIterator() do > if p <> 2 then sum := sum + E(4)^(p-1); fi; > if sum > 0 then break; fi; > od; gap> p; 26861 # gap> STOP_TEST("utils04.tst", 1); utils-0.94/tst/utils05.tst0000644000000000000000000001656715174515600012432 0ustar00# utils, chapter 5 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils05.tst"); # doc/groups.xml:28-35 gap> Comm( [ (1,2), (2,3) ] ); (1,2,3) gap> Comm( [(1,2),(2,3),(3,4),(4,5),(5,6)] ); (1,5,6) gap> Comm(Comm(Comm(Comm((1,2),(2,3)),(3,4)),(4,5)),(5,6)); ## the same (1,5,6) # doc/groups.xml:47-54 gap> D12 := DihedralGroup( 12 ); gap> SetName( D12, "D12" ); gap> a := D12.1;; b := D12.2;; gap> IsCommuting( a, b ); false # doc/groups.xml:67-76 gap> ListOfPowers( 2, 20 ); [ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 ] gap> ListOfPowers( (1,2,3)(4,5), 12 ); [ (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), (), (1,2,3)(4,5), (1,3,2), (4,5), (1,2,3), (1,3,2)(4,5), () ] gap> ListOfPowers( D12.2, 6 ); [ f2, f3, f2*f3, f3^2, f2*f3^2, of ... ] # doc/groups.xml:89-94 gap> GeneratorsAndInverses( D12 ); [ f1, f2, f3, f1, f2*f3^2, f3^2 ] gap> GeneratorsAndInverses( SymmetricGroup(5) ); [ (1,2,3,4,5), (1,2), (1,5,4,3,2), (1,2) ] # doc/groups.xml:114-136 gap> upp:= UpperFittingSeries( D12 );; gap> List( upp, StructureDescription ); [ "1", "C6", "D12" ] gap> low:= LowerFittingSeries( D12 );; gap> List( low, StructureDescription ); [ "D12", "C3", "1" ] gap> FittingLength( D12 ); 2 gap> S4 := SymmetricGroup( 4 );; gap> UpperFittingSeries( S4 ); [ Group(()), Group([ (1,2)(3,4), (1,4)(2,3) ]), Group([ (2,4,3), (1,2)(3,4) ]), Group([ (3,4), (2,4,3), (1,2)(3,4) ]) ] gap> List( last, StructureDescription ); [ "1", "C2 x C2", "A4", "S4" ] gap> LowerFittingSeries( S4 ); [ Sym( [ 1 .. 4 ] ), Alt( [ 1 .. 4 ] ), Group([ (1,4)(2,3), (1,2)(3,4) ]), Group(()) ] gap> List( last, StructureDescription ); [ "S4", "A4", "C2 x C2", "1" ] gap> FittingLength( S4); 3 # doc/groups.xml:171-192 gap> a4 := Group( (1,2,3), (2,3,4) );; SetName( a4, "a4" ); gap> k4 := Group( (1,2)(3,4), (1,3)(2,4) );; SetName( k4, "k4" ); gap> rc := RightCosets( a4, k4 ); [ RightCoset(k4,()), RightCoset(k4,(2,3,4)), RightCoset(k4,(2,4,3)) ] gap> lc := LeftCosets( a4, k4 ); [ LeftCoset((),k4), LeftCoset((2,4,3),k4), LeftCoset((2,3,4),k4) ] gap> AsSet( lc[2] ); [ (2,4,3), (1,2,3), (1,3,4), (1,4,2) ] gap> LeftCoset( (1,4,2), k4 ) = lc[2]; true gap> Representative( lc[2] ); (2,4,3) gap> ActingDomain( lc[2] ); k4 gap> (1,4,3) in lc[3]; true gap> (1,2,3)*lc[2] = lc[3]; true gap> lc[2]^(1,3,2) = lc[3]; true # doc/groups.xml:203-208 gap> Inverse( rc[3] ) = lc[3]; true gap> Inverse( lc[2] ) = rc[2]; true # doc/groups.xml:229-248 gap> G := Group( (1,2,3), (3,4,5), (5,6,7), (7,8,9) );; gap> phi := EpimorphismByGenerators( FreeGroup("a","b","c","d"), G ); [ a, b, c, d ] -> [ (1,2,3), (3,4,5), (5,6,7), (7,8,9) ] gap> PreImagesRepresentativeNC( phi, (1,2,3,4,5,6,7,8,9) ); d*c*b*a gap> a := G.1;; b := G.2;; c := G.3;; d := G.4;; gap> d*c*b*a; (1,2,3,4,5,6,7,8,9) gap> ## note that it is easy to produce nonsense: gap> epi := EpimorphismByGenerators( Group((1,2,3)), Group((8,9)) ); Warning: calling GroupHomomorphismByImagesNC without checks [ (1,2,3) ] -> [ (8,9) ] gap> IsGroupHomomorphism( epi ); true gap> Image( epi, (1,2,3) ); () gap> Image( epi, (1,3,2) ); (8,9) # doc/groups.xml:282-307 gap> s4 := Group( (1,2),(2,3),(3,4) );; gap> s3 := Group( (5,6),(6,7) );; gap> c3 := Subgroup( s3, [ (5,6,7) ] );; gap> f := GroupHomomorphismByImages( s4, s3, > [(1,2),(2,3),(3,4)], [(5,6),(6,7),(5,6)] );; gap> i := GroupHomomorphismByImages( c3, s3, [(5,6,7)], [(5,6,7)] );; gap> Pfi := Pullback( f, i ); Group([ (2,3,4)(5,7,6), (1,2)(3,4) ]) gap> StructureDescription( Pfi ); "A4" gap> info := PullbackInfo( Pfi ); rec( directProduct := Group([ (1,2), (2,3), (3,4), (5,6,7) ]), projections := [ [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (2,3,4), (1,2)(3,4) ], [ (2,3,4)(5,7,6), (1,2)(3,4) ] -> [ (5,7,6), () ] ] ) gap> g := (1,2,3)(5,6,7);; gap> ImageElm( info!.projections[1], g ); (1,2,3) gap> ImageElm( info!.projections[2], g ); (5,6,7) gap> dp := info!.directProduct;; gap> a := ImageElm( Embedding( dp, 1 ), (1,4,3) );; gap> b := ImageElm( Embedding( dp, 2 ), (5,7,6) );; gap> a*b in Pfi; true # doc/groups.xml:351-373 gap> g1 := DihedralGroup( 8 ); gap> c1 := Centre( g1 ); Group([ f3 ]) gap> cp1 := CentralProduct( g1, g1, c1, IdentityMapping( c1 ) ); Group([ f1, f2, f5, f3, f4, f5 ]) gap> IdGroup( cp1 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) ); true gap> g2 := QuaternionGroup( 8 ); gap> c2 := Centre( g2 ); Group([ y2 ]) gap> cp2 := CentralProduct( g2, g2, c2, IdentityMapping( c2 ) ); Group([ f1, f2, f5, f3, f4, f5 ]) gap> IdGroup( cp2 ) = IdGroup( ExtraspecialGroup( 2^5, "+" ) ); true gap> info2 := CentralProductInfo( cp2 ); rec( phi := IdentityMapping( Group([ y2 ]) ), projection := [ f1, f2, f3, f4, f5, f6 ] -> [ f1, f2, f5, f3, f4, f5 ] ) gap> Source( Embedding( Source( info2.projection ), 1 ) ) = g2; true # doc/groups.xml:406-427 gap> gens := [ (1,2,3,4), (1,2)(3,4) ];; gap> d8 := Group( gens );; gap> SetName( d8, "d8" ); gap> c2 := Subgroup( d8, [ (2,4) ] );; gap> SortedList( IdempotentEndomorphismsWithImage( gens, c2 ) ); [ [ (), (2,4) ], [ (2,4), () ] ] gap> data:= IdempotentEndomorphismsData( d8 );; gap> data.images[1]; [ [ (), () ] ] gap> List( data.images, Length ); [ 1, 2, 2, 2, 2, 1 ] gap> all:= IdempotentEndomorphisms( d8 );; gap> Length( all ); 10 gap> all[1]; [ (1,2,3,4), (1,2)(3,4) ] -> [ (), () ] gap> Size( Image( all[1] ) ); 1 gap> Last( all ) = IdentityMapping( d8 ); true # doc/groups.xml:435-439 gap> q8 := QuaternionGroup( 8 );; gap> IdempotentEndomorphisms( q8 ); [ [ x, y ] -> [ of ..., of ... ], [ x, y ] -> [ x, y ] ] # doc/groups.xml:449-464 gap> c4 := Group( (1,2,3,4) );; gap> c2 := Group( (5,6) );; gap> f1 := GroupHomomorphismByImages( c4, c2, [(1,2,3,4)], [(5,6)] );; gap> c3 := Group( (1,2,3) );; gap> c6 := Group( (1,2,3,4,5,6) );; gap> f2 := GroupHomomorphismByImages( c3, c6, [(1,2,3)], [(1,3,5)(2,4,6)] );; gap> c4c3 := DirectProduct( c4, c3 ); Group([ (1,2,3,4), (5,6,7) ]) gap> c2c6 := DirectProduct( c2, c6 ); Group([ (1,2), (3,4,5,6,7,8) ]) gap> f := DirectProductOfFunctions( c4c3, c2c6, f1, f2 ); [ (1,2,3,4), (5,6,7) ] -> [ (1,2), (3,5,7)(4,6,8) ] gap> ImageElm( f, (1,4,3,2)(5,7,6) ); (1,2)(3,7,5)(4,8,6) # doc/groups.xml:476-493 gap> c9 := Group( (1,2,3,4,5,6,7,8,9) );; gap> ac9 := AutomorphismGroup( c9 );; gap> q8 := QuaternionGroup( IsPermGroup, 8 );; gap> aq8 := AutomorphismGroup( q8 );; gap> A := DirectProductOfAutomorphismGroups( ac9, aq8 ); gap> genA := GeneratorsOfGroup( A );; gap> G := Source( genA[1] ); Group([ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13) (14,15,16,17) ]) gap> a := genA[1]*genA[5]; [ (1,2,3,4,5,6,7,8,9), (10,14,12,16)(11,17,13,15), (10,11,12,13)(14,15,16,17) ] -> [ (1,3,5,7,9,2,4,6,8), (10,16,12,14)(11,15,13,17), (10,11,12,13)(14,15,16,17) ] gap> ImageElm( a, (1,9,8,7,6,5,4,3,2)(10,14,12,16)(11,17,13,15) ); (1,8,6,4,2,9,7,5,3)(10,16,12,14)(11,15,13,17) # gap> STOP_TEST("utils05.tst", 1); utils-0.94/tst/utils06.tst0000644000000000000000000000447015174515600012421 0ustar00# utils, chapter 6 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils06.tst"); # doc/matrix.xml:41-86 gap> M6 := [ [1,2,0,0,0,0], [3,4,0,0,0,0], [5,6,0,0,0,0], > [0,0,9,0,0,0], [0,0,0,1,2,3], [0,0,0,4,5,6] ];; gap> Display( M6 ); [ [ 1, 2, 0, 0, 0, 0 ], [ 3, 4, 0, 0, 0, 0 ], [ 5, 6, 0, 0, 0, 0 ], [ 0, 0, 9, 0, 0, 0 ], [ 0, 0, 0, 1, 2, 3 ], [ 0, 0, 0, 4, 5, 6 ] ] gap> L6 := DirectSumDecompositionMatrices( M6 ); [ [ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ], [ [ 9 ] ], [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] ] ] gap> M4 := [ [0,3,0,0], [0,0,0,0], [0,0,0,0], [0,0,4,0] ];; gap> Display( M4 ); [ [ 0, 3, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 4, 0 ] ] gap> L4 := DirectSumDecompositionMatrices( M4 ); [ [ [ [ 0, 3 ] ], [ [ 0, 0 ], [ 0, 0 ], [ 4, 0 ] ] ], [ [ [ 0, 3 ], [ 0, 0 ] ], [ [ 0, 0 ], [ 4, 0 ] ] ], [ [ [ 0, 3 ], [ 0, 0 ], [ 0, 0 ] ], [ [ 4, 0 ] ] ] ] gap> for L in L4 do > A := DirectSumMat( L );; > if ( A = M4 ) then Print( "yes, A = M4\n" ); fi; > od; yes, A = M4 yes, A = M4 yes, A = M4 gap> M8 := DirectSumMat( M4, M4 );; gap> Display( M8 ); [ [ 0, 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, 4, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 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, 4, 0 ] ] gap> L8 := DirectSumDecompositionMatrices( M8 );; gap> Length( L8 ); 16 # doc/matrix.xml:97-108 gap> M5 := [ [1,2,0,0,0], [3,4,0,0,0], [0,0,0,0,0], > [0,0,0,6,7], [0,0,0,8,9] ];; gap> Display(M5); [ [ 1, 2, 0, 0, 0 ], [ 3, 4, 0, 0, 0 ], [ 0, 0, 0, 0, 0 ], [ 0, 0, 0, 6, 7 ], [ 0, 0, 0, 8, 9 ] ] gap> L5 := DirectSumDecompositionMatrices( M5 ); [ [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 0 ] ], [ [ 6, 7 ], [ 8, 9 ] ] ] ] # gap> STOP_TEST("utils06.tst", 1); utils-0.94/tst/utils07.tst0000644000000000000000000000431715174515600012422 0ustar00# utils, chapter 7 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils07.tst"); # doc/iterator.xml:43-57 gap> G := SmallGroup( 6,1);; gap> iter := AllIsomorphismsIterator( G, s3 );; gap> NextIterator( iter ); [ f1, f2 ] -> [ (6,7), (5,6,7) ] gap> n := AllIsomorphismsNumber( G, s3 ); 6 gap> AllIsomorphisms( G, s3 ); [ [ f1, f2 ] -> [ (6,7), (5,6,7) ], [ f1, f2 ] -> [ (5,7), (5,6,7) ], [ f1, f2 ] -> [ (5,6), (5,7,6) ], [ f1, f2 ] -> [ (6,7), (5,7,6) ], [ f1, f2 ] -> [ (5,7), (5,7,6) ], [ f1, f2 ] -> [ (5,6), (5,6,7) ] ] gap> iter := AllIsomorphismsIterator( G, s3 );; gap> for h in iter do Print( ImageElm( h, G.1 ) = (6,7), ", " ); od; true, false, false, true, false, false, # doc/iterator.xml:73-84 gap> c3c3 := Group( (1,2,3), (4,5,6) );; gap> iter := AllSubgroupsIterator( c3c3 ); gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od; Group( () ) Group( [ (4,5,6) ] ) Group( [ (1,2,3) ] ) Group( [ (1,2,3)(4,5,6) ] ) Group( [ (1,3,2)(4,5,6) ] ) Group( [ (4,5,6), (1,2,3) ] ) # doc/iterator.xml:106-120 gap> it1 := Iterator( [ 1, 2, 3 ] );; gap> it2 := Iterator( [ 4, 5, 6 ] );; gap> iter := CartesianIterator( it1, it2 );; gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od; [ 1, 4 ] [ 1, 5 ] [ 1, 6 ] [ 2, 4 ] [ 2, 5 ] [ 2, 6 ] [ 3, 4 ] [ 3, 5 ] [ 3, 6 ] # doc/iterator.xml:135-158 gap> L := [6,7,8,9];; gap> iterL := IteratorList( L );; gap> pairsL := UnorderedPairsIterator( iterL );; gap> while not IsDoneIterator(pairsL) do Print(NextIterator(pairsL),"\n"); od; [ 6, 6 ] [ 6, 7 ] [ 7, 7 ] [ 6, 8 ] [ 7, 8 ] [ 8, 8 ] [ 6, 9 ] [ 7, 9 ] [ 8, 9 ] [ 9, 9 ] gap> iter4 := IteratorList( [ 4 ] ); gap> pairs4 := UnorderedPairsIterator(iter4); gap> NextIterator( pairs4 ); [ 4, 4 ] gap> IsDoneIterator( pairs4 ); true # gap> STOP_TEST("utils07.tst", 1); utils-0.94/tst/utils08.tst0000644000000000000000000000463015174515600012421 0ustar00# utils, chapter 8 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils08.tst"); # doc/record.xml:26-33 gap> r := rec( a := 1, b := 2, c := 3 );; gap> AssignGlobals( r ); The following global variables have been assigned: [ "a", "b", "c" ] gap> [a,b,c]; [ 1, 2, 3 ] # doc/record.xml:65-81 gap> defaults := rec( a := 1, b := 2, c := 3 );; gap> OptionRecordWithDefaults( defaults, rec( a := 6) ); rec( a := 6, b := 2, c := 3 ) gap> OptionRecordWithDefaults( defaults, rec( b := 7, c := 8 ) ); rec( a := 1, b := 7, c := 8 ) gap> OptionRecordWithDefaults( defaults, [ ] ); rec( a := 1, b := 2, c := 3 ) gap> OptionRecordWithDefaults( defaults, [ rec( c := 8 ) ] ); rec( a := 1, b := 2, c := 8 ) gap> OptionRecordWithDefaults( defaults, rec( d := 9 ) ); Error, Unknown option: d gap> OptionRecordWithDefaults( defaults, [ rec( b := 7 ), rec( c := 8 ) ] ); Error, Too many arguments for function gap> OptionRecordWithDefaults( defaults, [6,7,8] ); Error, Too many arguments for function # doc/record.xml:94-113 gap> PrintDimensions := function( arg ) > local nargs, dim, order, V, L, len, K, i; > nargs := Length( arg ); > dim := [ arg[1]!.height, arg[1]!.width, arg[1]!.depth ]; > order := rec( h := 1, w := 2, d := 3 ); > V := [ "height", "width", "depth" ]; > if ( nargs > 1 ) and IsRecord( arg[2] ) then > order := OptionRecordWithDefaults( order, arg[2] ); > fi; > L := [ order!.h, order!.w, order!.d ]; > len := Length( L ); > K := [ 1..len ]; > SortParallel( L, K ); > Print( "dimensions: " ); > Print( V[K[1]], " = ", dim[K[1]], ", " ); > Print( V[K[2]], " = ", dim[K[2]], ", " ); > Print( V[K[3]], " = ", dim[K[3]], "\n" ); > end;; # doc/record.xml:121-128 gap> mydim := rec( height := 45, width := 31, depth := 17 ); rec( depth := 17, height := 45, width := 31 ) gap> PrintDimensions( mydim ); dimensions: height = 45, width = 31, depth = 17 gap> PrintDimensions( mydim, rec( h:=3, w:=1, d:=2 ) ); dimensions: width = 31, depth = 17, height = 45 # gap> STOP_TEST("utils08.tst", 1); utils-0.94/tst/utils09.tst0000644000000000000000000000147215174515600012423 0ustar00# utils, chapter 9 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils09.tst"); # doc/download.xml:85-97 gap> url:= "https://www.gap-system.org/index.html";; gap> res1:= Download( url );; gap> res1.success; true gap> IsBound( res1.result ) and IsString( res1.result ); true gap> res2:= Download( Concatenation( url, "xxx" ) );; gap> res2.success; false gap> IsBound( res2.error ) and IsString( res2.error ); true # gap> STOP_TEST("utils09.tst", 1); utils-0.94/tst/utils10.tst0000644000000000000000000000704415174515600012414 0ustar00# utils, chapter 10 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils10.tst"); # doc/../lib/gslp.gd:34-46 gap> gslp:= GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); gap> IsGeneralizedStraightLineProgram( gslp ); true gap> slp:= StraightLineProgram( [[[1,2]]], 1 ); gap> IsGeneralizedStraightLineProgram( slp ); true gap> IsGeneralizedStraightLineProgram( [ slp, slp ] ); false # doc/../lib/gslp.gd:194-203 gap> GeneralizedStraightLineProgram( [[[1,2]]], 1 ); gap> GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); gap> GeneralizedStraightLineProgram( "compose", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); # doc/../lib/gslp.gd:77-83 gap> gslp:= GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); gap> DataOfGeneralizedStraightLineProgram( gslp ); [ "union", [ , ] ] # doc/../lib/gslp.gd:111-116 gap> NrInputsOfGeneralizedStraightLineProgram( > GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); 1 # doc/../lib/gslp.gd:146-155 gap> NrOutputsOfGeneralizedStraightLineProgram( > GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); 2 gap> NrOutputsOfGeneralizedStraightLineProgram( > GeneralizedStraightLineProgram( "compose", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); 1 # doc/../lib/gslp.gd:248-260 gap> gens:= [ (1,2,3,4,5,6) ];; gap> gslp:= GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); gap> ResultOfGeneralizedStraightLineProgram( gslp, gens ); [ (1,3,5)(2,4,6), (1,4)(2,5)(3,6) ] gap> gslp:= GeneralizedStraightLineProgram( "compose", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); gap> ResultOfGeneralizedStraightLineProgram( gslp, gens ); [ () ] # doc/../lib/gslp.gd:292-317 gap> gslp:= GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); gap> slp:= EquivalentStraightLineProgram( gslp ); gap> Display( slp ); # input: r:= [ g1 ]; # program: # return values: [ r[1]^2, r[1]^3 ] gap> gslp:= GeneralizedStraightLineProgram( "compose", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); gap> slp:= EquivalentStraightLineProgram( gslp ); gap> Display( slp ); # input: r:= [ g1 ]; # program: r[2]:= r[1]^2; r[1]:= r[2]; # return values: [ r[1]^3 ] # doc/../lib/gslp.gi:220-229 gap> gslp:= GeneralizedStraightLineProgram( "union", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; gap> IsInternallyConsistent( gslp ); true gap> gslp:= GeneralizedStraightLineProgram( "compose", > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; gap> IsInternallyConsistent( gslp ); true # gap> STOP_TEST("utils10.tst", 1); utils-0.94/tst/utils11.tst0000644000000000000000000000375415174515600012421 0ustar00# utils, chapter 11 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils11.tst"); # doc/others.xml:57-62 gap> IntOrInfinityToLaTeX( 10^3 ); "1000" gap> IntOrInfinityToLaTeX( infinity ); "\\infty" # doc/others.xml:75-78 gap> LaTeXStringFactorsInt( Factorial(12) ); "2^{10} \\cdot 3^5 \\cdot 5^2 \\cdot 7 \\cdot 11" # doc/others.xml:120-165 gap> ## permutation groups gap> ConvertToMagmaInputString( Group( (1,2,3,4,5), (3,4,5) ) ); "PermutationGroup<5|(1,2,3,4,5),\n(3,4,5)>;\n" gap> ConvertToMagmaInputString( Group( (1,2,3,4,5) ), "c5" ); "c5 := PermutationGroup<5|(1,2,3,4,5)>;\n" gap> ## pc-group gap> ConvertToMagmaInputString( DihedralGroup( IsPcGroup, 10 ) ); "PolycyclicGroup< f1,f2 |\nf1^2,\nf2^5,\nf2^f1 = f2^4\n>;\n" gap> ## fp-group gap> F2 := FreeGroup( 2 );; gap> f := F2.1;; g := F2.2;; gap> relq8 := [ f^4, g^4, f*g*f*g^-1, f^2*g^2 ];; gap> q8 := F2/relq8;; gap> ConvertToMagmaInputString( q8 ); no conversion function yet available for fp-groups fail gap> ## matrix group gap> M := GL(2,5);; Size(M); 480 gap> s1 := ConvertToMagmaInputString( M ); "F := GF(5);\nP := GL(2,F);\ngens := [\nP![2,0,0,1],\nP![4,1,4,0]\n];\nsub

;\n" gap> Print( s1 ); F := GF(5); P := GL(2,F); gens := [ P![2,0,0,1], P![4,1,4,0] ]; sub

; gap> n1 := [ [ Z(9)^0, Z(9)^0 ], [ Z(9)^0, Z(9) ] ];; gap> n2 := [ [ Z(9)^0, Z(9)^3 ], [ Z(9)^4, Z(9)^2 ] ];; gap> N := Group( n1, n2 );; Size( N ); 5760 gap> s2 := ConvertToMagmaInputString( N, "gpN" );; gap> Print( s2 ); F := GF(3^2); P := GL(2,F); w := PrimitiveElement(F); gens := [ P![ 1, 1, 1,w^1], P![ 1,w^3, 2,w^2] ]; gpN := sub

; # gap> STOP_TEST("utils11.tst", 1); utils-0.94/tst/utils12.tst0000644000000000000000000000147515174515600012420 0ustar00# utils, chapter 12 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("utils12.tst"); # doc/obsolete.xml:49-66 gap> s3 := SymmetricGroup( 3 );; gap> L := KnownPropertiesOfObject( GeneratorsOfGroup( s3 ) );; gap> Perform( L, Display ); IsFinite IsSmallList IsGeneratorsOfMagmaWithInverses IsAssociative IsGeneratorsOfSemigroup IsSubsetLocallyFiniteGroup gap> Perform( s3, Display ); () (2,3) (1,3) (1,3,2) (1,2,3) (1,2) # gap> STOP_TEST("utils12.tst", 1);

## gslp:= GeneralizedStraightLineProgram( "union", ## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); ## ## gap> IsGeneralizedStraightLineProgram( gslp ); ## true ## gap> slp:= StraightLineProgram( [[[1,2]]], 1 ); ## ## gap> IsGeneralizedStraightLineProgram( slp ); ## true ## gap> IsGeneralizedStraightLineProgram( [ slp, slp ] ); ## false ## ]]> ## ## ## <#/GAPDoc> ## DeclareCategory( "IsGeneralizedStraightLineProgram", IsObject ); InstallTrueMethod( IsGeneralizedStraightLineProgram, IsStraightLineProgram ); ############################################################################# ## #A DataOfGeneralizedStraightLineProgram( ) ## ## <#GAPDoc Label="DataOfGeneralizedStraightLineProgram"> ## ## ## ## ## For a generalized straight line program gslp that is not ## a straight line program, ## returns a list of ## length two, ## the first entry being either "union" or "compose" ## and the second being the list of defining generalized straight line ## programs. ##