diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ca0f05b997..e2586f8e27 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -47,7 +47,7 @@ jobs: test-suites: [ # base test: fast first test - "testinstall", + "testinstall-bare", "teststandard", @@ -141,7 +141,7 @@ jobs: TEST_SUITES: ${{ matrix.test-suites }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: "Set up Python" uses: actions/setup-python@v6 @@ -276,7 +276,7 @@ jobs: - name: "Gather coverage data" run: ${{ matrix.extra }} dev/ci-gather-coverage.sh - name: "Upload coverage data to Codecov" - uses: codecov/codecov-action@v6 + uses: codecov/codecov-action@v7 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -288,7 +288,7 @@ jobs: steps: - name: "Send Codecov notifications" - uses: codecov/codecov-action@v6 + uses: codecov/codecov-action@v7 with: token: ${{ secrets.CODECOV_TOKEN }} run_command: send-notifications @@ -341,7 +341,7 @@ jobs: - name: Install cross compile dependencies run: sudo apt-get install -q -y libgmp-dev:s390x libreadline-dev:s390x zlib1g-dev:s390x - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - run: ./autogen.sh @@ -407,7 +407,7 @@ jobs: env: AUTOCONF_VERSION: 2.71 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Download required GAP packages run: | diff --git a/.github/workflows/gapjl.yml b/.github/workflows/gapjl.yml index 626f1a52a1..f23b79ddab 100644 --- a/.github/workflows/gapjl.yml +++ b/.github/workflows/gapjl.yml @@ -44,7 +44,7 @@ jobs: steps: - name: Checkout GAP - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: path: 'GAPROOT' - name: "Set up Julia" @@ -67,11 +67,31 @@ jobs: - name: "Install dependencies (for macOS)" if: runner.os == 'macOS' run: | - brew install autoconf zlib # gmp pkg-config + # - autoconf, gmp, zlib are needed by GAP's build system + # - coreutils provides nproc + # - force use of Homebrew gcc to build GAP for proper stacktrace support + # Homebrew installs versioned binaries such as gcc-14 and g++-14, + # while later scripts expect unversioned gcc and g++ in PATH. + brew install autoconf gmp zlib gcc@14 coreutils + + # ensure gcc and g++ are available under those names (on macOS, + # these names are aliases for clang / clang++ out of the box) + shimdir="${HOME}/bin" + mkdir -p "${shimdir}" + ln -sf "$(brew --prefix)/bin/gcc-14" "${shimdir}/gcc" + ln -sf "$(brew --prefix)/bin/g++-14" "${shimdir}/g++" + echo "${shimdir}" >> "${GITHUB_PATH}" - name: "Build GAP" run: | mv GAPROOT /tmp/GAPROOT cd /tmp/GAPROOT + patchdir=$GAPJLPATH/.github/workflows/GAP_patches/master + if [ -d $patchdir ]; then + for f in $patchdir/*.patch; do + echo "Applying patch ${f}" + patch -p1 -d . < ${f} + done + fi ./autogen.sh ./configure --enable-Werror make -j`nproc` diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index bbf8e68ac8..63eca8aeb6 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-slim steps: - name: "Check out the repository" - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: "Set up Python" uses: actions/setup-python@v6 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 36867a212c..8c2b84a1ba 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: name: "Validate release scripts" runs-on: ubuntu-slim steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: "Set up Python" uses: actions/setup-python@v6 @@ -57,7 +57,7 @@ jobs: # run: python -m mypy --disallow-untyped-calls --disallow-untyped-defs dev/releases/*.py - name: "Run tests" - run: cd dev/releases && python -m pytest test_release_notes.py + run: cd dev/releases && python -m pytest unix: name: "Create Unix archives and data" @@ -72,7 +72,7 @@ jobs: # requires fetching the entire history. Therefore, we might as well do # that here when checking out the repo, which is what setting fetch-depth # to 0 accomplishes here. - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 @@ -207,7 +207,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: "Clone the Windows installer maker scripts" - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: gap-system/gap-windows ref: main diff --git a/.github/workflows/update-gh-pages.yml b/.github/workflows/update-gh-pages.yml index e1ebb2c57b..cbafbb0093 100644 --- a/.github/workflows/update-gh-pages.yml +++ b/.github/workflows/update-gh-pages.yml @@ -41,7 +41,7 @@ jobs: sudo apt-get update sudo apt-get install --no-install-recommends "${packages[@]}" - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Configure GAP run: | ./autogen.sh && ./configure diff --git a/.gitignore b/.gitignore index 5d67442b54..ca50cf4952 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,17 @@ /libgap*.dll* /libgap*.so* +# emscripten / wasm build outputs (etc/emscripten/build.sh and friends) +/native-build/ +/extern/emscripten/ +/web-example/ +/packages.tar.gz +/gap.html +/gap.js +/gap.wasm +/gap.worker.js +/gap-fs.json + /bin/gap*.sh /bin/*-*/ # Compiling the `xgap` package creates the file `xgap.sh` diff --git a/CHANGES.md b/CHANGES.md index 6f4c6c84a9..a2e9050afa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,196 @@ # GAP - history of changes +## GAP 4.16.0 (June 2026) + +The following gives an overview of the changes compared to the previous +release. This list is not complete, many more internal or minor changes +were made, but we tried to only list those changes which we think might +affect some users directly. + +### New features + +- [#6384](https://github.com/gap-system/gap/pull/6384) Add `EnumeratorOfPartitionsSet` enumerator +- [#6322](https://github.com/gap-system/gap/pull/6322) Add `IsGenericMatrixRep` matrix object type +- [#6311](https://github.com/gap-system/gap/pull/6311) Add `PositionNonZeroInRow` for matrices and matrix objects +- [#6277](https://github.com/gap-system/gap/pull/6277) Add `DirectSumGModule` +- [#6268](https://github.com/gap-system/gap/pull/6268) Add `IsSquareMat` and `IsAntisymmetricMat` +- [#6262](https://github.com/gap-system/gap/pull/6262) Add `UserHomeShorten` as counterpart of `UserHomeExpand` +- [#6261](https://github.com/gap-system/gap/pull/6261) Add `WhereDepth` user preference to control depth of initial stack trace in break loops +- [#6259](https://github.com/gap-system/gap/pull/6259) Add `IsSymmetricMatrix` (and `IsSymmetricMat` as a synonym) +- [#6232](https://github.com/gap-system/gap/pull/6232) Add `RandomMatrix`, `RandomInvertibleMatrix`; and fix a problem with a new feature for matrix groups +- [#6213](https://github.com/gap-system/gap/pull/6213) Add `ConformalSymplecticGroup` +- [#5980](https://github.com/gap-system/gap/pull/5980) Add `AddMatrix`, `MultMatrix` (plus explicit left/right side variants) for in-place modification of matrices +- [#3357](https://github.com/gap-system/gap/pull/3357) Add `FoldLeft`, `FoldLeftX`; and `ForAllX`, `ForAnyX`, `FilteredX`, `NumberX`, `PerformX` to complement `ListX`, `SetX`, `SumX`, `ProductX` + +### Performance improvements + +- [#6398](https://github.com/gap-system/gap/pull/6398) Speed up conversion from integers to finite field elements +- [#6329](https://github.com/gap-system/gap/pull/6329) Speed up `CopySubMatrix`, `CopySubVector`, `ExtractSubMatrix`, `ExtractSubVector` for plist matrices/vectors +- [#6289](https://github.com/gap-system/gap/pull/6289) Make the meataxe faster by using `AddMatrix`, `AddVector`, `MultMatrix`, `MultVector` +- [#6276](https://github.com/gap-system/gap/pull/6276) Faster high-level Meataxe functions for irreducible modules (e.g. `MTX.IsomorphismModules`, `MTX.Indecomposition`, `MTX.BasisModuleEndomorphisms`, `MTX.BasisModuleHomomorphisms`) +- [#6267](https://github.com/gap-system/gap/pull/6267) Improve conjugation test for subgroups with different orders +- [#6265](https://github.com/gap-system/gap/pull/6265) Speed up `IsSubset` for cyclotomic domains (such as `Integers`, `PositiveIntegers`, `GaussianRationals` etc.) +- [#6114](https://github.com/gap-system/gap/pull/6114) Enhance support for very long transversals in a permutation group by forcing down huge index steps through an intermediate subgroup + +### Improved and extended functionality + +- [#6357](https://github.com/gap-system/gap/pull/6357) Update the GAP banner to reflect the new GAP logo +- [#6338](https://github.com/gap-system/gap/pull/6338) Improve `CosetLeadersMatFFE` documentation +- [#6334](https://github.com/gap-system/gap/pull/6334) Translating a range by adding an integer now produces another range (instead of a plain list) when possible +- [#6320](https://github.com/gap-system/gap/pull/6320) Add a manual section on how to write code for matrix objects +- [#6309](https://github.com/gap-system/gap/pull/6309) Allow `CopySubVector` on plain row vectors, fix `CopySubMatrix` +- [#6292](https://github.com/gap-system/gap/pull/6292) Document new `PackageInfo.g` fields `Dependencies.TestPackages` and `Dependencies.NeededSystemPackages`, and teach `ValidatePackageInfo` about them +- [#6280](https://github.com/gap-system/gap/pull/6280) Implement `MultVectorRight` for lists +- [#6257](https://github.com/gap-system/gap/pull/6257) Improve break-loop stack traces to be more consistent, provide more information and to indicate the current environment selected via `DownEnv`/`UpEnv` +- [#6211](https://github.com/gap-system/gap/pull/6211) Improve documentation for nice monomorphisms +- [#6183](https://github.com/gap-system/gap/pull/6183) Transfer more properties (such as `IsNaturalSL`, `InvariantQuadraticForm` etc.) when conjugating matrix groups + +### Removed or obsolete functionality + +- [#6067](https://github.com/gap-system/gap/pull/6067) Deprecate `InstallValue` for anything but plain objects (i.e., plain GAP lists, records or strings) and warn if it is done anyway + +### Changes related to handling of packages + +- [#6191](https://github.com/gap-system/gap/pull/6191) Remove unused "PC STACK" variables for from the left collectors (this breaks compatibility with polycyclic version 2.16 and older; use 2.17 or newer instead) + +### Changes in the documentation + +- [#6410](https://github.com/gap-system/gap/pull/6410) Document `OrbitStabilizer` return value +- [#6408](https://github.com/gap-system/gap/pull/6408) Document `SemiSimpleType` field restriction +- [#6405](https://github.com/gap-system/gap/pull/6405) Clarify `IsomorphismPcGroup` docs +- [#6370](https://github.com/gap-system/gap/pull/6370) Improve documentation of `OnTuplesSets`, `OnSetsDisjointSets`, `OnSetsTuples` +- [#6361](https://github.com/gap-system/gap/pull/6361) Simplify the list of `Matrix` argument variants in the manual +- [#6348](https://github.com/gap-system/gap/pull/6348) Clarify `CompatiblePairs` documentation +- [#6337](https://github.com/gap-system/gap/pull/6337) Clarify `IrreducibleModules` description to say 'at most' dim +- [#6260](https://github.com/gap-system/gap/pull/6260) Document `DirectProductElement` +- [#6220](https://github.com/gap-system/gap/pull/6220) Correct the documentation of `NewFamily` +- [#6198](https://github.com/gap-system/gap/pull/6198) Document setter for mutable attributes +- [#6174](https://github.com/gap-system/gap/pull/6174) Document objects with memory +- [#6171](https://github.com/gap-system/gap/pull/6171) Improve documentation of `InverseGeneralMapping` +- [#6169](https://github.com/gap-system/gap/pull/6169) Fix the definition of `PClassPGroup` +- [#6162](https://github.com/gap-system/gap/pull/6162) Only show authors in `Cite`, not maintainers + +### Fixed bugs that could lead to incorrect results + +- [#6382](https://github.com/gap-system/gap/pull/6382) Fix `Irr` for natural symmetric groups when the conjugacy classes are ordered differently in the group and its character table +- [#6358](https://github.com/gap-system/gap/pull/6358) Fix `HexSHA256` to always return 64 hex digits and not drop leading zero digits +- [#6341](https://github.com/gap-system/gap/pull/6341) Fix return value of `PartitionsGreatestLE(0, m)` and improve its documentation +- [#6340](https://github.com/gap-system/gap/pull/6340) Fix `MinimalGeneratingSet` for pc groups which sometimes returned incorrect (non-minimal) results +- [#6325](https://github.com/gap-system/gap/pull/6325) Fix garbled result produced by `CosetLeadersMatFFE` +- [#6303](https://github.com/gap-system/gap/pull/6303) Fix `CopySubVector` for GF(2) vectors to not produce invalid results for certain inputs +- [#6253](https://github.com/gap-system/gap/pull/6253) Fix `ShortestVectors` with `"positive"` argument returning a potentially incomplete list +- [#6245](https://github.com/gap-system/gap/pull/6245) Fix `PreImagesRepresentative` for group homomorphisms with `OnLines` action +- [#6206](https://github.com/gap-system/gap/pull/6206) Fix two bugs in `IsomorphismPermGroupForMatrixGroup` +- [#6203](https://github.com/gap-system/gap/pull/6203) Fix `FieldOfMatrixGroup` for certain classical matrix groups in dimension up to 2, and fix related problems with their invariant forms +- [#6170](https://github.com/gap-system/gap/pull/6170) Fix `IsomorphismPermGroup` for trivial f. p. (sub)group +- [#6160](https://github.com/gap-system/gap/pull/6160) Fix a bug in `RepresentativesPerfectSubgroups` that could lead to the omission of subgroups + +### Fixed bugs that could lead to crashes + +- [#6326](https://github.com/gap-system/gap/pull/6326) Fix crash in `CosetLeadersMatFFE` + +### Fixed bugs that could lead to unexpected errors + +- [#6418](https://github.com/gap-system/gap/pull/6418) Fix `RingGeneralMappingByImages` for non-SCRing +- [#6196](https://github.com/gap-system/gap/pull/6196) Fix an inconsistency problem in `IsFinite` for matrix groups over cycl. fields. +- [#6159](https://github.com/gap-system/gap/pull/6159) Fix a potential error message about data types when computing extensions + +### Other fixed bugs + +- [#6355](https://github.com/gap-system/gap/pull/6355) Reset the options stack after an error also when the break loop is disabled (`-T` command line option) +- [#6218](https://github.com/gap-system/gap/pull/6218) Change `CoverageLineByLine` to produce output compatible with that produced by the `--coverage` command line option + +### Other changes + +- [#6230](https://github.com/gap-system/gap/pull/6230) Make `RestrictedMapping` of a group homomorphism use the same `Range` as the original morphism + +### Package distribution + +#### New packages redistributed with GAP + +- [**ClassicalMaximals**](https://gap-packages.github.io/ClassicalMaximals/) 1.1: Maximal subgroups of classical groups, by Maximilian Hauck, Max Horn, Tristan Pfersdorff, Christian Seeger, Sergio Siccha +- [**LocalNR**](https://gap-packages.github.io/LocalNR) 2.1.0: Package of local nearrings, by Iryna Raievska, Maryna Raievska, Yaroslav Sysak +- [**ModularGroup**](https://ag-weitze-schmithusen.github.io/ModularGroup) 2.0.2: Finite-index subgroups of (P)SL(2,Integers), by Sebastian Engelhardt, Luca Leon Junk, Hannah Wagmann, Gabriela Weitze-Schmithüsen +- [**nofoma**](https://gap-packages.github.io/nofoma) 1.0.1: Normal forms of matrices, by Meinolf Geck, Alia Bonnet +- [**Origami**](https://AG-Weitze-Schmithusen.github.io/Origami/) 2.0.3: Computing Veech groups of origamis, by Leo Emmerich, Sebastian Engelhardt, Simon Ertl, Luca Leon Junk, Pascal Kattler, Alexander Rogovskyy, Pascal Schumann, Andrea Thevis, Hannah Wagmann, Gabriela Weitze-Schmithüsen +- [**PackageMaker**](https://gap-packages.github.io/PackageMaker) 1.0.1: A GAP package for creating new GAP packages, by Max Horn + +#### Updated packages redistributed with GAP + +The GAP 4.16.0 distribution contains 172 packages, of which 69 have been +updated since GAP 4.15.1. The full list of updated packages is given below: + +- [**4ti2Interface**](https://homalg-project.github.io/pkg/4ti2Interface): 2024.11-01 -> 2026.05-01 +- [**Alnuth**](https://gap-packages.github.io/alnuth): 3.2.1 -> 4.0.0 +- [**ANUPQ**](https://gap-packages.github.io/anupq/): 3.3.2 -> 3.3.3 +- [**AtlasRep**](https://www.math.rwth-aachen.de/~Thomas.Breuer/atlasrep): 2.1.9 -> 2.1.11 +- [**AutoDoc**](https://gap-packages.github.io/AutoDoc): 2025.10.16 -> 2026.05.11 +- [**AutPGrp**](https://gap-packages.github.io/autpgrp/): 1.11.1 -> 1.12.0 +- [**Browse**](https://www.math.rwth-aachen.de/~Browse): 1.8.21 -> 1.8.22 +- [**CAP**](https://homalg-project.github.io/pkg/CAP): 2025.09-04 -> 2026.05-08 +- [**CaratInterface**](https://www.math.uni-bielefeld.de/~gaehler/gap/packages.php): 2.3.7 -> 2.3.9 +- [**CddInterface**](https://homalg-project.github.io/CddInterface): 2025.06.24 -> 2026.03.02 +- [**Cryst**](https://www.math.uni-bielefeld.de/~gaehler/gap/packages.php): 4.1.30 -> 4.1.31 +- [**CrystCat**](https://www.math.uni-bielefeld.de/~gaehler/gap/packages.php): 1.1.10 -> 1.1.11 +- [**curlInterface**](https://gap-packages.github.io/curlInterface/): 2.4.2 -> 2.4.3 +- [**cvec**](https://gap-packages.github.io/cvec): 2.8.4 -> 2.8.5 +- [**datastructures**](https://gap-packages.github.io/datastructures): 0.4.0 -> 0.4.1 +- [**Digraphs**](https://digraphs.github.io/Digraphs): 1.13.1 -> 1.14.0 +- [**ExamplesForHomalg**](https://homalg-project.github.io/pkg/ExamplesForHomalg): 2023.10-01 -> 2025.12-01 +- [**ferret**](https://gap-packages.github.io/ferret/): 1.0.15 -> 1.0.16 +- [**float**](https://gap-packages.github.io/float/): 1.0.9 -> 1.0.10 +- [**FORMAT**](https://gap-packages.github.io/format/): 1.4.4 -> 1.4.5 +- [**Forms**](https://gap-packages.github.io/forms): 1.2.13 -> 1.3.0 +- [**FPLSA**](https://gap-packages.github.io/FPLSA): 1.2.7 -> 1.2.8 +- [**GAPDoc**](https://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc): 1.6.7 -> 1.6.10 +- [**Gauss**](https://homalg-project.github.io/pkg/Gauss): 2024.11-01 -> 2025.12-01 +- [**GaussForHomalg**](https://homalg-project.github.io/pkg/GaussForHomalg): 2024.08-01 -> 2026.04-01 +- [**GeneralizedMorphismsForCAP**](https://homalg-project.github.io/pkg/GeneralizedMorphismsForCAP): 2025.08-01 -> 2025.12-01 +- [**GradedModules**](https://homalg-project.github.io/pkg/GradedModules): 2024.12-01 -> 2026.04-01 +- [**GradedRingForHomalg**](https://homalg-project.github.io/pkg/GradedRingForHomalg): 2024.07-01 -> 2026.04-01 +- [**groupoids**](https://gap-packages.github.io/groupoids/): 1.79 -> 1.81 +- [**GUAVA**](https://gap-packages.github.io/guava): 3.20 -> 3.21 +- [**HAP**](https://gap-packages.github.io/hap): 1.70 -> 1.75 +- [**HAPcryst**](https://gap-packages.github.io/hapcryst/): 0.1.15 -> 0.2.0 +- [**HeLP**](https://gap-packages.github.io/HeLP): 4.0 -> 4.1 +- [**homalg**](https://homalg-project.github.io/pkg/homalg): 2024.01-01 -> 2025.12-01 +- [**HomalgToCAS**](https://homalg-project.github.io/pkg/HomalgToCAS): 2025.08-01 -> 2026.04-01 +- [**IBNP**](https://gap-packages.github.io/ibnp/): 0.17 -> 0.18 +- [**IO_ForHomalg**](https://homalg-project.github.io/pkg/IO_ForHomalg): 2023.02-04 -> 2025.12-01 +- [**json**](https://gap-packages.github.io/json/): 2.2.3 -> 2.4.0 +- [**LinearAlgebraForCAP**](https://homalg-project.github.io/pkg/LinearAlgebraForCAP): 2025.09-01 -> 2026.05-04 +- [**LocalizeRingForHomalg**](https://homalg-project.github.io/pkg/LocalizeRingForHomalg): 2023.10-01 -> 2026.05-01 +- [**lpres**](https://gap-packages.github.io/lpres): 1.1.1 -> 1.1.2 +- [**matgrp**](https://www.math.colostate.edu/~hulpke/matgrp): 0.72 -> 0.73 +- [**MatricesForHomalg**](https://homalg-project.github.io/pkg/MatricesForHomalg): 2025.09-01 -> 2026.04-01 +- [**ModIsom**](https://gap-packages.github.io/modisom/): 3.0.0 -> 3.1.0 +- [**ModulePresentationsForCAP**](https://homalg-project.github.io/pkg/ModulePresentationsForCAP): 2025.09-01 -> 2026.04-01 +- [**Modules**](https://homalg-project.github.io/pkg/Modules): 2024.12-01 -> 2026.04-01 +- [**MonoidalCategories**](https://homalg-project.github.io/pkg/MonoidalCategories): 2025.08-02 -> 2026.05-02 +- [**NConvex**](https://homalg-project.github.io/pkg/NConvex): 2024.12-01 -> 2025.12-02 +- [**NormalizInterface**](https://gap-packages.github.io/NormalizInterface): 1.4.1 -> 1.5.1 +- [**orb**](https://gap-packages.github.io/orb): 5.0.1 -> 5.1.0 +- [**Polycyclic**](https://gap-packages.github.io/polycyclic/): 2.17 -> 2.18 +- [**polymaking**](https://gap-packages.github.io/polymaking/): 0.8.7 -> 0.8.9 +- [**PrimGrp**](https://gap-packages.github.io/primgrp/): 4.0.1 -> 4.0.2 +- [**qpa**](https://gap-packages.github.io/qpa): 1.35 -> 1.37 +- [**RCWA**](https://gap-packages.github.io/rcwa/): 4.8.0 -> 4.9.0 +- [**recog**](https://gap-packages.github.io/recog): 1.4.4 -> 1.5.1 +- [**RingsForHomalg**](https://homalg-project.github.io/pkg/RingsForHomalg): 2024.11-02 -> 2026.05-01 +- [**SCO**](https://homalg-project.github.io/pkg/SCO): 2023.08-01 -> 2025.12-01 +- [**Semigroups**](https://semigroups.github.io/Semigroups): 5.5.4 -> 5.6.3 +- [**singular**](https://gap-packages.github.io/singular/): 2025.08.26 -> 2026.05.05 +- [**SmallClassNr**](https://stertooy.github.io/SmallClassNr): 1.4.2 -> 1.5.1 +- [**ToolsForHomalg**](https://homalg-project.github.io/pkg/ToolsForHomalg): 2025.05-01 -> 2026.04-01 +- [**TwistedConjugacy**](https://stertooy.github.io/TwistedConjugacy): 3.1.1 -> 3.3.2 +- [**typeset**](https://gap-packages.github.io/typeset/): 1.2.3 -> 1.2.4 +- [**utils**](https://gap-packages.github.io/utils): 0.92 -> 0.95 +- [**walrus**](https://gap-packages.github.io/walrus): 0.9991 -> 0.9992 +- [**Wedderga**](https://gap-packages.github.io/wedderga): 4.11.1 -> 4.11.3 +- [**XMod**](https://gap-packages.github.io/xmod/): 2.95 -> 2.98 +- [**ZeroMQInterface**](https://gap-packages.github.io/ZeroMQInterface/): 0.17 -> 0.18 + + ## GAP 4.15.1 (October 2025) The following gives an overview of the changes compared to the previous diff --git a/CITATION b/CITATION index 906d89e6a5..bcd784c127 100644 --- a/CITATION +++ b/CITATION @@ -2,23 +2,23 @@ Please use one of the following samples to cite GAP version from this installati Text: -[GAP] GAP – Groups, Algorithms, and Programming, Version 4.16dev, +[GAP] GAP – Groups, Algorithms, and Programming, Version 4.17dev, The GAP Group (this year), https://www.gap-system.org. HTML:

[GAP] - GAP – Groups, Algorithms, and Programming, Version 4.16dev, + GAP – Groups, Algorithms, and Programming, Version 4.17dev, The GAP Group (this year), https://www.gap-system.org.

BibXML: - + <C>GAP</C> – <C>G</C>roups, <C>A</C>lgorithms, - and <C>P</C>rogramming, <C>V</C>ersion 4.16dev + and Programming, Version 4.17dev https://www.gap-system.org this year GAP @@ -28,8 +28,8 @@ BibXML: BibTeX: -@misc{ GAP4.16dev, - title = {{GAP} {\textendash} {G}roups, {A}lgorithms, and {P}rogramming, {V}ersion 4.16dev}, +@misc{ GAP4.17dev, + title = {{GAP} {\textendash} {G}roups, {A}lgorithms, and {P}rogramming, {V}ersion 4.17dev}, organization = {The GAP {G}roup}, year = {this year}, howpublished = {\href{https://www.gap-system.org}{\texttt{https://www.gap-system.org}}}, @@ -41,7 +41,7 @@ If you are not using BibTeX, here is the bibliography entry produced by BibTeX (in bibliography style `alpha'): \bibitem[GAP]{GAP4} -\emph{GAP -- Groups, Algorithms, and Programming}, Version 4.16dev, +\emph{GAP -- Groups, Algorithms, and Programming}, Version 4.17dev, The GAP~Group (this year), \verb+https://www.gap-system.org+. If you have (predominantly) used one or more particular GAP packages, diff --git a/COPYRIGHT b/COPYRIGHT index 6a58d3bd37..b144b05166 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with GAP; if not, see . -Copyright (C) 1988-2025 by its authors, which include: +Copyright (C) 1988-2026 by its authors, which include: * Ákos Seress * Alex Wegner diff --git a/Makefile.rules b/Makefile.rules index ffe22eb1ba..e2512739ec 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -24,8 +24,11 @@ default: all ######################################################################## # Developer helper targets ######################################################################## -test_release_notes: - cd dev/releases && python3 -m pytest test_release_notes.py +test_release_scripts: + cd dev/releases && python3 -m pytest +.PHONY: test_release_scripts + +test_release_notes: test_release_scripts .PHONY: test_release_notes diff --git a/configure.ac b/configure.ac index 1c313ffb8a..10b9b528f8 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl Setup autoconf dnl AC_PREREQ([2.68]) -m4_define([gap_version], [4.16dev]) +m4_define([gap_version], [4.17dev]) m4_define([gap_releaseday], [today]) m4_define([gap_releaseyear], [this year]) @@ -727,12 +727,12 @@ for READLINE_PREFIX in ${READLINE_SEARCH_PATH} ; do [DEFAULTS_EREADLINE],[ dnl ereadline is the name of GNU readline library on OpenBSD READLINE_PREFIX="" - READLINE_CPPFLAGS="-I/usr/local/include/ereadline" + READLINE_CPPFLAGS="-isystem /usr/local/include/ereadline" READLINE_LDFLAGS="" READLINE_LIBS="-lereadline" ], [*],[ - READLINE_CPPFLAGS="-I${READLINE_PREFIX}/include" + READLINE_CPPFLAGS="-isystem ${READLINE_PREFIX}/include" READLINE_LDFLAGS="-L${READLINE_PREFIX}/lib" READLINE_LIBS="-lreadline" ] diff --git a/dev/ci.sh b/dev/ci.sh index e45ca39268..170a346368 100755 --- a/dev/ci.sh +++ b/dev/ci.sh @@ -422,6 +422,10 @@ GAPInput ;; + testinstall-bare) + $GAP $(gap_cover_arg) --bare $SRCDIR/tst/testinstall.g + ;; + *) if [[ ! -f $SRCDIR/tst/${TEST_SUITE}.g ]] then diff --git a/dev/migratedoc.tex b/dev/migratedoc.tex deleted file mode 100644 index 8e3f02270e..0000000000 --- a/dev/migratedoc.tex +++ /dev/null @@ -1,1141 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%W migratedoc.tex GAP documentation Thomas Breuer -%W & Frank Celler -%W & Martin Schoenert -%W & Heiko Theissen -%% -%% -%Y Copyright 1997, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany -%% -%% self-contained document with the former chapter -%% ``Migrating to GAP 4'' of the GAP Tutorial -%% -\input gapmacro -\BeginningOfBook{mig} -\TitlePage{ - \centerline{\titlefont GAP}\bigskip - \centerline{\secfont Release 4.5}\medskip - \centerline{\secfont May 2012}\bigskip\bigskip - \centerline{\titlefont Migrating to GAP 4}\vfill - \centerline{\secfont The GAP Group}\bigskip - \centerline{\secfont https://www.gap-system.org} -} -\TableOfContents -\FrontMatter -Copyright {\copyright} (1987-2012) for the core -part of the {\GAP} system by the {\GAP} Group. - -Most parts of the {\GAP} distribution, including -the core part of the {\GAP} system, are distributed -under the terms of the GNU General Public License -(see {\tt{https://www.gnu.org/licenses/gpl.html}} -or the file {\tt GPL} in the {\tt etc} directory -of the {\GAP} installation). - -More detailed information about copyright and -licenses of parts of this distribution can be -found in the {\GAP}~4 Reference manual -(see {\bf Reference: Copyright and License}). - -{\GAP} is developed over a long time and has -many authors and contributors. More detailed -information can be found in the {\GAP}~4 -Reference manual (see {\bf Reference: Authors and Maintainers}). - -\Chapters - -\Chapter{Migrating to GAP 4} - -This chapter is intended to give users who have experience with {\GAP}~3 -some information about what has changed in {\GAP}~4. -In particular, it informs about changed command line options -(see~"Changed Command Line Options"), -the new global variable `fail' (see~"Fail"), -some functions that have changed their behaviour -(see~"Changed Functionality") or their names -(see~"Changed Variable Names"), -and some conventions used for variable names (see~"Naming Conventions"). - -Then the new concepts of {\GAP}~4 are sketched, -first that of mutability or immutability (see~"Immutable Objects"), -with the explanation of related changes in functions that copy objects -(see~"Copy"), -then the concepts of operations and method selection, which are compared -with the use of operations records in {\GAP}~3 -(see~"Attributes vs. Record Components", "Operations Records", -and~"Operations vs. Dispatcher Functions"). - -More local changes affect the concepts of notions of generation -(see~"Different Notions of Generation"), -of parents (see~"Parents and Subgroups"), -of homomorphisms (see~"Homomorphisms vs. General Mappings", -"Homomorphisms vs. Factor Structures", -and~"Isomorphisms vs. Isomorphic Structures"), -how elements in finitely presented groups are treated -(see~"Elements of Finitely Presented Groups"), -how information about progress of computations can be obtained -(see~"The Info Mechanism"), -and how one gets information in a `break' loop -(see~"Debugging"). - -%Commented out: no longer provided with GAP 4.5 -%While a ``{\GAP}~3 compatibility mode'' is provided -%(see "Compatibility Mode"), -%its use will disable some of the new features of {\GAP}~4. -%Also it certainly can only try to provide partial compatibility. - -%For a detailed explanation of the new features and concepts of {\GAP}~4, -%see the manual ``Programming in GAP''. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Changed Command Line Options} - -In {\GAP}~4, the `-l' option is used to specify the *root directory* -(see ``GAP Root Directory'' in the {\GAP}~4 Reference Manual) -of the {\GAP} distribution, -which is the directory containing the `lib' and `doc' subdirectories. -Note that in {\GAP}~3 this option was used to specify the path to the -`lib' directory. - -The `-h' option of {\GAP}~3 has been removed, -the path(s) for the documentation are deduced automatically in {\GAP}~4. - -The option `-g' is now used to print information only about full garbage -collections. -The new option `-g -g' generates information about partial -garbage collections too. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Fail} - -There is a new global variable - -\>`fail'{fail instead of false} - -in {\GAP}~4. -It is intended as a return value of a function for the case that it -could not perform its task. -For example, `Inverse' returns `fail' if it is called with a singular -matrix, and `Position' returns `fail' if the second argument is not -contained in the list given as first argument. - -{\GAP}~3 handled such situations by either signalling an error, -for example if it was asked for the inverse of a singular matrix, -or by (mis)using `false' as return value, as in the example `Position'. -Note that in the first example, in {\GAP}~3 it was necessary to check -the invertibility of a matrix before one could safely ask for its -inverse, which meant that roughly the same work was done twice. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Changed Functionality} - -Some functions that were already available in {\GAP}~3 behave -differently in {\GAP}~4. This section lists them. - -\>Orbit( ,) - -The {\GAP}~3 manual promised that would be the first entry of the -resulting orbit. This was wrong already there in a few cases, therefore -{\GAP}~4 does not promise anything about the ordering of points in an orbit. - -\>Order( ) - -only takes the element and computes its multiplicative order. -%Calling `Order' with two arguments is permitted only in the -%{\GAP}~3 compatibility mode, see~"Compatibility Mode". -(Note that it does not make sense anymore to specify a group as -first argument w.r.t. which the order of the second argument shall -be computed, see~"Elements of Finitely Presented Groups".) - -\>Position( , ) - -If is not contained in the list then `fail' is returned -in {\GAP}~4 (see~"Fail"), whereas `false' was returned in {\GAP}~3. - - -\>PermGroupOps.ElementProperty( , [, ] ) - -In {\GAP}~3, this function took either two or three arguments, -the optional argument being a subgroup of that stabilizes -in the sense that for any element in , -either all elements or no element in the coset ` \* ' have the -property . - -The {\GAP}~4 function `ElementProperty', however, -takes between two and four arguments, -and the subgroup known from {\GAP}~3 has to be entered as the *fourth* -argument *not* the third. -(The third argument in the {\GAP}~4 function denotes a subgroup -stabilizing in the sense that either all elements or no element -in right cosets ` \* ' have the property .) - -(This discrepancy was discovered only in March~2002, -short before the release of {\GAP}~4.3.) - - -\>Print( , ... ) - -Objects may appear on the screen in a different way, -depending on whether they are printed by the read eval print loop -or by an explicit call of `Print'. -The reason is that the read eval print loop calls the operation `ViewObj' -and not `PrintObj', whereas `Print' calls `PrintObj' for each of its -arguments. -This permits the installation of methods for printing objects in a short form -in the read eval print loop while retaining `Print' to display -the object completely. -See also Section ``View and Print'' in the {\GAP}~4 Reference Manual. - -(`PrintObj' is installed as standard method `ViewObj', so it is -not really necessary to have a `ViewObj' method for an object.) - -\>PrintTo( , , ... ) - -In {\GAP}~3, `PrintTo' could be (mis)used to ``redirect'' the text -*printed* by a function (that is, *not* only the output of a function) -to a file by entering the function call as second argument. -This was used mainly in order to avoid many calls of `AppendTo'. -In {\GAP}~4, this feature has disappeared. -One can use streams (see Chapter ``Streams'' in the {\GAP}~4 Reference Manual) -instead in order to write files efficiently. - -\break - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Changed Variable Names} - -\indextt{AgGroup} -\indextt{ApplyFunc} -\indextt{Backtrace} -\indextt{CharTable} -\indextt{Denominator} -\indextt{DepthVector} -\indextt{Elements} -\indextt{IsBijection} -\indextt{IsFunc} -\indextt{IsMat} -\indextt{IsRec} -\indextt{IsSet} -\indextt{LengthWord} -\indextt{NOfCyc} -\indextt{Numerator} -\indextt{RandomInvertableMat} -\indextt{RecFields} -\indextt{X} - -Some functions have changed their name without changing the -functionality. -A -- probably incomplete -- list follows -\begintt - GAP 3 GAP 4 - - AgGroup PcGroup # (also composita) - ApplyFunc CallFuncList - Backtrace Where - CharTable CharacterTable # (also composita) - Denominator DenominatorRat - DepthVector PositionNonZero - Elements AsSSortedList - IsBijection IsBijective - IsFunc IsFunction - IsMat IsMatrix - IsRec IsRecord - IsSet IsSSortedList - LengthWord Length - NOfCyc Conductor - Numerator NumeratorRat - NormedVector NormedRowVector - Operation Action # (also composita) - Order(G,g) Order(g) - OrderMat Order - OrderPerm Order - RandomInvertableMat RandomInvertibleMat - RecFields RecNames - X Indeterminate -\endtt - -%See Section~"Compatibility Mode" for a way to make the old names -%available again. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Naming Conventions} - -The way functions are named has been unified in {\GAP}~4. -This might help to memorize or even guess names of library functions. - -If a variable name consists of several words then the first -letter of each word is capitalized. - -If the first part of the name of a function is a verb then the function -may modify its argument(s) but does not return anything, -for example `Append' appends the list given as second argument to the -list given as first argument. -Otherwise the function returns an object without changing the arguments, -for example `Concatenation' returns the concatenation of the lists -given as arguments. - -If the name of a function contains the word `By' then the return value is -thought of as built in a certain way from the parts given as arguments. -For example, `GroupByGenerators' returns a group built from its group -generators, and creating a group as a factor group of a given group -by a normal subgroup can be done by taking the image of -`NaturalHomomorphismByNormalSubgroup' -(see also~"Homomorphisms vs. Factor Structures"). -Other examples of ```By''' functions are `GroupHomomorphismByImages' and -`UnivariateLaurentPolynomialByCoefficients'. - -If the name of a function contains the word `Of' then the return value is -thought of as information deduced from the arguments. -Usually such functions are attributes -(see ``Attributes'' in the {\GAP}~4 Reference Manual). -Examples are `GeneratorsOfGroup', which returns a list of generators for -the group entered as argument, or `DiagonalOfMat'. - -For the setter and tester functions of an attribute -(see~"Attributes vs. Record Components" in this document -and ``Attributes'' in the {\GAP}~4 Reference Manual) -the names `Set' resp.~`Has' are available. - -If the name of a function ends with `NC' then there is another -function with the same name except that the `NC' is missing. -`NC' stands for ``no check''. -When is called then it checks whether its arguments are valid, -and if so then it calls . -The functions `SubgroupNC' and `Subgroup' are a typical example. - -The idea is that the possibly time consuming check of the arguments -can be omitted if one is sure that they are unnecessary. -For example, if an algorithm produces generators of the derived subgroup -of a group then it is guaranteed that they lie in the original group; -`Subgroup' would check this, and `SubgroupNC' omits the check. - -Needless to say, all these rules are not followed slavishly, -for example there is one operation `Zero' instead of two operations -`ZeroOfElement' and `ZeroOfAdditiveGroup'. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Immutable Objects} - -{\GAP}~4 supports ``immutable'' objects. Such objects cannot be -changed, attempting to do so issues an error. Typically attribute -values are immutable, and also the results of those binary arithmetic -operations where both arguments are immutable. -For example, `[1..100]+[1..100]' is a -mutable list and `2 \* Immutable([1..100])' is an immutable -list, both are equal to the (mutable) list `[2,4..200]'. - -There is no way to *make* an immutable object mutable, one can only -get a mutable copy by `ShallowCopy'. The other way round, -`MakeImmutable' makes a (mutable or immutable) object and all its -subobjects immutable; one must be very careful to use `MakeImmutable' -only for those objects that are really newly created, for such objects -the advantage over `Immutable' is that no copy is made. - -More about immutability can be found in Sections ``Immutability'' in -the {\GAP}~4 Tutorial and ``Mutability and Copyability'' in the {\GAP}~4 -Reference Manual. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Copy} - -\indextt{StructuralCopy} -\indextt{ShallowCopy} -The function `Copy' of {\GAP}~3 is not supported in {\GAP}~4. This -function was used to create a copy of its argument with -the properties that and had no subobjects in common and -that if two subobjects of were identical then also the -corresponding subobjects of were identical. - -The possibility of having immutable objects (see~"Immutable Objects") can and -should be used to avoid unnecessary copying. -Namely, given an immutable object one needs to copy it only if one wants -to get a modified object, and in such a situation usually it is -sufficient to use `ShallowCopy', or at least one knows how deep one must -copy in order to do the changes one has in mind. - -For example, suppose you have a matrix group, and you want to -construct a list of matrices by modifying the group generators. This -list of generators is immutable, so you call `ShallowCopy' to get a -mutable list that contains the same matrices. If you only want to -exchange some of them, or to append some other matrices, this shallow -copy is already what you need. So suppose that you are interested in -a list of matrices where some rows are also changed. For that, you -call `ShallowCopy' for the matrices in question, and you get matrices -whose rows can be changed. If you want to change single entries in -some rows, `ShallowCopy' must be called to get mutable copies of these -rows. Note that in all these situations there is no danger to change, -i.e., to destroy the original generators of the matrix group. - -If one needs the facility of the `Copy' function of {\GAP}~3 to get a -copy with the same structure then one can use the new {\GAP}~4 -function `StructuralCopy'. It returns a structural copy that has no -*mutable* subobject in common with its argument. So if -`StructuralCopy' is called with an immutable object then this object -itself is returned, and if `StructuralCopy' is called with a mutable -list of immutable objects then a shallow copy of this list is -returned. - -Note that `ShallowCopy' now is an operation. So if you create your -own type of (copyable) objects then you must define what a shallow -copy of these objects is, and install an appropriate method. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Attributes vs. Record Components} - -In {\GAP}~3, many complex objects were represented via records, for -example all domains. Information about these objects was stored in -components of these records. For the user, this was usually not -relevant, since there were functions for computing information about -the objects in question. For example, if one was interested in the -size of a group then one could call `Size'. - -But since it was guaranteed that the size of a domain was stored -as value of the component `size', it was allowed to access `.size' -if this component was bound, and a check for this was possible via -`IsBound( .size )'. - -In {\GAP}~4, only the access via functions is admissible. One reason -is the following basic rule. - -*From the information that a given {\GAP}~4 object is for example a -domain, one cannot conclude that this object has a certain -representation.* - -For attributes like `Size', {\GAP}~4 provides two related functions, -the *setter* and the *tester* of the attribute, which can be used to -set an attribute value and to check whether the value of an attribute -is already stored for an object (see also ``Attributes'' in the {\GAP}~4 -Reference Manual). For example, if is a domain in {\GAP}~4 then -`HasSize( )' is `true' if the size of is already stored, and -`false' otherwise. In the latter case, if you know that the size of - is then you may store it by `SetSize( , )'. - -Besides the flexibility in the internal representation of objects, -storing information only via function calls has also the advantage -that {\GAP}~4 is able to draw conclusions automatically. For example, -as soon as it is stored that a group is nilpotent, it is also stored -that it is solvable, see Chapters ``Types of Objects'' and -``Method Selection'' in the {\GAP}~4 Reference Manual for the details. - -As a consequence, you cannot put your favourite information into a -domain by assigning it to a new component like -`.myPrivateInfo'. Instead you can introduce a new attribute and -then use its setter, -see Section ``Attributes'' in the {\GAP}~4 Reference Manual. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Different Notions of Generation} - -As in {\GAP}~3, a *domain* in {\GAP}~4 is a structured set. - -The same set can have different structures, for example a field can be -regarded as a ring or as an algebra or vector space over a subfield. - -In {\GAP}~3, however, an object representing a ring did not represent -a field, and an object representing a field did not represent a ring. -One reason for this was that the record component `generators' was -used to denote the appropriate generators of the domain. For a ring -, the component `.generators' was a list of ring generators, and -for a field , `.generators' was a list of field generators. - -{\GAP}~4 cleans this up, -see ``Notions of Generation'' in the {\GAP}~4 Tutorial. It supports -many different notions of generation, for example one can ask for -magma generators of a group or for generators of a field as an additive -group. A subtle but important distinction is that between generators -of an algebra and of an algebra-with-one. - -So the attributes `GeneratorsOfGroup', `GeneratorsOfMagma', -`GeneratorsOfRing', `GeneratorsOfField', `GeneratorsOfVectorSpace', -and so on, replace the access to the `generators' component. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Operations Records} - -Already in {\GAP}~3 there were several functions that were applicable -to many different kinds of objects, for example `Size' could be -applied to any domain, and the binary infix multiplication `*' could -be used to multiply two matrices, an integer with a row vector, or a -permutation with a permutation group. This was implemented as -follows. Functions like `Size' and `*' tried to find out what -situation was described by its arguments, and then it called a more -specific function to compute the desired information. These more -specific functions, let us call them *methods* as they are also called -in {\GAP}~4, were stored in so-called *operations records* of the -arguments. - -For example, every domain in {\GAP}~3 was represented as a record, and -the operations record was stored in the record component `operations'. -If `Size' was called for the domain then the method to compute the -size of the domain was found as value of the `Size' component of the -operations record. - -This was fine for functions taking only one argument, and in principle -it is possible that for those functions an object stored an optimal -method in its operations record. But in the case of more arguments -this is not possible. In a multiplication of two objects in {\GAP}~3, -one had to choose between the methods stored in the operations records -of the arguments, and if for example the method stored for the left -operand was called, this method had to handle all possible right -operands. - -So operations records turned out to be not flexible enough. In -{\GAP}~4, operations records are not supported -%(see~"Compatibility Mode" for a possibility to use your {\GAP}~3 -%code that utilizes operations records, at least to some extent). -A detailed description -of the new mechanism to select methods can be found in -Chapter ``Method Selection'' in the {\GAP}~4 Reference Manual. - -An important point is that the new mechanism allows {\GAP} to take the -relation between arguments into account. So it is possible (and -recommended) to install different methods for different relations -between the arguments. Note that such methods need not do the -extensive argument checking that was necessary in {\GAP}~3, because -most of the checks are done already by the method selection mechanism. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Operations vs. Dispatcher Functions} - -{\GAP}~3 functions like `Size', `CommutatorSubgroup', or -`SylowSubgroup' did mainly call an appropriate method (see~"Operations -Records") after they had checked their arguments. Such functions were -called *dispatchers* in {\GAP}~3. In {\GAP}~4, many dispatchers have -been replaced by *operations*, due to the fact that methods are no -longer stored in operations records (see ``Method Selection'' in -in the {\GAP}~4 Reference Manual for the details). - -Most dispatchers taking only one argument were treated in a special -way in {\GAP}~3, they had the additional task of storing computed -values and using these values in subsequent calls. For example, the -dispatcher `Size' first checked whether the size of the argument was -already stored, and if so then this value was returned; otherwise a -method was called, the value returned by this method was stored in the -argument, and then returned by `Size'. - -In {\GAP}~4, computed values of operations that take one argument -(these operations are called *attributes*) are also stored, only the -mechanism to achieve this has changed, see the sections ``Attributes'' -and ``Properties'' in the {\GAP}~4 Reference Manual. - -So the behaviour of `Size' is the same in {\GAP}~3 and {\GAP}~4. But -note that in {\GAP}~4, it is not possible to access `.size', -see~"Attributes vs. Record Components". As described in~"Operations -Records", {\GAP}~4 does not admit ``bypassing the dispatcher'' by -calling for example `.operations.Size'. This was done in {\GAP}~3 -often for efficiency reasons, but the method selection mechanism of -{\GAP}~4 is fast enough to make this unnecessary. - -If you had written your own dispatchers and put your own methods into -existing operations records then this code will not work in {\GAP}~4. -See ``Creating New Objects'' and ``Method Selection'' in the {\GAP}~4 -Reference Manual for a description of how to define operations and -to install methods. - -Finally, some functions in {\GAP}~3 were hidden in -operations records, e.g., `PermGroupOps.MovedPoints'. -These functions became proper operations in {\GAP}~4. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Parents and Subgroups} - -In {\GAP}~3 there was a strict distinction between parent groups and -subgroups. -The use of the name ``parent'' (instead of ``supergroup'') -was chosen to indicate that the parent of an object was more than just -useful information. -In fact the main reason for the introduction of parents was to provide -a common roof for example for all groups of polycyclic words that -belonged to the same PC-presentation, or for all subgroups of a finitely -presented group (see~"Elements of Finitely Presented Groups"). -A subgroup was never a parent group, and it was possible to create -subgroups only of parent groups. - -In {\GAP}~4 this common roof is provided already by the concept of -*families*, see Section ``Families'' in the {\GAP}~4 Reference Manual. -Thus it is no longer compulsory to use parent groups at all. -On the other hand, parents *may* be used in {\GAP}~4 to provide -information about an object, for example the normalizer of a group in its -parent group may be stored as an attribute value. -Note that there is no restriction on the supergroup that is set to be -the parent, -it is possible to create a subgroup of -any group, this group then being the parent of the new subgroup. -This permits for example chains of subgroups with respective parents, -of arbitrary length. - -As a consequence, the `Parent' command cannot be used in {\GAP}~4 to -test whether the two arguments of `CommutatorSubgroup' fit together, -this is now a question that concerns the relation between the families -of the groups. So the 2-argument version of `Parent' and the now -meaningless function `IsParent' have been abolished. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Homomorphisms vs. General Mappings} - -In {\GAP}~3 there had been a confusion between group homomorphisms and -general mappings, as `GroupHomomorphismByImages' created only a -general mapping that did *not* store whether it was a mapping. This -caused expensive, unwanted, and unnecessary tests whether the mapping -was in fact a group homomorphism. Moreover, the ``official'' -workaround to set some components of the mapping record was quite -unwieldy. - -In {\GAP}~4, `GroupHomomorphismByImages' checks whether the desired -mapping is indeed a group homomorphism; if so then this property is -stored in the returned mapping, otherwise `fail' is returned. If you -want to avoid the checks then you can use -`GroupHomomorphismByImagesNC'. If you want to check whether a general -mapping that respects the group operations is really a group -homomorphism, you can construct it via `GroupGeneralMappingByImages' -and then call `IsGroupHomomorphism' for it. (Note that -`IsGroupHomomorphism' returns `true' if and only if both -`IsGroupGeneralMapping' and `IsMapping' do, so one does in fact check -`IsMapping' in this case.) - -There is *no* function `IsHomomorphism' in {\GAP}~4, -since there are several different operations with respect to which a -mapping can be a homomorphism. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Homomorphisms vs. Factor Structures} - -If $F$ is a factor structure of $G$, with kernel $N$, complete -information about the connection between $F$ and $G$ is provided by -the *natural homomorphism*. - -In {\GAP}~3, the ``official way'' to construct this natural homomorphism -was to create first the factor structure $F$, and then to call -`NaturalHomomorphism' with the arguments $G$ and $F$. -For that, the data necessary to compute the homomorphism was stored in -$F$ when $F$ was constructed. - -In {\GAP}~4, factor structures are not treated in a special way, -in particular they do not store information about a homomorphism. -Instead, the more natural way is taken to construct the natural -homomorphism from $G$ and $N$ by `NaturalHomomorphismByNormalSubgroup' -if $N$ is a normal subgroup of the group $G$, -or by `NaturalHomomorphismByIdeal' if $N$ is an ideal in the ring $G$. -The factor $F$ can then be accessed as the image of this homomorphism, -and of course $G$ is the preimage and $N$ is the kernel. - -Note that {\GAP}~4 does not guarantee anything about the representation -of the factor $F$, it may be a permutation group or a polycyclically -presented group or another kind of group. -Also note that a natural homomorphism need not be surjective. - -A consequence of this change is that {\GAP}~4 does *not* allow you to -construct a natural homomorphism from the groups $G$ and $F$. - -The other common type of homomorphism in {\GAP} 3, ``operation -homomorphisms'', have been replaced (just a name change) by *action -homomorphisms*, which are handled in a similar fashion. That is, an -action homomorphism is constructed from an acting group, an action -domain, and a function describing the operation. The permutation -group arising by the induced action is then the image of this -operation homomorphism. - -The {\GAP}~3 function `Operation' is still supported, under the name `Action', -but from the original group and the result of `Action' it is not -possible to construct the action homomorphism. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Isomorphisms vs. Isomorphic Structures} - -In {\GAP}~3, a different representation of a group could be obtained by -calling `AgGroup' to get an isomorphic polycyclically presented group, -`PermGroup' to get an isomorphic permutation group, and so on. -The returned objects stored an isomorphism in the record component -`bijection'. - -For the same reason as in~"Homomorphisms vs. Factor Structures", -{\GAP}~4 puts emphasis on the isomorphism, -and the isomorphic object in the desired representation can be accessed -as its image. -So you can call `IsomorphismPcGroup' or `IsomorphismPermGroup' in order -to get an isomorphism to a polycyclically presented group or a -permutation group, respectively, and then call `Image' to get the -isomorphic group. - -Note that the image of an action homomorphism with trivial kernel is -also an isomorphic permutation group, but an action homomorphism need -not be surjective, since it may be easier to define it into the full -symmetric group. - -Further note that in {\GAP}~3, a usual application of isomorphisms to -polycyclically presented groups was to utilize the usually more -effective algorithms for solvable groups. However, the new concept of -polycyclic generating systems in {\GAP}~4 makes it possible to apply -these algorithms to arbitrary solvable groups, independent of the -representation. For example, {\GAP}~4 can handle polycyclic -generating systems of solvable permutation groups. So in many cases, -a change of the representation for efficiency reasons may be not -necessary any longer. - -In general `IsomorphismFpGroup' will define a presentation on generators -chosen by the algorithm. The corresponding elements of the original -group can be obtained by the command -\begintt -gens:=List(GeneratorsOfGroup(Image(isofp)),i->PreImagesRepresentative(isofp,i)); -\endtt -If a presentation in the given generators is needed, the command -`IsomorphismFpGroupByGenerators(, )' will produce one. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Elements of Finitely Presented Groups} - -Strictly speaking, {\GAP}~3 did not support elements of finitely -presented groups. Instead, the ``words in abstract generators'' of -the underlying free groups were (mis)used. This caused problems -whenever calculations with elements were involved, the most obvious -ones being wrong results of element comparisons. Also functions -that should in principle work for any group were not applicable to -finitely presented groups. In effect, a finitely presented group had -to be treated in a special way in {\GAP}~3. - -{\GAP}~4 distinguishes free groups and their elements from finitely -presented groups and their elements. Comparing two elements of a -finitely presented group will yield either the correct result or no -result at all. - -Note that in {\GAP}~4, the arithmetic and comparison operations for -group elements do not depend on a context provided by a group that -contains the elements. In particular, in {\GAP}~4 it is not -meaningful to call `Order( , )' for a group and an element -. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Polynomials} - -In {\GAP}~3, polynomials were defined over a field. So a polynomial over -`GF(3)' was different from a polynomial over `GF(9)', even if the -coefficients were exactly the same. - -{\GAP}~4 defines polynomials only over a characteristic. This makes it -possible for example to multiply a polynomial over `GF(3)' with a polynomial -over `GF(9)' without the need to convert the former to the larger field. - -However it has an effect on the result of `DefaultRing' for polynomials: -In {\GAP}~3 the default ring for a polynomial was the polynomial ring of the -field over which the polynomial was defined. In {\GAP}~4 no field is -associated, so (to avoid having to define the algebraic closure as the only -other sensible alternative) the default ring of a polynomial is the -`DefaultRing' of its coefficients. - -This has an effect on `Factors': If no ring is given, a polynomial is -factorized over its `DefaultRing' and so `Factors()' -might return different results. - -To be safe from this problem, if you are not working over prime fields, -rather call `Factors(,)' with the appropriate polynomial ring -and change your code accordingly. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{The Info Mechanism} - -Sometimes it is useful to get information about the progress of a -calculation. -Many {\GAP} functions contain statements to display such information -under certain conditions. - -In {\GAP}~3, these statements were calls to functions such as -`InfoGroup1' or `InfoGroup2', and if the user assigned `Print' to -these variables then this had the effect to switch on the printing of -information. -`InfoGroup2' was used for more detailed information than `InfoGroup1'. -One could switch off the printing again by assigning `Ignore' to the -variables, and `Ignore' was also the default value. - -{\GAP}~4 uses one function `Info' for the same purpose, -which is a function that takes as first argument an *info class* such as -`InfoGroup', as second argument an *info level*, and the print statements -as remaining arguments. -The level of an info class is set to by calling -`SetInfoLevel( , )'. -An `Info' statement is printed only if its second argument is smaller than -or equal to the current info level. -For example, -\beginexample -gap> test:= function( obj ) -> Info( InfoGroup, 2, "This is useful, isn't it?" ); -> return obj; -> end;; -gap> test( 1 ); -1 -gap> SetInfoLevel( InfoGroup, 2 ); -gap> test( 1 ); -#I This is useful, isn't it? -1 -\endexample - -As in {\GAP}~3, if an info statement is ignored then its arguments are -not evaluated. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\Section{Debugging} - -\indextt{Backtrace} -\indextt{DownEnv} -\indextt{Where} -If {\GAP}~4 runs into an error or is interrupted, -it enters a break loop. -The command `Where( )', which replaces `Backtrace' of {\GAP}~3, -can be used to display lines of information about the current -function call stack. - -As in {\GAP}~3, access is only possible to the variables of the current -level in the function stack, -but in {\GAP}~4 the function `DownEnv', with a positive or negative -integer as argument, permits one to step down or up in the -stack. - -When interrupting, the first line printed by `Where' actually may be -one level higher, as the following example shows -\begintt -gap> OnBreak := function() Where(0); end;; # eliminate back-tracing on -gap> # entry to break loop -gap> test:= function( n ) -> if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; -gap> test( 1 ); -Error, ! -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue -brk> Where(); - called from -test( n + 1 ); called from -test( n + 1 ); called from -test( n + 1 ); called from -( ) called from read-eval-loop -brk> n; -4 -brk> DownEnv(); -brk> n; -3 -brk> Where(); - called from -test( n + 1 ); called from -test( n + 1 ); called from -( ) called from read-eval-loop -brk> DownEnv( 2 ); -brk> n; -1 -brk> Where(); - called from -( ) called from read-eval-loop -brk> DownEnv( -2 ); -brk> n; -3 -brk> quit; -gap> OnBreak := Where;; # restore OnBreak to its default value -\endtt - -For purposes of debugging, it can be helpful sometimes, to see what -information is stored within an object. In {\GAP}~3 this was possible using -`RecFields' because the objects in question were represented via records. -For component objects, {\GAP}~4 permits the same by -`NamesOfComponents( )', which will list all components present. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% \Section{Compatibility Mode} -% -% For users who want to use {\GAP}~3 code with as little changes as -% possible, a compatibility mode is provided by {\GAP}~4. -% This mode must be turned on explicitly by the user. -% -% It should be noted that this compatibility mode has not been tested -% thoroughly. -% -% The compatibility mode can be turned on by loading some of the following -% files with `ReadLib'. -% The different files address different aspects of compatibility. -% -% \beginitems -% `compat3a.g' & -% makes some {\GAP}~3 function names available that were changed -% in {\GAP}~4, -% and provides code for some {\GAP}~3 features that were -% deliberately left out from the {\GAP}~4 library. -% For example, -% almost all variable names concerning character theory that are -% mentioned in the {\GAP}~3 manual, -% such as `CharTable' and `SubgroupFusions', -% are available after `compat3a.g' has been read; -% the only exceptions are names of operations records. -% -% `compat3b.g' & -% implements the availability of ``components'' of domains; -% besides components that have no meaning for the rest of the {\GAP}~4 -% library, such as `.myInfo', there are components associated to -% attributes; for example `.size' is redirected to the call of the -% attribute `Size', `IsBound( .size )' to the call of its tester, -% and `.size:= ' to the call of its setter. -% (An important special case is the component `operations', see below.) -% -% `compat3c.g' & -% permits you to implement your own elements represented as records, -% and using operations records to provide a `Print' method and -% the basic arithmetic operations. -% When using operations records, it is probably a good idea to -% use *immutable* operations records; for example, if the results -% of arithmetic operations are records with operations records then -% this avoids to create shallow copies of the operations records -% in the call to `Immutable' for the results. -% \enditems -% -% The following features are accessible only via starting {\GAP} with -% the command line option `-O' and may damage some features of {\GAP}~4 -% permanently for the current session. -% -% With this option, also the files listed above are read automatically. -% -% \beginitems -% `compat3d.g' & -% provides some {\GAP}~3 functions like `Domain', simulates the -% {\GAP}~3 behaviour of `IsString' (to convert a list to string -% representation if possible), and replaces `fail' by `false'; -% these changes destroy parts of the functionality of {\GAP}~4. -% \enditems -% -% Some words concerning the simulation of operations records may be -% necessary. -% -% The operations records of the {\GAP}~3 library, such as `DomainOps' -% and `GroupOps', are available *only* for access to their components, -% whose values are {\GAP}~4 operations; for example, the value of both -% `DomainOps.Size' and `GroupOps.Size' is the operation `Size'. So it -% is *not* safely possible to delegate from a `Size' method in another -% operations record to `DomainOps.Size'. Also it is not possible to -% change these predefined operations records. -% -% If one wants to install individual methods for a given object -% via the mechanism of operations records then one can construct a new -% operations record with `OperationsRecord', assign the desired methods -% to components of this record, and then assign the operations record to -% `.operations'. Whenever an operation that is associated with a -% component of the operations record is called with as first -% argument, the value of is chosen as the method. -% -% In the case of the binary operations `=', `\<', `+', `-', `*', `/', -% `Comm', and `LeftQuotient', -% this also happens if is the right-hand argument. -% As in {\GAP}~3, if both arguments of one of the above binary operations -% have operations records containing a function for this operation, -% then the function in the operations record of the right-hand argument -% is chosen. -% -% We give a small example how the compatibility mode works. -% -% Suppose we want to deal with new objects that are derived from known -% field elements by distorting their multiplication. Namely, let $a'$ -% and $b'$ be the new objects corresponding to the field elements $a$, -% $b$, and define $a' \* b' = a b - a - b + 2$. -% -% In {\GAP}~3, this problem was solved by representing each new object -% by a record that stored the corresponding ``old'' object and an -% operations record, where the latter was a record containing the -% functions applicable to the new object. After the library file -% `compat3c.g' has been read, we can use this construction of the -% operations record and of the new objects. Note that operations -% records must be created with the function `OperationsRecord' (this was -% also the norm in {\GAP}~3), starting with an empty record would not work. -% For our intended application, we thus start with the following two -% lines of code. -% -% \begintt -% gap> ReadLib( "compat3c.g" ); -% gap> MyOps:= OperationsRecord( "MyOps" );; -% HasMyOps := NewFilter( "HasMyOps" ); -% \endtt -% -% In order to make the translation from {\GAP}~3 code to {\GAP}~4 -% easier, {\GAP} prints the definition of filters associated with -% operations records and the method installations for operations -% corresponding to components of the operations records. The output -% line printed by {\GAP} after the call of `OperationsRecord' is one -% such case. -% -% Now we add our multiplication function to the operations record, -% and again {\GAP}~4 prints a translation to {\GAP}~4 code. -% -% \begintt -% gap> MyOps.\* := function( a, b ) -% > return rec( x:= a.x * b.x - a.x - b.x + 2, -% > operations := MyOps ); -% > end;; -% # If the following method installation matches the requirements -% # of the operation `PROD' then `InstallMethod' should be used. -% # It might be useful to replace the rank `SUM_FLAGS' by `0'. -% InstallOtherMethod( PROD, -% "for object with `MyOps' as first argument", -% true, -% [ HasMyOps, IsObject ], SUM_FLAGS, -% MyOps.\* ); -% -% # For binary infix operators, a second method is installed -% # for the case that the object with `MyOps' is the right operand; -% # since this case has higher priority in GAP 3, the method is -% # installed with higher rank `SUM_FLAGS + 1'. -% InstallOtherMethod( PROD, -% "for object with `MyOps' as second argument", -% true, -% [ IsObject, HasMyOps ], SUM_FLAGS + 1, -% MyOps.\* ); -% \endtt -% -% Let us look how this installation works. -% -% \begintt -% gap> a:= rec( x:= 3, operations:= MyOps ); -% rec( x := 3, operations := MyOps ) -% gap> b:= rec( x:= 5, operations:= MyOps ); -% rec( x := 5, operations := MyOps ) -% gap> a * b; -% rec( x := 9, operations := MyOps ) -% \endtt -% -% (In more complicated cases, we might run into problems, but this was -% already the case in {\GAP}~3. For example, suppose we want to support -% the multiplication of two operands having different operations -% records; then it is not clear which of the two multiplication -% functions is to be chosen, and in {\GAP}~3, the only way out was to -% change the multiplication functions, in order to make them aware of -% such situations.) -% -% If we are now interested to translate the code to {\GAP}~4 in the -% sense that no compatibility mode is needed, we can use what {\GAP}~4 -% has printed above. (The same example is dealt with in Section ``An -% Example -- Designing Arithmetic Operations'' in the {\GAP}~4 Reference -% Manual.) -% -% The objects will no longer be records with `operations' component. -% Instead of records we may use so-called component objects -% with record-like access to components, -% and instead of the `operations' component, we give the objects a -% type that has the filter `HasMyOps' set. -% \begintt -% HasMyOps := NewFilter( "HasMyOps" ); -% MyType := NewType( NewFamily( "MyFamily" ), -% HasMyOps and IsComponentObjectRep ); -% \endtt -% (More about families and representations in this context can be found -% in the same chapter of the {\GAP}~4 Reference Manual mentioned above.) -% -% The next step is to write a function that creates a new object. -% It may look as follows. -% \begintt -% MyObject := function( val ) -% return Objectify( MyType, rec( x:= val ) ); -% end; -% \endtt -% -% The multiplication function shall return an object with the -% filter `HasMyOp', so we change it as follows. -% \begintt -% gap> MyMult := function( a, b ) -% > return MyObject( x:= a!.x * b!.x - a!.x - b!.x + 2 ); -% > end;; -% \endtt -% Note that the component access for these objects -% works via `!.' instead of `.'; -% further note that no operations record needs to appear here, -% the filter takes its role. -% -% Finally, we install the multiplication for at least one argument -% with the new filter, as had been printed by {\GAP}~4 in the -% session shown above. -% \begintt -% InstallOtherMethod( PROD, -% "for object with `MyOps' as first argument", -% true, -% [ HasMyOps, IsObject ], 0, -% MyMult ); -% -% InstallOtherMethod( PROD, -% "for object with `MyOps' as second argument", -% true, -% [ IsObject, HasMyOps ], 1, -% MyMult ); -% \endtt -% And now the example works (again). -% \begintt -% gap> a:= MyObject( 3 ); -% -% gap> b:= MyObject( 5 ); -% -% gap> a * b; -% -% gap> last!.x -% 9 -% \endtt -% -% We may install a method to print our objects in a nice way; -% we could have done this for the operations record `MyOps' -% in the compatibility mode, -% the printed output would look similar to the following. -% \begintt -% InstallOtherMethod( PRINT_OBJ, -% "for object with `MyOps' as first argument", -% true, -% [ HasMyOps ], 0, -% function( obj ) Print( "MyObject( ", obj!.x, " )" ); end ); -% \endtt -% -% Now the example behaves as follows. -% \begintt -% gap> a; b; a * b; -% MyObject( 3 ) -% MyObject( 5 ) -% MyObject( 9 ) -% \endtt -% -% Maybe now we want to improve the installation. -% The multiplication function we want to use is apparently -% thought only for the case that *both* operands have -% the filter `HasMyOps' (and a component `x'). -% So it is reasonable to replace the two methods for -% the multiplication by one method for which both arguments -% are required to have the filter. -% \begintt -% InstallOtherMethod( PROD, -% "for two objects with `MyOps'", -% true, -% [ HasMyOps, HasMyOps ], 0, -% MyMult ); -% \endtt -% -% At first sight, the {\GAP}~4 approach seems to be much more -% complicated. -% But the last example shows that in {\GAP}~4, -% each method can be installed more specifically for the appropriate -% situation. -% Moreover, it is for example possible to install a method -% for the multiplication of an integer and a `HasMyOps' object; -% note that --contrary to the situation in {\GAP}~3-- -% such a method is independent from already existing methods -% in the sense that these need not be changed when -% new functionality is added. -% -% Another example that uses this part of the compatibility mode can be -% found in the file `tst/compat3.tst' of the {\GAP}~4 distribution. - -\EndOfBook - diff --git a/dev/releases/make_archives.py b/dev/releases/make_archives.py index 5b06f8e0f3..33fe219c1b 100755 --- a/dev/releases/make_archives.py +++ b/dev/releases/make_archives.py @@ -29,6 +29,7 @@ from utils import ( download_with_sha256, error, + normalize_archive_permissions, notice, patchfile, verify_command_available, @@ -211,14 +212,11 @@ def run_with_log(args: List[str], name: str, msg: Optional[str] = None) -> None: notice("Extracting package tarballs") with tarfile.open(tmpdir + "/" + all_packages_tarball) as tar: tar.extractall(path="pkg") - # for some reason pkg sometimes ends up with permission 0700 so - # we make sure to fix that here - subprocess.run(["chmod", "0755", "pkg"], check=True) - # ensure all files are at readable by everyone - subprocess.run(["chmod", "-R", "a+r", "."], check=True) with tarfile.open(tmpdir + "/" + req_packages_tarball) as tar: tar.extractall(path=tmpdir + "/" + req_packages) + notice("Normalizing permissions in required packages") + normalize_archive_permissions(tmpdir + "/" + req_packages) notice("Building GAP's manuals") run_with_log(["make", "doc"], "gapdoc", "building the manuals") @@ -278,6 +276,9 @@ def run_with_log(args: List[str], name: str, msg: Optional[str] = None) -> None: notice("Removing generated files we don't want to distribute") run_with_log(["make", "distclean"], "make-distclean", "make distclean") + notice("Normalizing permissions in GAP archive tree") + normalize_archive_permissions(".") + # Create an archive in the current directory with shutil.make_archive, and # record the filename of the new archive in . diff --git a/dev/releases/test_archive_utils.py b/dev/releases/test_archive_utils.py new file mode 100644 index 0000000000..ef05608a4a --- /dev/null +++ b/dev/releases/test_archive_utils.py @@ -0,0 +1,39 @@ +import os +import stat + +from utils import normalize_archive_permissions + + +def mode(path): + return stat.S_IMODE(os.stat(path).st_mode) + + +def test_normalize_archive_permissions_removes_group_and_other_write_bits(tmp_path): + package_dir = tmp_path / "pkg" + package_dir.mkdir() + private_dir = package_dir / "private" + private_dir.mkdir() + unreadable_dir = package_dir / "unreadable" + unreadable_dir.mkdir() + world_writable_file = package_dir / "data.g" + world_writable_file.write_text("data", encoding="utf-8") + executable_file = package_dir / "script.sh" + executable_file.write_text("#!/bin/sh\n", encoding="utf-8") + oddly_executable_file = package_dir / "odd.g" + oddly_executable_file.write_text("data", encoding="utf-8") + + os.chmod(package_dir, 0o777) + os.chmod(private_dir, 0o700) + os.chmod(unreadable_dir, 0o600) + os.chmod(world_writable_file, 0o666) + os.chmod(executable_file, 0o777) + os.chmod(oddly_executable_file, 0o654) + + normalize_archive_permissions(tmp_path) + + assert mode(package_dir) == 0o755 + assert mode(private_dir) == 0o755 + assert mode(unreadable_dir) == 0o755 + assert mode(world_writable_file) == 0o644 + assert mode(executable_file) == 0o755 + assert mode(oddly_executable_file) == 0o644 diff --git a/dev/releases/utils.py b/dev/releases/utils.py index e38c0ba72f..c14420f7c6 100644 --- a/dev/releases/utils.py +++ b/dev/releases/utils.py @@ -12,6 +12,7 @@ import os import re import shutil +import stat import subprocess import sys from typing import Iterator, NoReturn @@ -74,6 +75,29 @@ def working_directory(path: str) -> Iterator[None]: os.chdir(prev_cwd) +def normalize_archive_permissions(root: str) -> None: + """Apply the archive permission policy recursively below ``root``. + + This mirrors ``chmod -R g-w,o-w,g+r,o+r`` for regular files and also makes + directories searchable by group and others. File executable bits are + normalized from the owner's executable bit, so scripts remain executable + without making ordinary data files executable. Symlinks are left untouched. + """ + for dirpath, dirnames, filenames in os.walk(root): + for name in [dirpath, *dirnames, *filenames]: + path = os.path.join(dirpath, name) if name != dirpath else dirpath + if os.path.islink(path): + continue + mode = stat.S_IMODE(os.stat(path).st_mode) + mode |= stat.S_IRGRP | stat.S_IROTH + mode &= ~(stat.S_IWGRP | stat.S_IWOTH) + if os.path.isdir(path) or mode & stat.S_IXUSR: + mode |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH + else: + mode &= ~(stat.S_IXGRP | stat.S_IXOTH) + os.chmod(path, mode) + + # compute the sha256 checksum of a file def sha256file(path: str) -> str: h = hashlib.sha256() diff --git a/doc/ref/debug.xml b/doc/ref/debug.xml index 7121efabd7..5f5b77f9d7 100644 --- a/doc/ref/debug.xml +++ b/doc/ref/debug.xml @@ -42,9 +42,8 @@ error as in the following example occurs and a break loop is entered: gap> IsNormal(2,2); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `IsNormal' on 2 arguments -Stack trace: called from read-eval loop at *stdin*:1 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> ]]>

@@ -918,30 +917,37 @@ gap> dive(100); gap> OnBreak:= function() Where(2); end;; # shorter traceback gap> dive(6000); Error, recursion depth trap (5000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:1 [2] dive( depth - 1 ); @ *stdin*:1 ... at *stdin*:4 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; gap> dive(11000); Error, recursion depth trap (5000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:1 [2] dive( depth - 1 ); @ *stdin*:1 ... at *stdin*:5 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; Error, recursion depth trap (10000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:1 [2] dive( depth - 1 ); @ *stdin*:1 ... at *stdin*:5 -you may 'return;' -brk> return;gap> +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue +brk> return; +gap> ]]>

@@ -976,20 +982,24 @@ gap> dive(100); Depth 100 gap> dive(2500); Error, recursion depth trap (1000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:4 [2] dive( depth - 1 ); @ *stdin*:4 ... at *stdin*:12 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; Error, recursion depth trap (2000) +Stack trace: *[1] dive( depth - 1 ); @ *stdin*:4 [2] dive( depth - 1 ); @ *stdin*:4 ... at *stdin*:12 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> GetRecursionDepth(); 0 brk> return; diff --git a/doc/ref/grphomom.xml b/doc/ref/grphomom.xml index 9e4536c88a..3878ed73a0 100644 --- a/doc/ref/grphomom.xml +++ b/doc/ref/grphomom.xml @@ -372,6 +372,17 @@ are satisfied. +A technical remark:Run_In_GGMBI + +

+ +In order to avoid infinite recursions when constructing nice monomorphisms, +the global option Run_In_GGMBI is set to true in certain +situations. +The value of this option is checked in methods for the operations + and +. + <#Include Label="IsHandledByNiceMonomorphism"> <#Include Label="NiceMonomorphism"> <#Include Label="NiceObject"> diff --git a/doc/ref/helpintf.xml b/doc/ref/helpintf.xml index 6ed9b9be27..3daccf2773 100644 --- a/doc/ref/helpintf.xml +++ b/doc/ref/helpintf.xml @@ -164,7 +164,7 @@ gap> stream := InputTextFile( file );; This must return a text string or list of text lines which contains the chapter headers of the book info.bookname. -ShowSection( info ) +ShowSections( info ) This must return a text string or list of text lines which contains the section (and chapter) headers of the book info.bookname. diff --git a/doc/ref/language.xml b/doc/ref/language.xml index cab355969b..b0e03199ff 100644 --- a/doc/ref/language.xml +++ b/doc/ref/language.xml @@ -715,11 +715,9 @@ gap> xx := 15; 15 gap> MakeReadOnlyGlobal("xx"); gap> xx := 16; -Variable: 'xx' is read only -not in any function -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can 'return;' after making it writable to continue +Error, Variable: 'xx' is read only +not in any function at *stdin*:3 +you can enter 'quit;' to quit to outer loop brk> quit; gap> IsReadOnlyGlobal("xx"); true @@ -1563,11 +1561,12 @@ gap> f2:= function( x ) return f1( x ); end;; gap> f2( 4 ); value: 4 Error, Function Calls: must return a value +Stack trace: *[1] f1( x ) @ *stdin*:2 ( ) called from read-eval loop at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> ]]>

diff --git a/doc/ref/methsel.xml b/doc/ref/methsel.xml index 1ce2674710..5e88dabef2 100644 --- a/doc/ref/methsel.xml +++ b/doc/ref/methsel.xml @@ -127,13 +127,13 @@ gap> XCons(IsFullTransformationMonoid,4); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `XCons' on 2 arguments called from read-eval loop at *stdin*:8 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> XCons(IsNilpotentGroup,4); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `XCons' on 2 arguments called from read-eval loop at *stdin*:8 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> ]]> diff --git a/doc/ref/mloop.xml b/doc/ref/mloop.xml index b39f2f50e8..8b9aef83fa 100644 --- a/doc/ref/mloop.xml +++ b/doc/ref/mloop.xml @@ -478,7 +478,7 @@ indicate that you are in a break loop. gap> 1/0; Error, Rational operations: must not be zero not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop ]]>

If errors occur within a break loop &GAP; enters another break loop at a @@ -487,8 +487,8 @@ If errors occur within a break loop &GAP; enters another break loop at a 1/0; Error, Rational operations: must not be zero -not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +not in any function at *errin*:1 +you can enter 'quit;' to quit to outer loop brk_2> ]]>

@@ -537,25 +537,11 @@ purpose of this function. return return from break loop The other way to leave a break loop is to return from a break loop. -To do this you type return; or return obj;. If the break loop was entered because you interrupted &GAP;, then you can continue by typing return;. -If the break loop was entered due to an error, -you may have to modify the value of a variable before typing return; -(see the example for ) or you may have to -return an object obj -(by typing: return obj;) to continue the computation; -in any case, the message printed on entering the break loop will -tell you which of these alternatives is possible. -For example, if the break loop was entered because a variable had no -assigned value, the value to be returned is often a value that this -variable should have to continue the computation. -

- return 9; # we had tried to enter the divisor 9 but typed 0 ... -1/9 -gap> -]]> +If the break loop was entered due to an error, this option may or may not +be available, depending on the kind of error. The message printed on entering +the break loop will tell you whether this possible. @@ -581,9 +567,8 @@ function( ) ... end gap> Error("!\n"); Error, ! Hello -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; ]]>

@@ -606,8 +591,7 @@ emitted at level 1

Note that for break loops entered by a call to , -the lines after Entering break read-eval-print loop ... -and before the brk> prompt can also be customised, +the lines just before the brk> prompt can also be customised, namely by redefining .

ErrorNoTraceBack @@ -648,10 +632,10 @@ Here is a somewhat trivial demonstration of the use of

ErrorNoTraceBack("Gidday!", " How's", " it", " going?\n"); -Error, Gidday! How's it going? -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +Error, +Gidday! How's it going? +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; ]]>

@@ -661,9 +645,8 @@ Now we call with the same arguments to show the difference. gap> Error("Gidday!", " How's", " it", " going?\n"); Error, Gidday! How's it going? Hello -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; ]]>

@@ -685,17 +668,16 @@ gap> OnBreak := Where;; Break loop message When a break loop is entered by a call to -the message after the -Entering break read-eval-print loop ... line is produced -by the function OnBreakMessage, +the message at the end starting with you can enter 'quit;' to ... +is produced by the function OnBreakMessage, which just like is a user-configurable global variable that is a function with no arguments.

OnBreakMessage(); # By default, OnBreakMessage prints the following -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue ]]>

Perhaps you are familiar with what's possible in a break loop, and so @@ -718,7 +700,6 @@ calling as we did above, now produces: gap> Error("!\n"); Error, ! Hello -Entering break read-eval-print loop ... brk> quit; # to get back to outer loop ]]>

@@ -770,7 +751,8 @@ Error, user interrupt @ GAPROOT/lib/stbc.gi:18 ( ) called from read-eval loop at *stdin*:2 -you can 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> Where(2); *[1] genlabels := Filtered( genlabels, function ( x ) return pnt ^ sgs[x] = pnt; @@ -843,17 +825,18 @@ gap> test:= function( n ) > if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; gap> test( 1 ); Error, ! -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> Where(); +Stack trace: *[1] Error( "!\n" ); - @ *stdin*:4 + @ *stdin*:3 [2] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [3] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [4] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 ( ) called from read-eval loop at *errin*:1 brk> n; @@ -862,28 +845,30 @@ brk> DownEnv(); brk> n; 3 brk> Where(); +Stack trace: [1] Error( "!\n" ); - @ *stdin*:4 + @ *stdin*:3 *[2] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [3] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [4] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 ( ) called from read-eval loop at *errin*:5 brk> DownEnv( 2 ); brk> n; 1 brk> Where(); +Stack trace: [1] Error( "!\n" ); - @ *stdin*:4 + @ *stdin*:3 [2] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 [3] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 *[4] test( n + 1 ); - @ *stdin*:4 + @ *stdin*:3 ( ) called from read-eval loop at *errin*:8 brk> DownEnv( -2 ); @@ -923,8 +908,8 @@ Stack trace: @ *stdin*:7 ( ) called from read-eval loop at *stdin*:8 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> x; 1 brk> DownEnv(1); diff --git a/doc/ref/types.xml b/doc/ref/types.xml index 32ffe77b0c..b49fe1ad2f 100644 --- a/doc/ref/types.xml +++ b/doc/ref/types.xml @@ -601,12 +601,9 @@ for an object.

Setter( prop )( Rationals, false ); -You cannot set an "and-filter" except to true -not in any function -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can type 'return true;' to set all components true -(but you might really want to reset just one component) to continue +Error, You cannot set an "and-filter" except to true +not in any function at *stdin*:8 +you can enter 'quit;' to quit to outer loop brk> ]]> diff --git a/doc/tut/group.xml b/doc/tut/group.xml index 3d19ea2713..a47c55dec9 100644 --- a/doc/tut/group.xml +++ b/doc/tut/group.xml @@ -928,11 +928,12 @@ gap> Size( Image( hom, DerivedSubgroup(s4) ) ); PreImage( hom, (1,2,3) ); Error, must be an injective and surjective mapping +Stack trace: *[1] ErrorNoReturn( " must be an injective and surjective ", "mapping" ); @ GAPROOT/lib/mapping.gi:262 ( ) called from read-eval loop at *stdin*:7 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; ]]>

diff --git a/doc/tut/lists.xml b/doc/tut/lists.xml index d79908c21e..e2f8393cc6 100644 --- a/doc/tut/lists.xml +++ b/doc/tut/lists.xml @@ -341,11 +341,9 @@ gap> list[3][5] := 'w';; list; copy; [ 1, 2, "threw", [ 4 ] ] [ 1, 2, "three", [ 4 ] ] gap> copy[3][5] := 'w'; -List Assignment: must be a mutable list -not in any function -Entering break read-eval-print loop ... -you can 'quit;' to quit to outer loop, or -you can 'return;' and ignore the assignment to continue +Error, List Assignment: must be a mutable list +not in any function at *stdin*:3 +you can enter 'quit;' to quit to outer loop brk> quit; ]]>

diff --git a/doc/tut/migrat.xml b/doc/tut/migrat.xml deleted file mode 100644 index bf73228ae0..0000000000 --- a/doc/tut/migrat.xml +++ /dev/null @@ -1,1226 +0,0 @@ - - - - - - - - -Migrating to &GAP; 4 - -This chapter is intended to give users who have experience with &GAP; 3 -some information about what has changed in &GAP; 4. -

-In particular, it informs about changed command line options -(see ), -the new global variable fail (see ), -some functions that have changed their behaviour -(see ) or their names -(see ), -and some conventions used for variable names (see ). -

-Then the new concepts of &GAP; 4 are sketched, -first that of mutability or immutability (see ), -with the explanation of related changes in functions that copy objects -(see ), -then the concepts of operations and method selection, which are compared -with the use of operations records in &GAP; 3 -(see , , -and ). -

-More local changes affect the concepts of notions of generation -(see ), -of parents (see ), -of homomorphisms (see , -, -and ), -how elements in finitely presented groups are treated -(see ), -how information about progress of computations can be obtained -(see ), -and how one gets information in a break loop -(see ). -

-While a &GAP; 3 compatibility mode is provided -(see ), -its use will disable some of the new features of &GAP; 4. -Also it certainly can only try to provide partial compatibility. -

-For a detailed explanation of the new features and concepts of &GAP; 4, -see the manual Programming in GAP. - - - -

-Changed Command Line Options - -In &GAP; 4, the -l option is used to specify the root directory -(see ) -of the &GAP; distribution, -which is the directory containing the lib and doc subdirectories. -Note that in &GAP; 3 this option was used to specify the path to the -lib directory. -

-The -h option of &GAP; 3 has been removed, -the path(s) for the documentation are deduced automatically in &GAP; 4. -

-The option -g is now used to print information only about full garbage -collections. -The new option -g -g generates information about partial -garbage collections too. - -

- - - -
-Fail - -There is a new global variable -fail instead of false -

- - - -in &GAP; 4. -It is intended as a return value of a function for the case that it -could not perform its task. -For example, Inverse returns fail if it is called with a singular -matrix, and Position returns fail if the second argument is not -contained in the list given as first argument. -

-&GAP; 3 handled such situations by either signalling an error, -for example if it was asked for the inverse of a singular matrix, -or by (mis)using false as return value, as in the example Position. -Note that in the first example, in &GAP; 3 it was necessary to check -the invertibility of a matrix before one could safely ask for its -inverse, which meant that roughly the same work was done twice. - - - -

- - - -
-Changed Functionality - -Some functions that were already available in &GAP; 3 behave -differently in &GAP; 4. This section lists them. -

- - - -The &GAP; 3 manual promised that pnt would be the first entry of the -resulting orbit. This was wrong already there in a few cases, therefore -&GAP; 4 does not promise anything about the ordering of points in an orbit. - - -

- - - -only takes the element g and computes its multiplicative order. -Calling Order with two arguments is permitted only in the -&GAP; 3 compatibility mode, see . -(Note that it does not make sense anymore to specify a group as -first argument w.r.t. which the order of the second argument shall -be computed, see .) - - -

- - - -If obj is not contained in the list list then fail is returned -in &GAP; 4 (see ), whereas false was returned in &GAP; 3. - - -

- - - -In &GAP; 3, this function took either two or three arguments, -the optional argument K being a subgroup of G that stabilizes prop -in the sense that for any element g in G, -either all elements or no element in the coset g * K have the -property prop. -

-The &GAP; 4 function ElementProperty, however, -takes between two and four arguments, -and the subgroup K known from &GAP; 3 has to be entered as the fourth -argument not the third. -(The third argument in the &GAP; 4 function denotes a subgroup U -stabilizing prop in the sense that either all elements or no element -in right cosets U * g have the property prop.) -

-(This discrepancy was discovered only in March 2002, -short before the release of &GAP; 4.3.) - - -

- - - -Objects may appear on the screen in a different way, -depending on whether they are printed by the read eval print loop -or by an explicit call of Print. -The reason is that the read eval print loop calls the operation ViewObj -and not PrintObj, whereas Print calls PrintObj for each of its -arguments. -This permits the installation of methods for printing objects in a short form -in the read eval print loop while retaining Print to display -the object completely. -See also Section . -

-(PrintObj is installed as standard method ViewObj, so it is -not really necessary to have a ViewObj method for an object.) - - -

- - - -In &GAP; 3, PrintTo could be (mis)used to redirect the text -printed by a function (that is, not only the output of a function) -to a file by entering the function call as second argument. -This was used mainly in order to avoid many calls of AppendTo. -In &GAP; 4, this feature has disappeared. -One can use streams (see Chapter ) -instead in order to write files efficiently. - - - -

- - - -
-Changed Variable Names - -AgGroup -ApplyFunc -Backtrace -CharTable -Denominator -DepthVector -Elements -IsBijection -IsFunc -IsMat -IsRec -IsSet -LengthWord -NOfCyc -Numerator -RandomInvertableMat -RecFields -X - -Some functions have changed their name without changing the -functionality. -A -- probably incomplete -- list follows -

- -

-See Section  for a way to make the old names -available again. - -

- - - -
-Naming Conventions - -The way functions are named has been unified in &GAP; 4. -This might help to memorize or even guess names of library functions. -

-If a variable name consists of several words then the first -letter of each word is capitalized. -

-If the first part of the name of a function is a verb then the function -may modify its argument(s) but does not return anything, -for example Append appends the list given as second argument to the -list given as first argument. -Otherwise the function returns an object without changing the arguments, -for example Concatenation returns the concatenation of the lists -given as arguments. -

-If the name of a function contains the word By then the return value is -thought of as built in a certain way from the parts given as arguments. -For example, GroupByGenerators returns a group built from its group -generators, and creating a group as a factor group of a given group -by a normal subgroup can be done by taking the image of -NaturalHomomorphismByNormalSubgroup -(see also ). -Other examples of By functions are GroupHomomorphismByImages and -UnivariateLaurentPolynomialByCoefficients. -

-If the name of a function contains the word Of then the return value is -thought of as information deduced from the arguments. -Usually such functions are attributes -(see  in this Tutorial and ). -Examples are GeneratorsOfGroup, which returns a list of generators for -the group entered as argument, or DiagonalOfMat. -

-For the setter and tester functions of an attribute attr -(see  in this Tutorial -and ) -the names Setattr resp. Hasattr are available. -

-If the name of a function fun1 ends with NC then there is another -function fun2 with the same name except that the NC is missing. -NC stands for no check. -When fun2 is called then it checks whether its arguments are valid, -and if so then it calls fun1. -The functions SubgroupNC and Subgroup are a typical example. -

-The idea is that the possibly time consuming check of the arguments -can be omitted if one is sure that they are unnecessary. -For example, if an algorithm produces generators of the derived subgroup -of a group then it is guaranteed that they lie in the original group; -Subgroup would check this, and SubgroupNC omits the check. -

-Needless to say, all these rules are not followed slavishly, -for example there is one operation Zero instead of two operations -ZeroOfElement and ZeroOfAdditiveGroup. - -

- - - -
-Immutable Objects - -&GAP; 4 supports immutable objects. Such objects cannot be -changed, attempting to do so issues an error. Typically attribute -values are immutable, and also the results of those binary arithmetic -operations where both arguments are immutable, -see Section . -For example, [ 1 .. 100 ] + [ 1 .. 100 ] is a -mutable list and 2 * Immutable( [ 1 .. 100 ] ) is an immutable -list, both are equal to the (mutable) list [ 2, 4 .. 200 ]. -

-There is no way to make an immutable object mutable, one can only -get a mutable copy by ShallowCopy. The other way round, -MakeImmutable makes a (mutable or immutable) object and all its -subobjects immutable; one must be very careful to use MakeImmutable -only for those objects that are really newly created, for such objects -the advantage over Immutable is that no copy is made. -

-More about immutability can be found in Sections  in -this tutorial and . - -

- - - -
-Copy - -StructuralCopy -ShallowCopy -The function Copy of &GAP; 3 is not supported in &GAP; 4. This -function was used to create a copy cop of its argument obj with -the properties that cop and obj had no subobjects in common and -that if two subobjects of obj were identical then also the -corresponding subobjects of cop were identical. -

-The possibility of having immutable objects (see ) can and -should be used to avoid unnecessary copying. -Namely, given an immutable object one needs to copy it only if one wants -to get a modified object, and in such a situation usually it is -sufficient to use ShallowCopy, or at least one knows how deep one must -copy in order to do the changes one has in mind. -

-For example, suppose you have a matrix group, and you want to -construct a list of matrices by modifying the group generators. This -list of generators is immutable, so you call ShallowCopy to get a -mutable list that contains the same matrices. If you only want to -exchange some of them, or to append some other matrices, this shallow -copy is already what you need. So suppose that you are interested in -a list of matrices where some rows are also changed. For that, you -call ShallowCopy for the matrices in question, and you get matrices -whose rows can be changed. If you want to change single entries in -some rows, ShallowCopy must be called to get mutable copies of these -rows. Note that in all these situations there is no danger to change, -i.e., to destroy the original generators of the matrix group. -

-If one needs the facility of the Copy function of &GAP; 3 to get a -copy with the same structure then one can use the new &GAP; 4 -function StructuralCopy. It returns a structural copy that has no -mutable subobject in common with its argument. So if -StructuralCopy is called with an immutable object then this object -itself is returned, and if StructuralCopy is called with a mutable -list of immutable objects then a shallow copy of this list is -returned. -

-Note that ShallowCopy now is an operation. So if you create your -own type of (copyable) objects then you must define what a shallow -copy of these objects is, and install an appropriate method. - -

- - - -
-Attributes vs. Record Components - -In &GAP; 3, many complex objects were represented via records, for -example all domains. Information about these objects was stored in -components of these records. For the user, this was usually not -relevant, since there were functions for computing information about -the objects in question. For example, if one was interested in the -size of a group then one could call Size. -

-But since it was guaranteed that the size of a domain D was stored -as value of the component size, it was allowed to access D.size -if this component was bound, and a check for this was possible via -IsBound( D.size ). -

-In &GAP; 4, only the access via functions is admissible. One reason -is the following basic rule. -

-From the information that a given &GAP; 4 object is for example a -domain, one cannot conclude that this object has a certain -representation. -

-For attributes like Size, &GAP; 4 provides two related functions, -the setter and the tester of the attribute, which can be used to -set an attribute value and to check whether the value of an attribute -is already stored for an object (see also ). For example, if D is a domain in &GAP; 4 then -HasSize( D ) is true if the size of D is already stored, and -false otherwise. In the latter case, if you know that the size of -D is size then you may store it by SetSize( D, size ). -

-Besides the flexibility in the internal representation of objects, -storing information only via function calls has also the advantage -that &GAP; 4 is able to draw conclusions automatically. For example, -as soon as it is stored that a group is nilpotent, it is also stored -that it is solvable, see Chapters  and  -for the details. -

-As a consequence, you cannot put your favourite information into a -domain D by assigning it to a new component like -D.myPrivateInfo. Instead you can introduce a new attribute and -then use its setter, see . - -

- - - -
-Different Notions of Generation - -As in &GAP; 3, a domain in &GAP; 4 is a structured set. -

-The same set can have different structures, for example a field can be -regarded as a ring or as an algebra or vector space over a subfield. -

-In &GAP; 3, however, an object representing a ring did not represent -a field, and an object representing a field did not represent a ring. -One reason for this was that the record component generators was -used to denote the appropriate generators of the domain. For a ring -R, the component R.generators was a list of ring generators, and -for a field F, F.generators was a list of field generators. -

-&GAP; 4 cleans this up, see . It supports -many different notions of generation, for example one can ask for -magma generators of a group or for generators of a field as an additive -group. A subtle but important distinction is that between generators -of an algebra and of an algebra-with-one. -

-So the attributes GeneratorsOfGroup, GeneratorsOfMagma, -GeneratorsOfRing, GeneratorsOfField, GeneratorsOfVectorSpace, -and so on, replace the access to the generators component. - -

- - - -
-Operations Records - -Already in &GAP; 3 there were several functions that were applicable -to many different kinds of objects, for example Size could be -applied to any domain, and the binary infix multiplication * could -be used to multiply two matrices, an integer with a row vector, or a -permutation with a permutation group. This was implemented as -follows. Functions like Size and * tried to find out what -situation was described by its arguments, and then it called a more -specific function to compute the desired information. These more -specific functions, let us call them methods as they are also called -in &GAP; 4, were stored in so-called operations records of the -arguments. -

-For example, every domain in &GAP; 3 was represented as a record, and -the operations record was stored in the record component operations. -If Size was called for the domain then the method to compute the -size of the domain was found as value of the Size component of the -operations record. -

-This was fine for functions taking only one argument, and in principle -it is possible that for those functions an object stored an optimal -method in its operations record. But in the case of more arguments -this is not possible. In a multiplication of two objects in &GAP; 3, -one had to choose between the methods stored in the operations records -of the arguments, and if for example the method stored for the left -operand was called, this method had to handle all possible right -operands. -

-So operations records turned out to be not flexible enough. -In &GAP; 4, operations records are not supported -(see  for a possibility -to use your &GAP; 3 code that utilizes operations records, -at least to some extent). -A detailed description -of the new mechanism to select methods can be found in -Chapter . -

-An important point is that the new mechanism allows &GAP; to take the -relation between arguments into account. So it is possible (and -recommended) to install different methods for different relations -between the arguments. Note that such methods need not do the -extensive argument checking that was necessary in &GAP; 3, because -most of the checks are done already by the method selection mechanism. - -

- - - -
-Operations vs. Dispatcher Functions - -&GAP; 3 functions like Size, CommutatorSubgroup, or -SylowSubgroup did mainly call an appropriate method -(see ) -after they had checked their arguments. -Such functions were -called dispatchers in &GAP; 3. In &GAP; 4, many dispatchers have -been replaced by operations, due to the fact that methods are no -longer stored in operations records (see  for the details). -

-Most dispatchers taking only one argument were treated in a special -way in &GAP; 3, they had the additional task of storing computed -values and using these values in subsequent calls. For example, the -dispatcher Size first checked whether the size of the argument was -already stored, and if so then this value was returned; otherwise a -method was called, the value returned by this method was stored in the -argument, and then returned by Size. -

-In &GAP; 4, computed values of operations that take one argument -(these operations are called attributes) are also stored, only the -mechanism to achieve this has changed, see  -and . -

-So the behaviour of Size is the same in &GAP; 3 and &GAP; 4. But -note that in &GAP; 4, it is not possible to access D.size, -see . -As described in , -&GAP; 4 does not admit bypassing the dispatcher by -calling for example D.operations.Size. This was done in &GAP; 3 -often for efficiency reasons, but the method selection mechanism of -&GAP; 4 is fast enough to make this unnecessary. -

-If you had written your own dispatchers and put your own methods into -existing operations records then this code will not work in &GAP; 4. -See  -and  -for a description of how to define operations -and to install methods. -

-Finally, some functions in &GAP; 3 were hidden in -operations records, e.g., PermGroupOps.MovedPoints. -These functions became proper operations in &GAP; 4. - -

- - - -
-Parents and Subgroups - -In &GAP; 3 there was a strict distinction between parent groups and -subgroups. -The use of the name parent (instead of supergroup) -was chosen to indicate that the parent of an object was more than just -useful information. -In fact the main reason for the introduction of parents was to provide -a common roof for example for all groups of polycyclic words that -belonged to the same PC-presentation, or for all subgroups of a finitely -presented group (see ). -A subgroup was never a parent group, and it was possible to create -subgroups only of parent groups. -

-In &GAP; 4 this common roof is provided already by the concept of -families, see . -Thus it is no longer compulsory to use parent groups at all. -On the other hand, parents may be used in &GAP; 4 to provide -information about an object, for example the normalizer of a group in its -parent group may be stored as an attribute value. -Note that there is no restriction on the supergroup that is set to be -the parent, -it is possible to create a subgroup of -any group, this group then being the parent of the new subgroup. -This permits for example chains of subgroups with respective parents, -of arbitrary length. -

-As a consequence, the Parent command cannot be used in &GAP; 4 to -test whether the two arguments of CommutatorSubgroup fit together, -this is now a question that concerns the relation between the families -of the groups. So the 2-argument version of Parent and the now -meaningless function IsParent have been abolished. - -

- - - -
-Homomorphisms vs. General Mappings - -In &GAP; 3 there had been a confusion between group homomorphisms and -general mappings, as GroupHomomorphismByImages created only a -general mapping that did not store whether it was a mapping. This -caused expensive, unwanted, and unnecessary tests whether the mapping -was in fact a group homomorphism. Moreover, the official -workaround to set some components of the mapping record was quite -unwieldy. -

-In &GAP; 4, GroupHomomorphismByImages checks whether the desired -mapping is indeed a group homomorphism; if so then this property is -stored in the returned mapping, otherwise fail is returned. If you -want to avoid the checks then you can use -GroupHomomorphismByImagesNC. If you want to check whether a general -mapping that respects the group operations is really a group -homomorphism, you can construct it via GroupGeneralMappingByImages -and then call IsGroupHomomorphism for it. (Note that -IsGroupHomomorphism returns true if and only if both -IsGroupGeneralMapping and IsMapping do, so one does in fact check -IsMapping in this case.) -

-There is no function IsHomomorphism in &GAP; 4, -since there are several different operations with respect to which a -mapping can be a homomorphism. - -

- - - -
-Homomorphisms vs. Factor Structures - -If F is a factor structure of G, with kernel N, complete -information about the connection between F and G is provided by -the natural homomorphism. -

-In &GAP; 3, the official way to construct this natural homomorphism -was to create first the factor structure F, and then to call -NaturalHomomorphism with the arguments G and F. -For that, the data necessary to compute the homomorphism was stored in -F when F was constructed. -

-In &GAP; 4, factor structures are not treated in a special way, -in particular they do not store information about a homomorphism. -Instead, the more natural way is taken to construct the natural -homomorphism from G and N by NaturalHomomorphismByNormalSubgroup -if N is a normal subgroup of the group G, -or by NaturalHomomorphismByIdeal if N is an ideal in the ring G. -The factor F can then be accessed as the image of this homomorphism, -and of course G is the preimage and N is the kernel. -

-Note that &GAP; 4 does not guarantee anything about the representation -of the factor F, it may be a permutation group or a polycyclically -presented group or another kind of group. -Also note that a natural homomorphism need not be surjective. -

-A consequence of this change is that &GAP; 4 does not allow you to -construct a natural homomorphism from the groups G and F. -

-The other common type of homomorphism in &GAP; 3, operation -homomorphisms, have been replaced (just a name change) by action -homomorphisms, which are handled in a similar fashion. That is, an -action homomorphism is constructed from an acting group, an action -domain, and a function describing the operation. The permutation -group arising by the induced action is then the image of this -operation homomorphism. -

-The &GAP; 3 function Operation is still supported, under the name Action, -but from the original group and the result of Action it is not -possible to construct the action homomorphism. - -

- - - -
-Isomorphisms vs. Isomorphic Structures - -In &GAP; 3, a different representation of a group could be obtained by -calling AgGroup to get an isomorphic polycyclically presented group, -PermGroup to get an isomorphic permutation group, and so on. -The returned objects stored an isomorphism in the record component -bijection. -

-For the same reason as in , -&GAP; 4 puts emphasis on the isomorphism, -and the isomorphic object in the desired representation can be accessed -as its image. -So you can call IsomorphismPcGroup or IsomorphismPermGroup in order -to get an isomorphism to a polycyclically presented group or a -permutation group, respectively, and then call Image to get the -isomorphic group. -

-Note that the image of an action homomorphism with trivial kernel is -also an isomorphic permutation group, but an action homomorphism need -not be surjective, since it may be easier to define it into the full -symmetric group. -

-Further note that in &GAP; 3, a usual application of isomorphisms to -polycyclically presented groups was to utilize the usually more -effective algorithms for solvable groups. However, the new concept of -polycyclic generating systems in &GAP; 4 makes it possible to apply -these algorithms to arbitrary solvable groups, independent of the -representation. For example, &GAP; 4 can handle polycyclic -generating systems of solvable permutation groups. So in many cases, -a change of the representation for efficiency reasons may be not -necessary any longer. -

-In general IsomorphismFpGroup will define a presentation on generators -chosen by the algorithm. The corresponding elements of the original -group can be obtained by the command -

-PreImagesRepresentative(isofp,i)); -]]> -

-If a presentation in the given generators is needed, the command -IsomorphismFpGroupByGenerators(G, gens) will produce one. - -

- - - -
-Elements of Finitely Presented Groups - -Strictly speaking, &GAP; 3 did not support elements of finitely -presented groups. Instead, the words in abstract generators of -the underlying free groups were (mis)used. This caused problems -whenever calculations with elements were involved, the most obvious -ones being wrong results of element comparisons. Also functions -that should in principle work for any group were not applicable to -finitely presented groups. In effect, a finitely presented group had -to be treated in a special way in &GAP; 3. -

-&GAP; 4 distinguishes free groups and their elements from finitely -presented groups and their elements. Comparing two elements of a -finitely presented group will yield either the correct result or no -result at all. -

-Note that in &GAP; 4, the arithmetic and comparison operations for -group elements do not depend on a context provided by a group that -contains the elements. In particular, in &GAP; 4 it is not -meaningful to call Order( G, g ) for a group G and an element -g. - -

- - - -
-Polynomials - -In &GAP; 3, polynomials were defined over a field. So a polynomial over -GF(3) was different from a polynomial over GF(9), even if the -coefficients were exactly the same. -

-&GAP; 4 defines polynomials only over a characteristic. This makes it -possible for example to multiply a polynomial over GF(3) with a polynomial -over GF(9) without the need to convert the former to the larger field. -

-However it has an effect on the result of DefaultRing for polynomials: -In &GAP; 3 the default ring for a polynomial was the polynomial ring of the -field over which the polynomial was defined. In &GAP; 4 no field is -associated, so (to avoid having to define the algebraic closure as the only -other sensible alternative) the default ring of a polynomial is the -DefaultRing of its coefficients. -

-This has an effect on Factors: If no ring is given, a polynomial is -factorized over its DefaultRing and so Factors(poly) -might return different results. -

-To be safe from this problem, if you are not working over prime fields, -rather call Factors(pring,poly) with the appropriate polynomial ring -and change your code accordingly. - -

- - - -
-The Info Mechanism - -Sometimes it is useful to get information about the progress of a -calculation. -Many &GAP; functions contain statements to display such information -under certain conditions. -

-In &GAP; 3, these statements were calls to functions such as -InfoGroup1 or InfoGroup2, and if the user assigned Print to -these variables then this had the effect to switch on the printing of -information. -InfoGroup2 was used for more detailed information than InfoGroup1. -One could switch off the printing again by assigning Ignore to the -variables, and Ignore was also the default value. -

-&GAP; 4 uses one function Info for the same purpose, -which is a function that takes as first argument an info class such as -InfoGroup, as second argument an info level, and the print statements -as remaining arguments. -The level of an info class class is set to level by calling -SetInfoLevel( class, level ). -An Info statement is printed only if its second argument is smaller than -or equal to the current info level. -

- test:= function( obj ) -> Info( InfoGroup, 2, "This is useful, isn't it?" ); -> return obj; -> end;; -gap> test( 1 ); -1 -gap> SetInfoLevel( InfoGroup, 2 ); -gap> test( 1 ); -#I This is useful, isn't it? -1 -]]> -

-As in &GAP; 3, if an info statement is ignored then its arguments are -not evaluated. - -

- - - -
-Debugging - -Backtrace -DownEnv -Where -If &GAP; 4 runs into an error or is interrupted, -it enters a break loop. -The command Where( number ), which replaces Backtrace of &GAP; 3, -can be used to display number lines of information about the current -function call stack. -

-As in &GAP; 3, access is only possible to the variables of the current -level in the function stack, -but in &GAP; 4 the function DownEnv, with a positive or negative -integer as argument, permits one to step down or up in the -stack. -

-When interrupting, the first line printed by Where actually may be -one level higher, as shown below. -

- OnBreak := function() Where(0); end;; # eliminate back-tracing on -gap> # entry to break loop -gap> test:= function( n ) -> if n > 3 then Error( "!\n" ); fi; test( n+1 ); end;; -gap> test( 1 ); -Error, ! -at *stdin*:6 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue -brk> Where(); -*[1] Error( "!\n" ); - @ *stdin*:4 - [2] test( n + 1 ); - @ *stdin*:4 - [3] test( n + 1 ); - @ *stdin*:4 - [4] test( n + 1 ); - @ *stdin*:4 -( ) - called from read-eval loop at *errin*:1 -brk> n; -4 -brk> DownEnv(); -brk> n; -3 -brk> Where(); - [1] Error( "!\n" ); - @ *stdin*:4 -*[2] test( n + 1 ); - @ *stdin*:4 - [3] test( n + 1 ); - @ *stdin*:4 - [4] test( n + 1 ); - @ *stdin*:4 -( ) - called from read-eval loop at *errin*:5 -brk> DownEnv( 2 ); -brk> n; -1 -brk> Where(); - [1] Error( "!\n" ); - @ *stdin*:4 - [2] test( n + 1 ); - @ *stdin*:4 - [3] test( n + 1 ); - @ *stdin*:4 -*[4] test( n + 1 ); - @ *stdin*:4 -( ) - called from read-eval loop at *errin*:8 -brk> DownEnv( -2 ); -brk> n; -3 -brk> quit; -gap> OnBreak := Where;; # restore OnBreak to its default value -]]> -

-For purposes of debugging, it can be helpful sometimes, to see what -information is stored within an object. In &GAP; 3 this was possible using -RecFields because the objects in question were represented via records. -For component objects, &GAP; 4 permits the same by -NamesOfComponents( object ), which will list all components present. - -

- - - -
-Compatibility Mode - -For users who want to use &GAP; 3 code with as little changes as -possible, a compatibility mode is provided by &GAP; 4. -This mode must be turned on explicitly by the user. -

-It should be noted that this compatibility mode has not been tested -thoroughly. -

-The compatibility mode can be turned on by loading some of the following -files with ReadLib. -The different files address different aspects of compatibility. -

- -compat3a.g - - makes some &GAP; 3 function names available that were changed - in &GAP; 4, - and provides code for some &GAP; 3 features that were - deliberately left out from the &GAP; 4 library. - For example, - almost all variable names concerning character theory that are - mentioned in the &GAP; 3 manual, - such as CharTable and SubgroupFusions, - are available after compat3a.g has been read; - the only exceptions are names of operations records. - -compat3b.g - - implements the availability of components of domains; - besides components that have no meaning for the rest of the &GAP; 4 - library, such as D.myInfo, there are components associated to - attributes; for example D.size is redirected to the call of the - attribute Size, IsBound( D.size ) to the call of its tester, - and D.size:= val to the call of its setter. - (An important special case is the component operations, see below.) - -compat3c.g - - permits you to implement your own elements represented as records, - and using operations records to provide a Print method and - the basic arithmetic operations. - When using operations records, it is probably a good idea to - use immutable operations records; for example, if the results - of arithmetic operations are records with operations records then - this avoids to create shallow copies of the operations records - in the call to Immutable for the results. - - -

-The following features are accessible only via starting &GAP; with -the command line option -O and may damage some features of &GAP; 4 -permanently for the current session. -

- With this option, also the files listed above are read automatically. -

- -compat3d.g - - provides some &GAP; 3 functions like Domain, simulates the - &GAP; 3 behaviour of IsString (to convert a list to string - representation if possible), and replaces fail by false; - these changes destroy parts of the functionality of &GAP; 4. - - -

-Some words concerning the simulation of operations records may be -necessary. -

-The operations records of the &GAP; 3 library, such as DomainOps -and GroupOps, are available only for access to their components, -whose values are &GAP; 4 operations; for example, the value of both -DomainOps.Size and GroupOps.Size is the operation Size. So it -is not safely possible to delegate from a Size method in another -operations record to DomainOps.Size. Also it is not possible to -change these predefined operations records. -

-If one wants to install individual methods for a given object obj -via the mechanism of operations records then one can construct a new -operations record with OperationsRecord, assign the desired methods -to components of this record, and then assign the operations record to -obj.operations. Whenever an operation that is associated with a -component nam of the operations record is called with obj as first -argument, the value of nam is chosen as the method. -

-In the case of the binary operations =, <, +, -, *, /, -Comm, and LeftQuotient, -this also happens if obj is the right-hand argument. -As in &GAP; 3, if both arguments of one of the above binary operations -have operations records containing a function for this operation, -then the function in the operations record of the right-hand argument -is chosen. -

-We give a small example how the compatibility mode works. -

-Suppose we want to deal with new objects that are derived from known -field elements by distorting their multiplication. Namely, let a' -and b' be the new objects corresponding to the field elements a, -b, and define a' * b' = a b - a - b + 2. -

-In &GAP; 3, this problem was solved by representing each new object -by a record that stored the corresponding old object and an -operations record, where the latter was a record containing the -functions applicable to the new object. After the library file -compat3c.g has been read, we can use this construction of the -operations record and of the new objects. Note that operations -records must be created with the function OperationsRecord (this was -also the norm in &GAP; 3), starting with an empty record would not work. -For our intended application, we thus start with the following two -lines of code. -

- ReadLib( "compat3c.g" ); -gap> MyOps:= OperationsRecord( "MyOps" );; -HasMyOps := NewFilter( "HasMyOps" ); -]]> -

-In order to make the translation from &GAP; 3 code to &GAP; 4 -easier, &GAP; prints the definition of filters associated with -operations records and the method installations for operations -corresponding to components of the operations records. The output -line printed by &GAP; after the call of OperationsRecord is one -such case. -

-Now we add our multiplication function to the operations record, -and again &GAP; 4 prints a translation to &GAP; 4 code. -

- MyOps.\* := function( a, b ) -> return rec( x:= a.x * b.x - a.x - b.x + 2, -> operations := MyOps ); -> end;; -# If the following method installation matches the requirements -# of the operation `PROD' then `InstallMethod' should be used. -# It might be useful to replace the rank `SUM_FLAGS' by `0'. -InstallOtherMethod( PROD, - "for object with `MyOps' as first argument", - true, - [ HasMyOps, IsObject ], SUM_FLAGS, - MyOps.\* ); - -# For binary infix operators, a second method is installed -# for the case that the object with `MyOps' is the right operand; -# since this case has higher priority in GAP 3, the method is -# installed with higher rank `SUM_FLAGS + 1'. -InstallOtherMethod( PROD, - "for object with `MyOps' as second argument", - true, - [ IsObject, HasMyOps ], SUM_FLAGS + 1, - MyOps.\* ); -]]> -

-Let us look how this installation works. -

- a:= rec( x:= 3, operations:= MyOps ); -rec( x := 3, operations := MyOps ) -gap> b:= rec( x:= 5, operations:= MyOps ); -rec( x := 5, operations := MyOps ) -gap> a * b; -rec( x := 9, operations := MyOps ) -]]> -

-(In more complicated cases, we might run into problems, but this was -already the case in &GAP; 3. For example, suppose we want to support -the multiplication of two operands having different operations -records; then it is not clear which of the two multiplication -functions is to be chosen, and in &GAP; 3, the only way out was to -change the multiplication functions, in order to make them aware of -such situations.) -

-If we are now interested to translate the code to &GAP; 4 in the -sense that no compatibility mode is needed, we can use what &GAP; 4 -has printed above. (The same example is dealt with in -Chapter .) -

-The objects will no longer be records with operations component. -Instead of records we may use so-called component objects -with record-like access to components, -and instead of the operations component, we give the objects a -type that has the filter HasMyOps set. -

- -

-(More about families and representations in this context can be found -in the chapter of Programming in &GAP; mentioned above.) -

-The next step is to write a function that creates a new object. -It may look as follows. -

- -

-The multiplication function shall return an object with the -filter HasMyOp, so we change it as follows. -

- MyMult := function( a, b ) -> return MyObject( x:= a!.x * b!.x - a!.x - b!.x + 2 ); -> end;; -]]> -

-Note that the component access for these objects -works via !. instead of .; -further note that no operations record needs to appear here, -the filter takes its role. -

-Finally, we install the multiplication for at least one argument -with the new filter, as had been printed by &GAP; 4 in the -session shown above. -

- -

-And now it works (again). -

- a:= MyObject( 3 ); - -gap> b:= MyObject( 5 ); - -gap> a * b; - -gap> last!.x -9 -]]> -

-We may install a method to print our objects in a nice way; -we could have done this for the operations record MyOps -in the compatibility mode, -the printed output would look similar to the following. -

- -

-Now output looks as follows. -

- a; b; a * b; -MyObject( 3 ) -MyObject( 5 ) -MyObject( 9 ) -]]> -

-Maybe now we want to improve the installation. -The multiplication function we want to use is apparently -thought only for the case that both operands have -the filter HasMyOps (and a component x). -So it is reasonable to replace the two methods for -the multiplication by one method for which both arguments -are required to have the filter. -

- -

-At first sight, the &GAP; 4 approach seems to be much more -complicated. -But the last example shows that in &GAP; 4, -each method can be installed more specifically for the appropriate -situation. -Moreover, it is for example possible to install a method -for the multiplication of an integer and a HasMyOps object; -note that --contrary to the situation in &GAP; 3-- -such a method is independent from already existing methods -in the sense that these need not be changed when -new functionality is added. -

-Another example that uses this part of the compatibility mode can be -found in the file tst/compat3.tst of the &GAP; 4 distribution. - - - - - - - - diff --git a/doc/tut/opers.xml b/doc/tut/opers.xml index 6413348e73..313bdc7faf 100644 --- a/doc/tut/opers.xml +++ b/doc/tut/opers.xml @@ -218,7 +218,7 @@ stops with an error message of the form Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `Size' on 1 arguments called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop ]]>

You would get an error message as above if you asked for Size( 1 ). diff --git a/doc/versiondata b/doc/versiondata index 98c2758afa..a2eec48b00 100644 --- a/doc/versiondata +++ b/doc/versiondata @@ -4,7 +4,7 @@ Instead edit either the template file `doc/versiondata.in`, or edit `Makefile.rules` (which has code for generating this file), or edit `configure.ac` (where the value being substituted come from) --> - + - + diff --git a/etc/emscripten/Dockerfile b/etc/emscripten/Dockerfile new file mode 100644 index 0000000000..9025dbaaa3 --- /dev/null +++ b/etc/emscripten/Dockerfile @@ -0,0 +1,50 @@ +# Build environment for compiling GAP to WebAssembly via Emscripten. +# +# Pinned to emsdk 3.1.23 for reproducibility. Both pieces of the in-browser +# REPL are sensitive to the exact toolchain version: +# +# - GASMAN, GAP's conservative garbage collector, scans the stack including +# pointers held in wasm registers, reached via emscripten_scan_registers() +# (see src/gasman.c). That path is now compiled correctly regardless of +# version, so the GC itself is no longer the constraint. +# +# - The terminal uses xterm-pty, whose emscriptenHack() monkey-patches +# emscripten's internal TTY device so GAP's tcsetattr() (turning off echo +# and canonical mode) reaches the line discipline. That patch is tied to +# emscripten's TTY internals: on 3.1.47 the ioctl no longer reaches +# xterm-pty, echo stays on, and every typed line is echoed twice. +# +# 3.1.23 is the version where the pinned xterm-pty (0.9.4) works. Bump both +# together and re-test the REPL -- including that typed input is not +# double-echoed -- before changing this. + +FROM emscripten/emsdk:3.1.23 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + autoconf \ + automake \ + libtool \ + make \ + python3 \ + ca-certificates \ + curl \ + bison \ + byacc \ + m4 \ + && rm -rf /var/lib/apt/lists/* + +# Allow running as a non-root host UID without breaking the emscripten cache. +RUN mkdir -p /emsdk/upstream/emscripten/cache \ + && chmod -R 0777 /emsdk/upstream/emscripten/cache + +# Cache the GAP package distribution tarball so container runs don't +# re-download it from GitHub each time. The URL pins to the "latest" +# release on the PackageDistro side, so this snapshot drifts as upstream +# tags new releases — rebuild the image (--no-cache) to refresh. +ARG GAP_PACKAGES_URL=https://github.com/gap-system/PackageDistro/releases/download/latest/packages.tar.gz +RUN curl --fail --location --silent --show-error \ + --output /opt/gap-packages.tar.gz \ + "$GAP_PACKAGES_URL" \ + && chmod 0644 /opt/gap-packages.tar.gz + +WORKDIR /gap diff --git a/etc/emscripten/README.md b/etc/emscripten/README.md index 5946302efe..083de668b6 100644 --- a/etc/emscripten/README.md +++ b/etc/emscripten/README.md @@ -1,26 +1,127 @@ -Code to allow building gap to WASM using Emscripten. +# GAP in the browser -Files: +Build GAP as a WebAssembly module and serve it as a self-contained website. +The terminal interface uses [xterm-pty](https://github.com/mame/xterm-pty), +so the resulting page behaves like a normal GAP REPL. -- `build.sh`: Run as `etc/emscripten/build.sh` from a fresh copy of GAP. +## Quick start -- `web-template`: Uses 'xterm-pty' to create a "nice" interface to the Wasm GAP. +From a fresh GAP checkout, with either Docker or Podman installed: -- `build_startup_manifest.js`: Run it in the web root directory to build `startup_manifest.json` that contains resources to preload. +```sh +etc/emscripten/build-in-docker.sh +cd web-example +../etc/emscripten/serve.py +``` + +Then open . The first build takes 10–30 minutes; the +docker image, the GAP package distribution, and the GMP/zlib builds are all +cached for subsequent runs. + +To pick up newer GAP packages from upstream, force a fresh image build: + +```sh +docker build --no-cache -t gap-emscripten-build:3.1.23 etc/emscripten/ +``` + +On Apple Silicon (and other non-amd64 hosts), the build runs `linux/amd64` +under emulation, since `emscripten/emsdk:3.1.23` is amd64-only on Docker +Hub. `build-in-docker.sh` pins the platform explicitly so the layer cache +holds across runs; set `BUILD_PLATFORM` to override. + +The output directory `web-example/` is fully self-contained — copy it to any +static host (see "Hosting" below for the headers it needs). + +## Building without Docker + +If you already have emsdk 3.1.23 sourced in your shell, you can run the +underlying build directly: + +```sh +etc/emscripten/build.sh +etc/emscripten/assemble-website.sh +``` + +emsdk 3.1.23 is the version we test against, paired with xterm-pty 0.9.4. +GAP relies on ASYNCIFY together with GASMAN's conservative GC, which scans +wasm registers via `emscripten_scan_registers()` (see `src/gasman.c`); and +the terminal relies on xterm-pty's `emscriptenHack()` patching emscripten's +TTY device so `tcsetattr()` reaches the line discipline. Both are sensitive +to the toolchain version (a newer emsdk leaves `tcsetattr` unhonoured, so +typed input is echoed twice), so re-test the REPL when changing emsdk. -See 'run-web-demo.sh' as an example on how to set up a working website. +## Hosting -Note that this demo uses xterm-pty, a library which provides a terminal interface -for emscripten-compiled programs. This uses a javascript feature called -"SharedArrayBuffer", which requires some headers are returned by the server: +The xterm-pty terminal uses `SharedArrayBuffer`, which browsers only allow +when the page is served with these two headers: ``` Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp ``` -For more details, see for [this article](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer). +`serve.py` is a 20-line stdlib-only Python server that adds them. For +GitHub Pages and other static hosts that don't let you set headers, +`web-template/coi-serviceworker.js` is included as a workaround (it +re-fetches resources through a service worker that adds the headers). + +## Files + +| File | Role | +| ---- | ---- | +| `build-in-docker.sh` | One-stop entry point. Builds the image, runs `build.sh` inside, then `assemble-website.sh`. | +| `Dockerfile` | Pinned `emscripten/emsdk:3.1.23` with autotools, python3, bison/byacc/m4, and a baked-in copy of the GAP package distribution tarball at `/opt/gap-packages.tar.gz`. | +| `build.sh` | Configures and builds GMP, zlib, and GAP itself for wasm. | +| `assemble-website.sh` | Copies the build outputs and data directories (`pkg`, `lib`, `grp`, …) into `web-example/`. | +| `generate_gap_fs_json.py` | Reads file paths on stdin, writes `gap-fs.json` (the manifest of every file in the virtual FS). | +| `startup_manifest.json` | List of files to fetch eagerly at startup, captured from a real GAP run. Anything not in this list is fetched lazily on first read. See "Updating the startup manifest" below for how to refresh it. | +| `serve.py` | Local server that adds the COOP/COEP headers. | +| `web-template/` | Static UI: `index.html`, the worker scripts, the FS init shim, and the COOP/COEP service worker for hosts where you can't set headers. | + +## Updating the startup manifest + +`startup_manifest.json` lists files (relative to the GAP root) that the FS +init shim downloads up front instead of lazily. The current list was +captured from a real GAP run reaching its prompt, so it includes both +the core library bootstrap (`lib/init.g`, `lib/read*.g`, …) and any +default-loaded packages. Entries that no longer exist in the build are +silently ignored, so it is safe to leave stale entries in place; it is +also safe to leave the list empty (every file becomes lazy). + +The manifest is a startup-time optimisation, not a correctness mechanism: +a wrong list never breaks the build, it only makes startup slower (files +GAP needs but the manifest omits get fetched lazily, one round-trip each) +or wastes bandwidth (files in the manifest that GAP doesn't actually +read are downloaded anyway). So it's worth refreshing when something +changes the set of files read at startup — most importantly when the +default loaded packages change, but also after large library reshuffles. + +To regenerate it after such changes: + +1. Build the website (`build-in-docker.sh`) and serve it (`serve.py`). +2. **Empty the served manifest before capturing.** Replace + `web-example/startup_manifest.json` with `[]` (or delete it). + Otherwise the existing entries are eagerly pre-fetched at startup, + appear in `fetchedUrls`, and you'll just round-trip the old list. + Editing the served file is enough — no rebuild is needed. +3. Open the page and wait for the GAP prompt to appear. Every file that + GAP actually reads now goes through the lazy `XHR` path and gets + captured. +4. Open devtools and read the captured URLs from the page's JS console: + `window.fetchedUrls` is an array of every unique URL the worker + requested. Chrome/Firefox provide a `copy()` console helper: + `copy(JSON.stringify(fetchedUrls))` puts the JSON on your clipboard. +5. Strip non-GAP-FS entries (`gap.js`, `gap.wasm`, `gap-fs.json`, the + xterm CDN URLs) and write the result to + `etc/emscripten/startup_manifest.json` (so it's checked in and gets + picked up by the next `assemble-website.sh`). A `jq` filter that + keeps just GAP filesystem paths: + + ```sh + jq '[.[] | select(test("^(pkg|lib|grp|tst|doc|hpcgap|dev|benchmark)/"))]' \ + fetched-urls.json > etc/emscripten/startup_manifest.json + ``` -The file "coi-serviceworker.js" works around this problem on Github pages. This won't -work locally, so "server.rb" is a simple ruby script, which just starts a web-server -which returns the required headers. \ No newline at end of file +The bookkeeping lives in `web-template/gap-fs.js` (wraps `fetch` and +`XMLHttpRequest.open` to report URLs to the main thread) and +`web-template/index.html` (accumulates them onto `window.fetchedUrls`). diff --git a/etc/emscripten/assemble-website.sh b/etc/emscripten/assemble-website.sh new file mode 100755 index 0000000000..12e6f6a83b --- /dev/null +++ b/etc/emscripten/assemble-website.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# +# Assemble a self-contained website from a completed wasm build. +# Outputs ./web-example/ relative to the GAP source root. +# +# Run after etc/emscripten/build.sh (or have build-in-docker.sh call it). + +set -euo pipefail + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +ROOT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd) +OUT_DIR="$ROOT_DIR/web-example" + +cd "$ROOT_DIR" + +for f in gap.js gap.wasm gap-fs.json; do + if [[ ! -f $f ]]; then + echo "Error: missing build output '$f'. Run etc/emscripten/build.sh first." >&2 + exit 1 + fi +done + +# Always start from a clean output directory. Merging into a previous +# web-example/ confuses cp when a tree has changed shape between runs +# (e.g. pkg/X switching between a symlink and a real directory). +rm -rf "$OUT_DIR" +mkdir -p "$OUT_DIR" + +cp "$SCRIPT_DIR"/web-template/* "$OUT_DIR"/ +cp "$SCRIPT_DIR"/startup_manifest.json "$OUT_DIR"/ +cp gap.js gap.wasm gap-fs.json "$OUT_DIR"/ +# Emscripten only emits a separate gap.worker.js for pthread builds; this +# single-threaded ASYNCIFY build doesn't use one (newer emscripten inlines +# the worker regardless). Copy it only if it was produced. +if [[ -f gap.worker.js ]]; then + cp gap.worker.js "$OUT_DIR"/ +fi +cp LICENSE COPYRIGHT "$OUT_DIR"/ + +# Data directories. These are referenced by gap-fs.json and either eagerly +# loaded (if listed in startup_manifest.json) or lazily fetched on first +# read by Emscripten's createLazyFile. +# +# -L dereferences symlinks so the output tree is self-contained (a setup +# where pkg/X is a symlink into a separate checkout still works). Some +# packages ship dangling symlinks as build artefacts (e.g. pkg/vole's +# rust/target/*.dSYM); cp prints those and exits non-zero but still copies +# everything else, so we don't let that abort the run. The assertion below +# catches a genuinely incomplete copy. +for d in pkg lib grp tst doc hpcgap dev benchmark; do + cp -RL "$d" "$OUT_DIR"/ 2>/dev/null || true +done + +# pkg/log holds package test logs (.log/.err/.out) that are never read at +# runtime; keep them out of the shipped site. +rm -rf "$OUT_DIR/pkg/log" + +# The library bootstrap must be present, or GAP 404s during startup. +if [[ ! -f "$OUT_DIR/lib/init.g" ]]; then + echo "Error: lib/init.g missing from $OUT_DIR after copy." >&2 + exit 1 +fi + +echo "Assembled website at $OUT_DIR" diff --git a/etc/emscripten/build-in-docker.sh b/etc/emscripten/build-in-docker.sh new file mode 100755 index 0000000000..ac7a7aa604 --- /dev/null +++ b/etc/emscripten/build-in-docker.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# +# One-stop shop: build GAP for the web inside a pinned container. +# +# Usage (run from the GAP source tree): +# etc/emscripten/build-in-docker.sh +# +# Output: ./web-example/ with a self-contained website. Copy it anywhere +# and serve with COOP/COEP headers (etc/emscripten/serve.py is one option). + +set -euo pipefail + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +ROOT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd) + +RUNTIME="${CONTAINER_RUNTIME:-}" +if [[ -z "$RUNTIME" ]]; then + if command -v podman >/dev/null 2>&1; then + RUNTIME=podman + elif command -v docker >/dev/null 2>&1; then + RUNTIME=docker + else + echo "Error: neither podman nor docker found in PATH." >&2 + echo "Install one, or set CONTAINER_RUNTIME explicitly." >&2 + exit 1 + fi +fi + +IMAGE_TAG="gap-emscripten-build:3.1.23" + +# Pin the platform. emscripten/emsdk:3.1.23 is amd64-only on Docker Hub, so on +# Apple Silicon (or any non-amd64 host) the runtime would otherwise renegotiate +# the platform on every build -- that mismatch invalidates the FROM layer's +# cache and cascades through the whole image, defeating the layer cache even +# with --layers. Override with BUILD_PLATFORM if needed. +PLATFORM="${BUILD_PLATFORM:-linux/amd64}" + +echo ">> Using container runtime: $RUNTIME (platform: $PLATFORM)" +echo ">> Building image $IMAGE_TAG (cached after first run)" + +# --layers is the podman/buildah flag for "use the layer cache"; older +# podman versions default it to false. Docker has caching on by default +# and rejects the flag, so only pass it for podman. +declare -a BUILD_ARGS=(--platform "$PLATFORM") +if [[ "$RUNTIME" != "docker" ]]; then + BUILD_ARGS+=(--layers) +fi +"$RUNTIME" build "${BUILD_ARGS[@]}" -t "$IMAGE_TAG" -f "$SCRIPT_DIR/Dockerfile" "$SCRIPT_DIR" + +# Run as the host user where possible so build outputs are not root-owned. +declare -a USER_ARGS=() +if [[ "$RUNTIME" == "docker" ]]; then + USER_ARGS=(--user "$(id -u):$(id -g)" -e HOME=/tmp) +else + # Rootless podman maps host UID to container root by default. + USER_ARGS=(--userns=keep-id) +fi + +echo ">> Building GAP inside container" +"$RUNTIME" run --platform "$PLATFORM" --rm \ + -v "$ROOT_DIR:/gap" \ + -w /gap \ + "${USER_ARGS[@]}" \ + "$IMAGE_TAG" \ + bash etc/emscripten/build.sh + +echo ">> Assembling website" +bash "$SCRIPT_DIR/assemble-website.sh" + +cat </dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) -if ! command -v emmake &> /dev/null; then - echo Please install, and source, emscripten - echo This script was tested with version 3.1.23 - echo See https://emscripten.org/docs/getting_started/downloads.html for install instructions +if ! command -v emmake >/dev/null 2>&1; then + echo "Please install and source emscripten." >&2 + echo "This script is tested with emsdk 3.1.23." >&2 + echo "See https://emscripten.org/docs/getting_started/downloads.html" >&2 exit 1 -fi; +fi # Build the configure script if this is a fresh git checkout if [[ ! -f ./configure ]]; then ./autogen.sh fi -# First build a standard GAP install, for some files -# we will need during building +# First build a standard GAP install: we need ffgen and gap-nocomp on the +# host to generate sources that the wasm build cannot run itself. +# +# We copy those generated sources (build/c_*.c, build/ffdata.*) into src/ +# further down, so the wasm build picks them up as overrides. GAP's +# Makefile.rules, however, also treats src/c_oper1.c, src/ffdata.c etc. as +# overrides during THIS native build -- so leftovers from a previous run +# would stop the native build regenerating them in native-build/build/, and +# the copy below would then fail. Remove any leftovers so the native build +# regenerates them cleanly (keeps the script idempotent across re-runs). +rm -f src/c_oper1.c src/c_type1.c src/ffdata.c src/ffdata.h ( mkdir -p native-build cd native-build if [[ ! -f config.status ]]; then ../configure fi - make -j8 + make -j"$JOBS" ) AUX_BUILD=$PWD/extern/emscripten/build AUX_PREFIX=$PWD/extern/emscripten/install -mkdir -p "$AUX_BUILD" -mkdir -p "$AUX_PREFIX" +mkdir -p "$AUX_BUILD" "$AUX_PREFIX" +# A 32-bit build is required by GAP's small-integer representation, so we +# pin --build to i686-pc-linux-gnu. This may need revisiting if GAP ever +# moves to a 64-bit-friendly small-integer encoding. ( mkdir -p "$AUX_BUILD/gmp" - cd "$AUX_BUILD/gmp" && + cd "$AUX_BUILD/gmp" if [[ ! -f config.status ]]; then CC_FOR_BUILD=/usr/bin/gcc ABI=standard \ - emconfigure $BASEDIR/extern/gmp/configure \ - --build i686-pc-linux-gnu --host none \ - --disable-assembly --enable-cxx \ - --prefix=$AUX_PREFIX - fi && - emmake make -j8 && + emconfigure "$BASEDIR/extern/gmp/configure" \ + --build i686-pc-linux-gnu --host none \ + --disable-assembly --enable-cxx \ + --prefix="$AUX_PREFIX" + fi + emmake make -j"$JOBS" emmake make install ) ( mkdir -p "$AUX_BUILD/zlib" - cd "$AUX_BUILD/zlib" && + cd "$AUX_BUILD/zlib" if [[ ! -f Makefile ]]; then - emconfigure $BASEDIR/extern/zlib/configure --prefix=$AUX_PREFIX - fi; - emmake make -j8 && + # --static: skip the shared library. Newer emscripten's wasm-ld + # rejects linking zlib's .so test programs (examplesh) with + # "unknown file type: libz.so"; GAP only needs the static libz.a. + emconfigure "$BASEDIR/extern/zlib/configure" --static --prefix="$AUX_PREFIX" + fi + emmake make -j"$JOBS" emmake make install ) -# There are two problems with building GAP -# 1) GAP builds some executables (ffgen and gap-nocomp), which it wants to -# execute while building. We get these files from 'native-build'. -# 2) 'configure' gets confused by some of the LDFLAGS we need, so we have to pass -# them in to 'make' +# Two quirks of building GAP under emscripten: +# 1) GAP runs ffgen and gap-nocomp during the build. We copy the host-built +# versions in from native-build/ further down. +# 2) configure rejects some LDFLAGS we need at link time, so we pass them +# only at make-time. # -# These options are: -# -sASYNCIFY -- we don't care about ASYNC, but this forces the compiler to output -# all variables onto the stack, which is required for GASMAN -# Note we could use 'ALLOW_MEMORY_GROWTH', both we don't currently, we instead set -# a big memory window. -# -O2 : Some optimisation -# EXEEXT=.html -- this is actually a GAP makefile option, it lets us make the -# output 'gap.html', which makes emscripten output a html page we can load -# --pre-js lazy_fs.js : Prepend lazy_fs.js that is generated for lazy loading - -# Run configure if we don't have a makefile, or someone configured this -# GAP for standard building (emscripten builds will use 'emcc') -if [[ ! -f GNUmakefile ]] || ! grep '/emcc' GNUmakefile > /dev/null; then +# Link-time flags worth noting: +# -sASYNCIFY forces variables onto the stack (required by GASMAN). +# -O2 enables some optimisation. +# EXEEXT=.html a GAP makefile knob that produces gap.html, the html +# shim emscripten generates for loading the wasm module. + +if [[ ! -f GNUmakefile ]] || ! grep -q '/emcc' GNUmakefile; then + # Wipe any in-tree state from a prior native (or mismatched) build. + # Stale build/deps/*.d files reference build/ffdata.h, which under + # emcc would be regenerated by a non-executable JS shim; stale .o + # files have the wrong architecture. Configure regenerates build/. + rm -rf build ffgen emconfigure ./configure ABI=32 \ - --with-gmp=$AUX_PREFIX \ - --with-zlib=$AUX_PREFIX \ - LDFLAGS="-s ASYNCIFY=1 -O2" -fi; + --with-gmp="$AUX_PREFIX" \ + --with-zlib="$AUX_PREFIX" \ + LDFLAGS="-s ASYNCIFY=1 -O2" +fi -# Get full required packages -emmake make bootstrap-pkg-full +# Provide the GAP package distribution without re-downloading it on every +# build. Preference order: +# 1. An existing pkg/ directory. +# 2. packages.tar.gz already on the host (carried in the source mount). +# 3. The tarball baked into the docker image at /opt/gap-packages.tar.gz. +# 4. As a last resort, GAP's own bootstrap-pkg-full target downloads it. +# Skipping straight to tar avoids `bootstrap-pkg-full`, which calls +# curl -L -O unconditionally and overwrites packages.tar.gz on every run. +if [[ ! -d pkg ]]; then + if [[ ! -f packages.tar.gz && -f /opt/gap-packages.tar.gz ]]; then + cp /opt/gap-packages.tar.gz packages.tar.gz + fi + if [[ -f packages.tar.gz ]]; then + mkdir pkg + (cd pkg && tar xzf ../packages.tar.gz) + else + emmake make bootstrap-pkg-full + fi +fi -# Copy in files from native_build +# Copy host-built generated sources into place cp native-build/build/c_*.c native-build/build/ffdata.* src/ -# Dynamically find and append ALL required files to the JS array -# The flag -type f is safe because the only symbolic link is 'tst/mockpkg/Makefile.gappkg', -# which is safe to ignore -find pkg lib grp tst doc hpcgap dev benchmark -type f | python3 etc/emscripten/generate_gap_fs_json.py - -if [ $? -ne 0 ]; then - echo "Build aborted: generate_gap_fs_json.py failed." - exit 1 -fi +# Build the file list that will be served. -L follows symlinks so that +# users' local development setups (e.g. replacing pkg/foo with a symlink +# to a git checkout under git/foo) are picked up; -type f then drops any +# symlinks themselves. +find -L pkg lib grp tst doc hpcgap dev benchmark -type f ! -path 'pkg/log/*' \ + | python3 etc/emscripten/generate_gap_fs_json.py -# The EXEEXT is usually for windows, but here it lets us set GAP's extension, -# which lets us produce a html page to run GAP in. -emmake make -j8 LDFLAGS="-lidbfs.js -s ASYNCIFY=1 -sTOTAL_STACK=32mb -sASYNCIFY_STACK_SIZE=32000000 -sINITIAL_MEMORY=2048mb -O2" EXEEXT=".html" +emmake make -j"$JOBS" \ + LDFLAGS="-lidbfs.js -s ASYNCIFY=1 -sTOTAL_STACK=32mb -sASYNCIFY_STACK_SIZE=32000000 -sINITIAL_MEMORY=2048mb -O2" \ + EXEEXT=".html" diff --git a/etc/emscripten/build_startup_manifest.js b/etc/emscripten/build_startup_manifest.js deleted file mode 100755 index edb8594b10..0000000000 --- a/etc/emscripten/build_startup_manifest.js +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env node -"use strict"; - -const http = require('http'); -const fs = require('fs'); -const path = require('path'); - -const PORT = 9999; -const BASE_DIR = process.cwd(); -const LOG_FILE = path.join(BASE_DIR, 'startup_manifest.json'); - -const requestedFiles = new Set(); -fs.writeFileSync(LOG_FILE, '[\n]'); - -const server = http.createServer((req, res) => { - let urlPath = req.url.split('?')[0]; - if (urlPath === '/') { - urlPath = '/index.html'; - } - - let localDiskPath = urlPath; - try { - localDiskPath = decodeURIComponent(urlPath); - } catch (e) {} - - const filePath = path.join(BASE_DIR, localDiskPath); - - fs.readFile(filePath, (err, data) => { - if (err) { - console.error(`[404] Ignored missing file: ${localDiskPath}`); - res.writeHead(404); - res.end(`404: File not found`); - return; - } - - const ignored = ['/favicon.ico', '/index.html', '/startup_manifest.json', 'coi-serviceworker.js', 'gap-worker.js', 'gap-fs.js', 'gap.js', 'gap.wasm', 'gap-fs.json']; - if (!ignored.includes(localDiskPath)) { - let manifestPath = localDiskPath.startsWith('/') ? localDiskPath.substring(1) : localDiskPath; - - if (!requestedFiles.has(manifestPath)) { - requestedFiles.add(manifestPath); - - const manifest = Array.from(requestedFiles); - fs.writeFileSync(LOG_FILE, JSON.stringify(manifest, null, 4)); - - console.log(`[Loaded & Logged] ${manifestPath} (Total: ${requestedFiles.size})`); - } - } - - let contentType = 'application/octet-stream'; - if (urlPath.endsWith('.html')) contentType = 'text/html'; - else if (urlPath.endsWith('.js')) contentType = 'text/javascript'; - else if (urlPath.endsWith('.wasm')) contentType = 'application/wasm'; - else if (urlPath.endsWith('.css')) contentType = 'text/css'; - - res.writeHead(200, { - 'Content-Type': contentType, - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Access-Control-Allow-Origin': '*' - }); - - res.end(data); - }); -}); - -server.listen(PORT, '0.0.0.0', () => { - console.log(`\n Tracker running at http://localhost:${PORT}/`); - console.log(`Serving files from: ${BASE_DIR}`); - console.log(`Logging valid loaded files to: ${LOG_FILE}\n`); -}); diff --git a/etc/emscripten/generate_gap_fs_json.py b/etc/emscripten/generate_gap_fs_json.py index dbf5447bba..917f0a2a38 100755 --- a/etc/emscripten/generate_gap_fs_json.py +++ b/etc/emscripten/generate_gap_fs_json.py @@ -1,18 +1,11 @@ -import sys -import json -import os - -def main(): - paths = [line.strip() for line in sys.stdin if line.strip()] +#!/usr/bin/env python3 +"""Read a list of file paths from stdin (one per line) and write them as a +JSON array to gap-fs.json in the current directory.""" - try: - with open('gap-fs.json', 'w', encoding='utf-8') as f: - json.dump(paths, f, separators=(',', ':')) - - print(f"Successfully wrote {len(paths)} files to gap-fs.json", file=sys.stderr) - except Exception as e: - print(f"Failed to write gap-fs.json: {e}", file=sys.stderr) - sys.exit(1) +import json +import sys -if __name__ == "__main__": - main() +paths = [line.strip() for line in sys.stdin if line.strip()] +with open("gap-fs.json", "w", encoding="utf-8") as f: + json.dump(paths, f, separators=(",", ":")) +print(f"wrote {len(paths)} files to gap-fs.json", file=sys.stderr) diff --git a/etc/emscripten/run-web-demo.sh b/etc/emscripten/run-web-demo.sh deleted file mode 100755 index a82eb948a9..0000000000 --- a/etc/emscripten/run-web-demo.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -eux - -echo This script assumes you have already run 'build.sh' - -mkdir -p web-example -cp etc/emscripten/web-template/* web-example/ -cp gap.js gap.wasm gap.worker.js gap-fs.json web-example/ - -cp -r pkg lib grp tst doc hpcgap dev benchmark web-example/ -cd web-example -../etc/emscripten/server.rb diff --git a/etc/emscripten/serve.py b/etc/emscripten/serve.py new file mode 100755 index 0000000000..7d089f0c54 --- /dev/null +++ b/etc/emscripten/serve.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +"""Serve the current directory with the COOP/COEP headers required by +xterm-pty's SharedArrayBuffer usage. Run from the assembled web-example/ +(or any directory containing the gap.* artifacts). + + ./serve.py # listens on 8080 + ./serve.py 9000 # listens on 9000 +""" + +from __future__ import annotations + +import http.server +import socketserver +import sys + + +class CrossOriginIsolatedHandler(http.server.SimpleHTTPRequestHandler): + def end_headers(self): + self.send_header("Cross-Origin-Opener-Policy", "same-origin") + self.send_header("Cross-Origin-Embedder-Policy", "require-corp") + super().end_headers() + + +def main() -> None: + port = int(sys.argv[1]) if len(sys.argv) > 1 else 8080 + with socketserver.TCPServer(("", port), CrossOriginIsolatedHandler) as httpd: + print(f"Serving on http://localhost:{port}/ (Ctrl-C to stop)") + try: + httpd.serve_forever() + except KeyboardInterrupt: + print() + + +if __name__ == "__main__": + main() diff --git a/etc/emscripten/server.rb b/etc/emscripten/server.rb deleted file mode 100755 index 642c9ad167..0000000000 --- a/etc/emscripten/server.rb +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env ruby -# Taken from https://github.com/mame/xterm-pty/ - -require "webrick" - -class Server < WEBrick::HTTPServer - def service(req, res) - super - res["Cross-Origin-Opener-Policy"] = "same-origin" - res["Cross-Origin-Embedder-Policy"] = "require-corp" - end -end - -Server.new(Port: 8080, DocumentRoot: ".").start - diff --git a/etc/emscripten/startup_manifest.json b/etc/emscripten/startup_manifest.json new file mode 100644 index 0000000000..3ab701c269 --- /dev/null +++ b/etc/emscripten/startup_manifest.json @@ -0,0 +1,1521 @@ +[ + "lib/init.g", + "lib/kernel.g", + "lib/global.g", + "lib/system.g", + "lib/read1.g", + "lib/hpc/thread1.g", + "lib/filter.g", + "lib/oper.g", + "lib/oper1.g", + "lib/type.g", + "lib/type1.g", + "lib/methsel.g", + "lib/methsel2.g", + "lib/function.g", + "lib/cache.gd", + "lib/object.gd", + "lib/variable.g", + "lib/package.gd", + "lib/coll.gd", + "lib/list.gd", + "lib/wpobj.gd", + "lib/arith.gd", + "lib/ffe.gd", + "lib/domain.gd", + "lib/string.g", + "lib/cyclotom.g", + "lib/set.gd", + "lib/record.gd", + "lib/random.gd", + "lib/cache.gi", + "lib/coll.gi", + "lib/flag.g", + "lib/boolean.g", + "lib/ffe.g", + "lib/arith.gi", + "lib/list.g", + "lib/wpobj.g", + "lib/permutat.g", + "lib/trans.g", + "lib/pperm.g", + "lib/filter.gi", + "lib/object.gi", + "lib/listcoef.gd", + "lib/info.gd", + "lib/files.gd", + "lib/streams.gd", + "lib/record.gi", + "lib/matobj1.gd", + "lib/vecmat.gd", + "lib/vec8bit.gd", + "lib/mat8bit.gd", + "lib/global.gd", + "lib/info.gi", + "lib/global.gi", + "lib/options.gd", + "lib/options.gi", + "lib/attr.gd", + "lib/attr.gi", + "lib/string.gd", + "lib/userpref.g", + "lib/cmdledit.g", + "lib/cmdleditx.g", + "lib/objset.g", + "lib/float.gd", + "lib/macfloat.g", + "lib/hpc/tasks.g", + "lib/error.g", + "lib/session.g", + "lib/read2.g", + "lib/process.gd", + "lib/files.gi", + "lib/streams.gi", + "lib/process.gi", + "lib/read3.g", + "lib/type.gd", + "lib/tuples.gd", + "lib/rvecempt.gd", + "lib/extaset.gd", + "lib/extlset.gd", + "lib/extrset.gd", + "lib/extuset.gd", + "lib/dict.gd", + "lib/bitfields.gd", + "lib/mapping.gd", + "lib/mapphomo.gd", + "lib/relation.gd", + "lib/magma.gd", + "lib/mgmideal.gd", + "lib/mgmhom.gd", + "lib/mgmadj.gd", + "lib/mgmcong.gd", + "lib/semicong.gd", + "lib/semigrp.gd", + "lib/smgideal.gd", + "lib/monoid.gd", + "lib/grp.gd", + "lib/invsgp.gd", + "lib/addmagma.gd", + "lib/addcoset.gd", + "lib/semiring.gd", + "lib/ring.gd", + "lib/matrix.gd", + "lib/matint.gd", + "lib/matblock.gd", + "lib/ideal.gd", + "lib/module.gd", + "lib/basis.gd", + "lib/basismut.gd", + "lib/vspc.gd", + "lib/vspchom.gd", + "lib/zlattice.gd", + "lib/algebra.gd", + "lib/mgmring.gd", + "lib/algfp.gd", + "lib/alglie.gd", + "lib/algsc.gd", + "lib/alghom.gd", + "lib/liefam.gd", + "lib/algrep.gd", + "lib/lierep.gd", + "lib/integer.gd", + "lib/gaussian.gd", + "lib/numtheor.gd", + "lib/dlog.gd", + "lib/primality.gd", + "lib/contfrac.gd", + "lib/ringsc.gd", + "lib/ringhom.gd", + "lib/combinat.gd", + "lib/ratfun.gd", + "lib/fampred.g", + "lib/list.gi", + "lib/set.gi", + "lib/wpobj.gi", + "lib/random.gi", + "lib/field.gd", + "lib/zmodnz.gd", + "lib/zmodnze.gd", + "lib/cyclotom.gd", + "lib/fldabnum.gd", + "lib/padics.gd", + "lib/ringpoly.gd", + "lib/upoly.gd", + "lib/polyfinf.gd", + "lib/polyrat.gd", + "lib/polyconw.gd", + "lib/algfld.gd", + "lib/meataxe.gd", + "lib/unknown.gd", + "lib/word.gd", + "lib/wordass.gd", + "lib/matobj2.gd", + "lib/matobjplist.gd", + "lib/matobjnz.gd", + "lib/rws.gd", + "lib/rwspcclt.gd", + "lib/rwsgrp.gd", + "lib/rwspcgrp.gd", + "lib/groebner.gd", + "lib/pcgs.gd", + "lib/pcgsind.gd", + "lib/pcgspcg.gd", + "lib/pcgsmodu.gd", + "lib/pcgsperm.gd", + "lib/pcgsspec.gd", + "lib/grppc.gd", + "lib/grppcnrm.gd", + "lib/grptbl.gd", + "lib/grpperm.gd", + "lib/grpprmcs.gd", + "lib/stbcbckt.gd", + "lib/ghom.gd", + "lib/ghompcgs.gd", + "lib/gprd.gd", + "lib/ghomperm.gd", + "lib/gpprmsya.gd", + "lib/addgphom.gd", + "lib/grpnames.g", + "lib/grpnames.gd", + "lib/quotsys.gd", + "lib/pquot.gd", + "lib/oprt.gd", + "lib/partitio.gd", + "lib/stbc.gd", + "lib/clas.gd", + "lib/clashom.gd", + "lib/permdeco.gd", + "lib/csetgrp.gd", + "lib/factgrp.gd", + "lib/grpreps.gd", + "lib/grppcrep.gd", + "lib/onecohom.gd", + "lib/grppccom.gd", + "lib/twocohom.gd", + "lib/grppcext.gd", + "lib/grppcfp.gd", + "lib/randiso.gd", + "lib/schur.gd", + "lib/schursym.gd", + "lib/grplatt.gd", + "lib/oprtglat.gd", + "lib/grppclat.gd", + "lib/grppcaut.gd", + "lib/straight.gd", + "lib/memory.gd", + "lib/grpfp.gd", + "lib/grpfree.gd", + "lib/sgpres.gd", + "lib/tietze.gd", + "lib/ghomfp.gd", + "lib/dt.g", + "lib/integer.gi", + "lib/grpnice.gd", + "lib/morpheus.gd", + "lib/grpmat.gd", + "lib/fitfree.gd", + "lib/grpffmat.gd", + "lib/grpramat.gd", + "grp/basic.gd", + "grp/classic.gd", + "grp/conformal.gd", + "grp/perf.gd", + "grp/suzuki.gd", + "grp/ree.gd", + "grp/simple.gd", + "grp/imf.gd", + "grp/glzmodmz.gd", + "grp/clasmax.grp", + "lib/orders.gd", + "lib/trans.gd", + "lib/pperm.gd", + "lib/fastendo.gd", + "lib/fpsemi.gd", + "lib/fpmon.gd", + "lib/rwssmg.gd", + "lib/kbsemi.gd", + "lib/tcsemi.gd", + "lib/adjoin.gd", + "lib/semirel.gd", + "lib/semitran.gd", + "lib/reesmat.gd", + "lib/semiquo.gd", + "lib/semipperm.gd", + "lib/pager.gd", + "lib/helpbase.gd", + "lib/helpview.gd", + "lib/helpt2t.gd", + "lib/helpdef.gd", + "lib/ctbl.gd", + "lib/ctblfuns.gd", + "lib/ctblmaps.gd", + "lib/ctblauto.gd", + "lib/ctbllatt.gd", + "lib/ctblsymm.gd", + "lib/ctblsolv.gd", + "lib/ctblpope.gd", + "lib/ctblmoli.gd", + "lib/ctblmono.gd", + "lib/ctblgrp.gd", + "lib/tom.gd", + "lib/proto.gd", + "lib/gasman.gd", + "lib/memusage.gd", + "lib/read4.g", + "lib/profile.g", + "lib/newprofile.g", + "lib/methwhy.g", + "lib/pager.gi", + "lib/helpbase.gi", + "lib/helpview.gi", + "lib/helpt2t.gi", + "lib/helpdef.gi", + "lib/reread.g", + "lib/package.gi", + "lib/string.gi", + "lib/test.gd", + "lib/test.gi", + "lib/galois.gd", + "lib/galois.gi", + "lib/transatl.g", + "lib/obsolete.g", + "lib/obsolete.gd", + "lib/read.g", + "lib/read5.g", + "lib/type.gi", + "lib/rvecempt.gi", + "lib/ratfun1.gi", + "lib/matrix.gi", + "lib/matint.gi", + "lib/matblock.gi", + "lib/tuples.gi", + "lib/domain.gi", + "lib/mapping1.gi", + "lib/mapping.gi", + "lib/mapprep.gi", + "lib/mapphomo.gi", + "lib/relation.gi", + "lib/magma.gi", + "lib/mgmideal.gi", + "lib/mgmhom.gi", + "lib/mgmadj.gi", + "lib/mgmcong.gi", + "lib/semigrp.gi", + "lib/semicong.gi", + "lib/smgideal.gi", + "lib/monoid.gi", + "lib/grp.gi", + "lib/invsgp.gi", + "lib/addmagma.gi", + "lib/addcoset.gi", + "lib/ring.gi", + "lib/ideal.gi", + "lib/module.gi", + "lib/modfree.gi", + "lib/modulrow.gi", + "lib/modulmat.gi", + "lib/basis.gi", + "lib/basismut.gi", + "lib/vspc.gi", + "lib/vspcrow.gi", + "lib/vspcmat.gi", + "lib/vspchom.gi", + "lib/zlattice.gi", + "lib/mgmring.gi", + "lib/algebra.gi", + "lib/idealalg.gi", + "lib/alghom.gi", + "lib/algfp.gi", + "lib/alglie.gi", + "lib/algliess.gi", + "lib/algsc.gi", + "lib/algmat.gi", + "lib/liefam.gi", + "lib/algrep.gi", + "lib/lierep.gi", + "lib/numtheor.gi", + "lib/dlog.gi", + "lib/primality.gi", + "lib/contfrac.gi", + "lib/ringsc.gi", + "lib/ringhom.gi", + "lib/combinat.gi", + "lib/ratfun.gi", + "lib/ratfunul.gi", + "lib/ringpoly.gi", + "lib/upoly.gi", + "lib/upolyirr.gi", + "lib/polyfinf.gi", + "lib/polyrat.gi", + "lib/polyconw.gi", + "lib/listcoef.gi", + "lib/algfld.gi", + "lib/groebner.gi", + "lib/unknown.gi", + "lib/field.gi", + "lib/fieldfin.gi", + "lib/zmodnz.gi", + "lib/zmodnze.gi", + "lib/ffe.gi", + "lib/ffeconway.gi", + "lib/rational.gi", + "lib/gaussian.gi", + "lib/cyclotom.gi", + "lib/fldabnum.gi", + "lib/padics.gi", + "lib/matobj.gi", + "lib/matobjrowlist.gi", + "lib/vecmat.gi", + "lib/vec8bit.gi", + "lib/mat8bit.gi", + "lib/matobjplist.gi", + "lib/matobjnz.gi", + "lib/meataxe.gi", + "lib/meatauto.gi", + "lib/word.gi", + "lib/wordass.gi", + "lib/wordrep.gi", + "lib/wordlett.gi", + "lib/mgmfree.gi", + "lib/smgrpfre.gi", + "lib/monofree.gi", + "lib/grpfree.gi", + "lib/rws.gi", + "lib/rwspcclt.gi", + "lib/rwspcsng.gi", + "lib/rwspccoc.gi", + "lib/rwsgrp.gi", + "lib/rwspcgrp.gi", + "lib/rwsdt.gi", + "lib/nilpquot.gi", + "lib/pquot.gi", + "lib/pcgs.gi", + "lib/pcgsind.gi", + "lib/pcgsmodu.gi", + "lib/pcgspcg.gi", + "lib/pcgscomp.gi", + "lib/pcgsperm.gi", + "lib/pcgsnice.gi", + "lib/pcgsspec.gi", + "lib/grppc.gi", + "lib/grppcint.gi", + "lib/grppcprp.gi", + "lib/grppcatr.gi", + "lib/grppcnrm.gi", + "lib/bitfields.gi", + "lib/dict.gi", + "lib/dicthf.gi", + "lib/grptbl.gi", + "lib/ghom.gi", + "lib/ghompcgs.gi", + "lib/gprd.gi", + "lib/ghomperm.gi", + "lib/grpperm.gi", + "lib/gpprmsya.gi", + "lib/gprdperm.gi", + "lib/gprdpc.gi", + "lib/gprdmat.gi", + "lib/oprt.gi", + "lib/oprtperm.gi", + "lib/oprtpcgs.gi", + "lib/partitio.gi", + "lib/stbc.gi", + "lib/stbcbckt.gi", + "lib/stbcrand.gi", + "lib/clas.gi", + "lib/claspcgs.gi", + "lib/csetgrp.gi", + "lib/csetperm.gi", + "lib/csetpc.gi", + "lib/factgrp.gi", + "lib/grpreps.gi", + "lib/grppcrep.gi", + "lib/grpprmcs.gi", + "lib/grpnames.gi", + "lib/onecohom.gi", + "lib/grppccom.gi", + "lib/grpcompl.gi", + "lib/twocohom.gi", + "lib/grppcext.gi", + "lib/randiso.gi", + "lib/randiso2.gi", + "lib/grppcfp.gi", + "lib/schur.gi", + "lib/schursym.gi", + "lib/grpnice.gi", + "lib/fitfree.gi", + "lib/permdeco.gi", + "lib/clashom.gi", + "lib/clasperm.gi", + "lib/maxsub.gi", + "lib/norad.gi", + "lib/autsr.gi", + "lib/morpheus.gi", + "lib/grplatt.gi", + "lib/oprtglat.gi", + "lib/grppclat.gi", + "lib/grppcaut.gi", + "lib/grpmat.gi", + "lib/grpffmat.gi", + "lib/grpramat.gi", + "lib/grpfp.gi", + "lib/gpfpiso.gi", + "lib/sgpres.gi", + "lib/tietze.gi", + "lib/ghomfp.gi", + "lib/addgphom.gi", + "lib/trans.gi", + "lib/pperm.gi", + "lib/fastendo.gi", + "lib/fpsemi.gi", + "lib/fpmon.gi", + "lib/rwssmg.gi", + "lib/kbsemi.gi", + "lib/tcsemi.gi", + "lib/adjoin.gi", + "lib/semirel.gi", + "lib/semitran.gi", + "lib/reesmat.gi", + "lib/semiquo.gi", + "lib/semipperm.gi", + "lib/proto.gi", + "lib/orders.gi", + "lib/gasman.gi", + "lib/memusage.gi", + "lib/function.gi", + "lib/float.gi", + "lib/ieee754.g", + "lib/read6.g", + "grp/basicpcg.gi", + "grp/basicprm.gi", + "grp/basicmat.gi", + "grp/basicfp.gi", + "grp/perf.grp", + "grp/classic.gi", + "grp/conformal.gi", + "grp/suzuki.gi", + "grp/ree.gi", + "grp/simple.gi", + "grp/imf.grp", + "grp/imf.gi", + "grp/glzmodmz.gi", + "lib/read7.g", + "lib/ctbl.gi", + "lib/ctblfuns.gi", + "lib/ctblmaps.gi", + "lib/ctblauto.gi", + "lib/ctbllatt.gi", + "lib/ctblsymm.gi", + "lib/ctblsolv.gi", + "lib/ctblpope.gi", + "lib/ctblmoli.gi", + "lib/ctblmono.gi", + "lib/ctblgrp.gi", + "lib/ctblperm.gi", + "lib/ctblpc.gi", + "lib/tom.gi", + "lib/straight.gi", + "lib/memory.gi", + "lib/read8.g", + "lib/overload.g", + "lib/syntaxtree.gd", + "lib/syntaxtree.gi", + "lib/teaching.g", + "lib/teachm2.g", + "lib/operdebug.g", + "lib/colorprompt.g", + "pkg/4ti2interface/PackageInfo.g", + "pkg/ace/PackageInfo.g", + "pkg/aclib/PackageInfo.g", + "pkg/agt/PackageInfo.g", + "pkg/alco/PackageInfo.g", + "pkg/alnuth/PackageInfo.g", + "pkg/anupq/PackageInfo.g", + "pkg/atlasrep/PackageInfo.g", + "pkg/autodoc/PackageInfo.g", + "pkg/automata/PackageInfo.g", + "pkg/automgrp/PackageInfo.g", + "pkg/autpgrp/PackageInfo.g", + "pkg/browse/PackageInfo.g", + "pkg/cap/PackageInfo.g", + "pkg/caratinterface/PackageInfo.g", + "pkg/cddinterface/PackageInfo.g", + "pkg/circle/PackageInfo.g", + "pkg/classicalmaximals/PackageInfo.g", + "pkg/classicpres/PackageInfo.g", + "pkg/cohomolo/PackageInfo.g", + "pkg/congruence/PackageInfo.g", + "pkg/corefreesub/PackageInfo.g", + "pkg/corelg/PackageInfo.g", + "pkg/crime/PackageInfo.g", + "pkg/crisp/PackageInfo.g", + "pkg/crypting/PackageInfo.g", + "pkg/cryst/PackageInfo.g", + "pkg/crystcat/PackageInfo.g", + "pkg/ctbllib/PackageInfo.g", + "pkg/cubefree/PackageInfo.g", + "pkg/curlinterface/PackageInfo.g", + "pkg/cvec/PackageInfo.g", + "pkg/datastructures/PackageInfo.g", + "pkg/deepthought/PackageInfo.g", + "pkg/design/PackageInfo.g", + "pkg/difsets/PackageInfo.g", + "pkg/digraphs/PackageInfo.g", + "pkg/edim/PackageInfo.g", + "pkg/example/PackageInfo.g", + "pkg/examplesforhomalg/PackageInfo.g", + "pkg/factint/PackageInfo.g", + "pkg/ferret/PackageInfo.g", + "pkg/fga/PackageInfo.g", + "pkg/fining/PackageInfo.g", + "pkg/float/PackageInfo.g", + "pkg/format/PackageInfo.g", + "pkg/forms/PackageInfo.g", + "pkg/fplsa/PackageInfo.g", + "pkg/fr/PackageInfo.g", + "pkg/francy/PackageInfo.g", + "pkg/fwtree/PackageInfo.g", + "pkg/gapdoc/PackageInfo.g", + "pkg/gauss/PackageInfo.g", + "pkg/gaussforhomalg/PackageInfo.g", + "pkg/gbnp/PackageInfo.g", + "pkg/generalizedmorphismsforcap/PackageInfo.g", + "pkg/genss/PackageInfo.g", + "pkg/gradedmodules/PackageInfo.g", + "pkg/gradedringforhomalg/PackageInfo.g", + "pkg/grape/PackageInfo.g", + "pkg/groupoids/PackageInfo.g", + "pkg/grpconst/PackageInfo.g", + "pkg/guarana/PackageInfo.g", + "pkg/guava/PackageInfo.g", + "pkg/hap/PackageInfo.g", + "pkg/hapcryst/PackageInfo.g", + "pkg/hecke/PackageInfo.g", + "pkg/help/PackageInfo.g", + "pkg/homalg/PackageInfo.g", + "pkg/homalgtocas/PackageInfo.g", + "pkg/ibnp/PackageInfo.g", + "pkg/idrel/PackageInfo.g", + "pkg/images/PackageInfo.g", + "pkg/inducereduce/PackageInfo.g", + "pkg/intpic/PackageInfo.g", + "pkg/io/PackageInfo.g", + "pkg/io_forhomalg/PackageInfo.g", + "pkg/irredsol/PackageInfo.g", + "pkg/itc/PackageInfo.g", + "pkg/json/PackageInfo.g", + "pkg/jupyterkernel/PackageInfo.g", + "pkg/jupyterviz/PackageInfo.g", + "pkg/kan/PackageInfo.g", + "pkg/kbmag/PackageInfo.g", + "pkg/laguna/PackageInfo.g", + "pkg/liealgdb/PackageInfo.g", + "pkg/liepring/PackageInfo.g", + "pkg/liering/PackageInfo.g", + "pkg/linearalgebraforcap/PackageInfo.g", + "pkg/lins/PackageInfo.g", + "pkg/localizeringforhomalg/PackageInfo.g", + "pkg/localnr/PackageInfo.g", + "pkg/loops/PackageInfo.g", + "pkg/lpres/PackageInfo.g", + "pkg/majoranaalgebras/PackageInfo.g", + "pkg/mapclass/PackageInfo.g", + "pkg/matgrp/PackageInfo.g", + "pkg/matricesforhomalg/PackageInfo.g", + "pkg/modisom/PackageInfo.g", + "pkg/modulargroup/PackageInfo.g", + "pkg/modulepresentationsforcap/PackageInfo.g", + "pkg/modules/PackageInfo.g", + "pkg/monoidalcategories/PackageInfo.g", + "pkg/nconvex/PackageInfo.g", + "pkg/nilmat/PackageInfo.g", + "pkg/nock/PackageInfo.g", + "pkg/nofoma/PackageInfo.g", + "pkg/normalizinterface/PackageInfo.g", + "pkg/nq/PackageInfo.g", + "pkg/numericalsgps/PackageInfo.g", + "pkg/openmath/PackageInfo.g", + "pkg/orb/PackageInfo.g", + "pkg/origami/PackageInfo.g", + "pkg/packagemaker/PackageInfo.g", + "pkg/packagemanager/PackageInfo.g", + "pkg/patternclass/PackageInfo.g", + "pkg/permut/PackageInfo.g", + "pkg/polenta/PackageInfo.g", + "pkg/polycyclic/PackageInfo.g", + "pkg/polymaking/PackageInfo.g", + "pkg/primgrp/PackageInfo.g", + "pkg/profiling/PackageInfo.g", + "pkg/qdistrnd/PackageInfo.g", + "pkg/qpa/PackageInfo.g", + "pkg/quagroup/PackageInfo.g", + "pkg/radiroot/PackageInfo.g", + "pkg/rcwa/PackageInfo.g", + "pkg/rds/PackageInfo.g", + "pkg/recog/PackageInfo.g", + "pkg/repndecomp/PackageInfo.g", + "pkg/repsn/PackageInfo.g", + "pkg/resclasses/PackageInfo.g", + "pkg/ringsforhomalg/PackageInfo.g", + "pkg/sco/PackageInfo.g", + "pkg/scscp/PackageInfo.g", + "pkg/semigroups/PackageInfo.g", + "pkg/sglppow/PackageInfo.g", + "pkg/sgpviz/PackageInfo.g", + "pkg/simpcomp/PackageInfo.g", + "pkg/singular/PackageInfo.g", + "pkg/sl2reps/PackageInfo.g", + "pkg/sla/PackageInfo.g", + "pkg/smallantimagmas/PackageInfo.g", + "pkg/smallclassnr/PackageInfo.g", + "pkg/smallgrp/PackageInfo.g", + "pkg/smallsemi/PackageInfo.g", + "pkg/sonata/PackageInfo.g", + "pkg/sophus/PackageInfo.g", + "pkg/sotgrps/PackageInfo.g", + "pkg/spinsym/PackageInfo.g", + "pkg/standardff/PackageInfo.g", + "pkg/symbcompcc/PackageInfo.g", + "pkg/thelma/PackageInfo.g", + "pkg/tomlib/PackageInfo.g", + "pkg/toolsforhomalg/PackageInfo.g", + "pkg/toric/PackageInfo.g", + "pkg/transgrp/PackageInfo.g", + "pkg/twistedconjugacy/PackageInfo.g", + "pkg/typeset/PackageInfo.g", + "pkg/ugaly/PackageInfo.g", + "pkg/unipot/PackageInfo.g", + "pkg/unitlib/PackageInfo.g", + "pkg/utils/PackageInfo.g", + "pkg/uuid/PackageInfo.g", + "pkg/walrus/PackageInfo.g", + "pkg/wedderga/PackageInfo.g", + "pkg/wpe/PackageInfo.g", + "pkg/xgap/PackageInfo.g", + "pkg/xmod/PackageInfo.g", + "pkg/xmodalg/PackageInfo.g", + "pkg/yangbaxter/PackageInfo.g", + "pkg/zeromqinterface/PackageInfo.g", + "pkg/gapdoc/init.g", + "pkg/gapdoc/lib/UnicodeTools.gd", + "pkg/gapdoc/lib/PrintUtil.gd", + "pkg/gapdoc/lib/Text.gd", + "pkg/gapdoc/lib/ComposeXML.gd", + "pkg/gapdoc/lib/XMLParser.gd", + "pkg/gapdoc/lib/GAPDoc.gd", + "pkg/gapdoc/lib/BibTeX.gd", + "pkg/gapdoc/lib/BibXMLextTools.gd", + "pkg/gapdoc/lib/GAPDoc2LaTeX.gd", + "pkg/gapdoc/lib/GAPDoc2Text.gd", + "pkg/gapdoc/lib/GAPDoc2HTML.gd", + "pkg/gapdoc/lib/Make.g", + "pkg/gapdoc/lib/Examples.gd", + "pkg/gapdoc/read.g", + "pkg/gapdoc/lib/UnicodeTools.gi", + "pkg/gapdoc/lib/UnicodeTabs.g", + "pkg/gapdoc/lib/PrintUtil.gi", + "pkg/gapdoc/lib/Text.gi", + "pkg/gapdoc/lib/ComposeXML.gi", + "pkg/gapdoc/lib/XMLParser.gi", + "pkg/gapdoc/lib/gapdocdtdinfo.g", + "pkg/gapdoc/lib/GAPDoc.gi", + "pkg/gapdoc/lib/BibTeX.gi", + "pkg/gapdoc/lib/bibxmlextinfo.g", + "pkg/gapdoc/lib/BibXMLextTools.gi", + "pkg/gapdoc/lib/GAPDoc2LaTeX.gi", + "pkg/gapdoc/lib/latexhead.tex", + "pkg/gapdoc/lib/GAPDoc2Text.gi", + "pkg/gapdoc/lib/TextThemes.g", + "pkg/gapdoc/lib/GAPDoc2HTML.gi", + "pkg/gapdoc/lib/Examples.gi", + "pkg/gapdoc/lib/HelpBookHandler.g", + "pkg/primgrp/init.g", + "pkg/primgrp/lib/primitiv.gd", + "pkg/primgrp/lib/irredsol.gd", + "pkg/primgrp/read.g", + "pkg/primgrp/lib/primitiv.grp", + "pkg/primgrp/lib/primitiv.gi", + "pkg/primgrp/lib/irredsol.grp", + "pkg/primgrp/lib/irredsol.gi", + "pkg/primgrp/lib/cohorts.grp", + "pkg/smallgrp/init.g", + "pkg/smallgrp/gap/small.gd", + "pkg/smallgrp/read.g", + "pkg/smallgrp/gap/small.gi", + "pkg/smallgrp/gap/smlgp1.g", + "pkg/smallgrp/gap/idgrp1.g", + "pkg/smallgrp/gap/smlinfo.gi", + "pkg/smallgrp/small2/smlgp2.g.gz", + "pkg/smallgrp/small3/smlgp3.g.gz", + "pkg/smallgrp/small4/smlgp4.g.gz", + "pkg/smallgrp/small5/smlgp5.g.gz", + "pkg/smallgrp/small6/smlgp6.g.gz", + "pkg/smallgrp/small7/smlgp7.g.gz", + "pkg/smallgrp/small8/smlgp8.g.gz", + "pkg/smallgrp/small9/smlgp9.g.gz", + "pkg/smallgrp/small10/smlgp10.g.gz", + "pkg/smallgrp/small11/smlgp11.g.gz", + "pkg/smallgrp/id2/idgrp2.g.gz", + "pkg/smallgrp/id3/idgrp3.g.gz", + "pkg/smallgrp/id4/idgrp4.g.gz", + "pkg/smallgrp/id5/idgrp5.g.gz", + "pkg/smallgrp/id6/idgrp6.g.gz", + "pkg/smallgrp/id9/idgrp9.g.gz", + "pkg/smallgrp/id10/idgrp10.g.gz", + "pkg/transgrp/init.g", + "pkg/transgrp/lib/trans.gd", + "pkg/transgrp/read.g", + "pkg/transgrp/lib/trans.grp", + "pkg/transgrp/lib/trans.gi", + "pkg/autpgrp/init.g", + "pkg/autpgrp/gap/autos.gd", + "pkg/autpgrp/read.g", + "pkg/autpgrp/gap/general.gi", + "pkg/autpgrp/gap/autoops.gi", + "pkg/autpgrp/gap/matrix.gi", + "pkg/autpgrp/gap/nicestab.gi", + "pkg/autpgrp/gap/initmat.gi", + "pkg/autpgrp/gap/initperm.gi", + "pkg/autpgrp/gap/hybrstab.gi", + "pkg/autpgrp/gap/matrstab.gi", + "pkg/autpgrp/gap/orbstab.gi", + "pkg/autpgrp/gap/autos.gi", + "pkg/autpgrp/gap/pcpres.gi", + "pkg/autpgrp/gap/countcl.gi", + "pkg/alnuth/init.g", + "pkg/alnuth/gap/setup.gd", + "pkg/alnuth/gap/factors.gd", + "pkg/alnuth/gap/field.gd", + "pkg/polycyclic/init.g", + "pkg/polycyclic/gap/matrix/matrix.gd", + "pkg/polycyclic/gap/basic/infos.gd", + "pkg/polycyclic/gap/basic/collect.gd", + "pkg/polycyclic/gap/basic/pcpelms.gd", + "pkg/polycyclic/gap/basic/pcpgrps.gd", + "pkg/polycyclic/gap/basic/pcppcps.gd", + "pkg/polycyclic/gap/basic/grphoms.gd", + "pkg/polycyclic/gap/basic/basic.gd", + "pkg/polycyclic/gap/cohom/cohom.gd", + "pkg/polycyclic/gap/matrep/matrep.gd", + "pkg/polycyclic/gap/matrep/unitri.gd", + "pkg/polycyclic/gap/pcpgrp/pcpgrp.gd", + "pkg/polycyclic/gap/pcpgrp/torsion.gd", + "pkg/polycyclic/gap/exam/exam.gd", + "pkg/polycyclic/gap/obsolete.gd", + "pkg/alnuth/read.g", + "pkg/alnuth/gap/userpref.gi", + "pkg/alnuth/gap/setup.gi", + "pkg/alnuth/gap/pari.gi", + "pkg/alnuth/gap/factors.gi", + "pkg/alnuth/gap/matfield.gi", + "pkg/alnuth/gap/polfield.gi", + "pkg/alnuth/gap/field.gi", + "pkg/alnuth/gap/unithom.gi", + "pkg/alnuth/gap/matunits.gi", + "pkg/alnuth/gap/rels.gi", + "pkg/alnuth/gap/present.gi", + "pkg/alnuth/gap/isom.gi", + "pkg/alnuth/gap/rationals.gi", + "pkg/alnuth/exam/unimod.gi", + "pkg/alnuth/exam/rationals.gi", + "pkg/alnuth/exam/fields.gi", + "pkg/polycyclic/read.g", + "pkg/polycyclic/gap/matrix/rowbases.gi", + "pkg/polycyclic/gap/matrix/latbases.gi", + "pkg/polycyclic/gap/matrix/lattices.gi", + "pkg/polycyclic/gap/matrix/modules.gi", + "pkg/polycyclic/gap/matrix/triangle.gi", + "pkg/polycyclic/gap/matrix/hnf.gi", + "pkg/polycyclic/gap/basic/collect.gi", + "pkg/polycyclic/gap/basic/colftl.gi", + "pkg/polycyclic/gap/basic/colcom.gi", + "pkg/polycyclic/gap/basic/coldt.gi", + "pkg/polycyclic/gap/basic/colsave.gi", + "pkg/polycyclic/gap/basic/pcpelms.gi", + "pkg/polycyclic/gap/basic/pcppcps.gi", + "pkg/polycyclic/gap/basic/pcpgrps.gi", + "pkg/polycyclic/gap/basic/pcppara.gi", + "pkg/polycyclic/gap/basic/pcpexpo.gi", + "pkg/polycyclic/gap/basic/pcpsers.gi", + "pkg/polycyclic/gap/basic/grphoms.gi", + "pkg/polycyclic/gap/basic/pcpfact.gi", + "pkg/polycyclic/gap/basic/chngpcp.gi", + "pkg/polycyclic/gap/basic/convert.gi", + "pkg/polycyclic/gap/basic/orbstab.gi", + "pkg/polycyclic/gap/basic/construct.gi", + "pkg/polycyclic/gap/cohom/cohom.gi", + "pkg/polycyclic/gap/cohom/addgrp.gi", + "pkg/polycyclic/gap/cohom/general.gi", + "pkg/polycyclic/gap/cohom/solabel.gi", + "pkg/polycyclic/gap/cohom/solcohom.gi", + "pkg/polycyclic/gap/cohom/twocohom.gi", + "pkg/polycyclic/gap/cohom/intcohom.gi", + "pkg/polycyclic/gap/cohom/onecohom.gi", + "pkg/polycyclic/gap/cohom/grpext.gi", + "pkg/polycyclic/gap/cohom/grpcom.gi", + "pkg/polycyclic/gap/cohom/norcom.gi", + "pkg/polycyclic/gap/action/extend.gi", + "pkg/polycyclic/gap/action/basepcgs.gi", + "pkg/polycyclic/gap/action/freegens.gi", + "pkg/polycyclic/gap/action/dixon.gi", + "pkg/polycyclic/gap/action/kernels.gi", + "pkg/polycyclic/gap/action/orbstab.gi", + "pkg/polycyclic/gap/action/orbnorm.gi", + "pkg/polycyclic/gap/pcpgrp/general.gi", + "pkg/polycyclic/gap/pcpgrp/inters.gi", + "pkg/polycyclic/gap/pcpgrp/grpinva.gi", + "pkg/polycyclic/gap/pcpgrp/torsion.gi", + "pkg/polycyclic/gap/pcpgrp/maxsub.gi", + "pkg/polycyclic/gap/pcpgrp/findex.gi", + "pkg/polycyclic/gap/pcpgrp/nindex.gi", + "pkg/polycyclic/gap/pcpgrp/nilpot.gi", + "pkg/polycyclic/gap/pcpgrp/polyz.gi", + "pkg/polycyclic/gap/pcpgrp/pcpattr.gi", + "pkg/polycyclic/gap/pcpgrp/wreath.gi", + "pkg/polycyclic/gap/pcpgrp/fitting.gi", + "pkg/polycyclic/gap/pcpgrp/centcon.gi", + "pkg/polycyclic/gap/pcpgrp/normcon.gi", + "pkg/polycyclic/gap/pcpgrp/schur.gi", + "pkg/polycyclic/gap/pcpgrp/tensor.gi", + "pkg/polycyclic/gap/matrep/matrep.gi", + "pkg/polycyclic/gap/matrep/affine.gi", + "pkg/polycyclic/gap/matrep/unitri.gi", + "pkg/polycyclic/gap/exam/pcplib.gi", + "pkg/polycyclic/gap/exam/matlib.gi", + "pkg/polycyclic/gap/exam/nqlib.gi", + "pkg/polycyclic/gap/exam/generic.gi", + "pkg/polycyclic/gap/exam/bgnilp.gi", + "pkg/polycyclic/gap/exam/metacyc.gi", + "pkg/polycyclic/gap/exam/metagrp.gi", + "pkg/polycyclic/gap/cover/const/bas.gi", + "pkg/polycyclic/gap/cover/const/orb.gi", + "pkg/polycyclic/gap/cover/const/aut.gi", + "pkg/polycyclic/gap/cover/const/com.gi", + "pkg/polycyclic/gap/cover/const/cov.gi", + "pkg/crisp/init.g", + "pkg/crisp/lib/classes.gd", + "pkg/crisp/lib/grpclass.gd", + "pkg/crisp/lib/fitting.gd", + "pkg/crisp/lib/schunck.gd", + "pkg/crisp/lib/form.gd", + "pkg/crisp/lib/projector.gd", + "pkg/crisp/lib/injector.gd", + "pkg/crisp/lib/normpro.gd", + "pkg/crisp/lib/solveeq.gd", + "pkg/crisp/lib/compl.gd", + "pkg/crisp/lib/radical.gd", + "pkg/crisp/lib/residual.gd", + "pkg/crisp/lib/util.gd", + "pkg/crisp/lib/samples.gd", + "pkg/crisp/lib/socle.gd", + "pkg/crisp/read.g", + "pkg/crisp/lib/classes.gi", + "pkg/crisp/lib/grpclass.gi", + "pkg/crisp/lib/fitting.gi", + "pkg/crisp/lib/schunck.gi", + "pkg/crisp/lib/form.gi", + "pkg/crisp/lib/projector.gi", + "pkg/crisp/lib/injector.gi", + "pkg/crisp/lib/normpro.gi", + "pkg/crisp/lib/solveeq.gi", + "pkg/crisp/lib/compl.gi", + "pkg/crisp/lib/radical.gi", + "pkg/crisp/lib/residual.gi", + "pkg/crisp/lib/util.gi", + "pkg/crisp/lib/samples.gi", + "pkg/crisp/lib/socle.gi", + "pkg/factint/init.g", + "pkg/factint/lib/factint.gd", + "pkg/factint/read.g", + "pkg/factint/tables/3k2k.g", + "pkg/factint/tables/akbk.g", + "pkg/factint/tables/factorial.g", + "pkg/factint/tables/fibo.g", + "pkg/factint/tables/primorial.g", + "pkg/factint/lib/general.gi", + "pkg/factint/lib/pminus1.gi", + "pkg/factint/lib/pplus1.gi", + "pkg/factint/lib/ecm.gi", + "pkg/factint/lib/cfrac.gi", + "pkg/factint/lib/mpqs.gi", + "pkg/forms/init.g", + "pkg/forms/lib/forms.gd", + "pkg/forms/lib/recognition.gd", + "pkg/forms/lib/conformal.gd", + "pkg/forms/read.g", + "pkg/forms/lib/forms.gi", + "pkg/forms/lib/recognition.gi", + "pkg/forms/lib/classic.gi", + "pkg/forms/lib/recognition_new.gi", + "pkg/forms/lib/conformal.gi", + "pkg/orb/init.g", + "pkg/orb/gap/homwdata.gd", + "pkg/orb/gap/avltree.gd", + "pkg/orb/gap/hash.gd", + "pkg/orb/gap/cache.gd", + "pkg/orb/gap/orbits.gd", + "pkg/orb/gap/search.gd", + "pkg/orb/gap/bysuborbit.gd", + "pkg/orb/read.g", + "pkg/orb/gap/homwdata.gi", + "pkg/orb/gap/avltree.gi", + "pkg/orb/gap/hash.gi", + "pkg/orb/gap/cache.gi", + "pkg/orb/gap/orbits.gi", + "pkg/orb/gap/search.gi", + "pkg/orb/gap/bysuborbit.gi", + "pkg/utils/init.g", + "pkg/utils/lib/start.gd", + "pkg/utils/lib/files.gd", + "pkg/utils/lib/groups.gd", + "pkg/utils/lib/iterator.gd", + "pkg/utils/lib/latex.gd", + "pkg/utils/lib/lcset.gd", + "pkg/utils/lib/lists.gd", + "pkg/utils/lib/magma.gd", + "pkg/utils/lib/maps.gd", + "pkg/utils/lib/matrix.gd", + "pkg/utils/lib/number.gd", + "pkg/utils/lib/print.gd", + "pkg/utils/lib/record.gd", + "pkg/utils/lib/string.gd", + "pkg/utils/lib/gslp.gd", + "pkg/utils/lib/download.gd", + "pkg/utils/read.g", + "pkg/utils/lib/files.gi", + "pkg/utils/lib/groups.gi", + "pkg/utils/lib/iterator.gi", + "pkg/utils/lib/latex.gi", + "pkg/utils/lib/lcset.gi", + "pkg/utils/lib/lists.gi", + "pkg/utils/lib/magma.gi", + "pkg/utils/lib/maps.gi", + "pkg/utils/lib/matrix.gi", + "pkg/utils/lib/number.gi", + "pkg/utils/lib/print.gi", + "pkg/utils/lib/record.gi", + "pkg/utils/lib/string.gi", + "pkg/utils/lib/gslp.gi", + "pkg/utils/lib/download.gi", + "pkg/genss/init.g", + "pkg/genss/gap/genss.gd", + "pkg/genss/gap/setwise.gd", + "pkg/genss/read.g", + "pkg/genss/gap/genss.gi", + "pkg/genss/gap/setwise.gi", + "pkg/atlasrep/init.g", + "pkg/atlasrep/gap/userpref.g", + "pkg/atlasrep/gap/bbox.gd", + "pkg/atlasrep/gap/access.gd", + "pkg/atlasrep/gap/scanmtx.gd", + "pkg/atlasrep/gap/scanmtx.gi", + "pkg/atlasrep/gap/types.gd", + "pkg/atlasrep/gap/interfac.gd", + "pkg/atlasrep/gap/mindeg.gd", + "pkg/atlasrep/gap/utils.gd", + "pkg/ctbllib/init.g", + "pkg/ctbllib/gap4/ctadmin.gd", + "pkg/ctbllib/gap4/construc.gd", + "pkg/ctbllib/gap4/ctblothe.gd", + "pkg/ctbllib/dlnames/dlnames.gd", + "pkg/ctbllib/gap4/obsolete.gd", + "pkg/ctbllib/gap4/brdbattrX.gd", + "pkg/ctbllib/gap4/brdbattrX.gi", + "pkg/recog/init.g", + "pkg/recog/gap/base/hack.g", + "pkg/recog/gap/base/methods.gd", + "pkg/recog/gap/base/methsel.gd", + "pkg/recog/gap/base/recognition.gd", + "pkg/recog/gap/base/kernel.gd", + "pkg/recog/gap/base/projective.gd", + "pkg/recog/gap/matrix/ppd.gd", + "pkg/recog/gap/matrix/classical.gd", + "pkg/recog/gap/projective/almostsimple.gd", + "pkg/recog/gap/projective/findnormal.gd", + "pkg/recog/gap/projective/AnSnOnFDPM.gd", + "pkg/spinsym/init.g", + "pkg/spinsym/gap/mtx.gd", + "pkg/spinsym/gap/fus.gd", + "pkg/spinsym/gap/young.gd", + "pkg/standardff/init.g", + "pkg/standardff/lib/Util.gd", + "pkg/standardff/lib/IsIrred.gd", + "pkg/standardff/lib/StandardFF.gd", + "pkg/standardff/lib/StandardCyc.gd", + "pkg/tomlib/init.g", + "pkg/tomlib/gap/tmadmin.tmd", + "pkg/tomlib/gap/stdgen.gd", + "pkg/atlasrep/read.g", + "pkg/atlasrep/gap/bbox.gi", + "pkg/atlasrep/gap/access.gi", + "pkg/atlasrep/gap/types.gi", + "pkg/atlasrep/gap/interfac.gi", + "pkg/atlasrep/gap/mindeg.gi", + "pkg/atlasrep/gap/utlmrkup.g", + "pkg/atlasrep/gap/utils.gi", + "pkg/atlasrep/gap/test.g", + "pkg/atlasrep/gap/json.g", + "pkg/atlasrep/gap/obsolete.gd", + "pkg/atlasrep/gap/obsolete.gi", + "pkg/ctbllib/read.g", + "pkg/ctbllib/gap4/ctadmin.gi", + "pkg/ctbllib/gap4/ctprimar.g", + "pkg/ctbllib/data/firstnames.json", + "pkg/ctbllib/data/othernames.json", + "pkg/ctbllib/data/fusionsources.json", + "pkg/ctbllib/data/extinfo.json", + "pkg/ctbllib/data/ctgeneri.tbl", + "pkg/ctbllib/data/version", + "pkg/ctbllib/data/namerepl.json", + "pkg/ctbllib/gap4/construc.gi", + "pkg/ctbllib/gap4/ctblothe.gi", + "pkg/ctbllib/gap4/test.g", + "pkg/ctbllib/dlnames/dlnames.gi", + "pkg/ctbllib/gap4/ctbltoct.g", + "pkg/ctbllib/gap4/ctdbattr.g", + "pkg/ctbllib/gap4/od.g", + "pkg/ctbllib/data/odresults.json", + "pkg/ctbllib/gap4/atlasstr.g", + "pkg/ctbllib/gap4/atlasirr.g", + "pkg/recog/read.g", + "pkg/recog/gap/base/methods.gi", + "pkg/recog/gap/base/methsel.gi", + "pkg/recog/gap/base/recognition.gi", + "pkg/recog/gap/base/kernel.gi", + "pkg/recog/gap/base/projective.gi", + "pkg/recog/gap/utils.gi", + "pkg/recog/gap/generic/TrivialGroup.gi", + "pkg/recog/gap/generic/FewGensAbelian.gi", + "pkg/recog/gap/generic/KnownNilpotent.gi", + "pkg/recog/gap/perm/giant.gi", + "pkg/recog/gap/perm/largebase.gi", + "pkg/recog/gap/SnAnBB.gi", + "pkg/recog/gap/generic/SnAnUnknownDegree.gi", + "pkg/recog/gap/matrix/matimpr.gi", + "pkg/recog/gap/matrix/blocks.gi", + "pkg/recog/gap/matrix/ppd.gi", + "pkg/recog/gap/matrix/classical.gi", + "pkg/recog/gap/matrix/slconstr.gi", + "pkg/recog/gap/projective/findnormal.gi", + "pkg/recog/gap/projective/c6.gi", + "pkg/recog/gap/projective/tensor.gi", + "pkg/recog/gap/projective/c3c5.gi", + "pkg/recog/gap/projective/d247.gi", + "pkg/recog/gap/projective/almostsimple/threeelorders.gi", + "pkg/recog/gap/projective/almostsimple.gi", + "pkg/recog/gap/projective/almostsimple/lietype.gi", + "pkg/recog/gap/projective/almostsimple/hints.gi", + "pkg/recog/gap/projective/classicalnatural.gi", + "pkg/recog/gap/projective/sl2_natural.gi", + "pkg/recog/gap/projective/sl.gi", + "pkg/recog/gap/projective/AnSnOnFDPM.gi", + "pkg/recog/gap/perm.gi", + "pkg/recog/gap/matrix.gi", + "pkg/recog/gap/projective.gi", + "pkg/spinsym/read.g", + "pkg/spinsym/gap/mtx.gi", + "pkg/spinsym/gap/fus.gi", + "pkg/spinsym/gap/young.gi", + "pkg/standardff/read.g", + "pkg/standardff/lib/Util.gi", + "pkg/standardff/lib/IsIrred.gi", + "pkg/standardff/lib/StandardFF.gi", + "pkg/standardff/lib/StandardCyc.gi", + "pkg/standardff/lib/CANFACT.g", + "pkg/standardff/lib/TestFuncs.g", + "pkg/tomlib/read.g", + "pkg/tomlib/gap/tmstdrd.tom", + "pkg/tomlib/gap/tmadmin.tmi", + "pkg/tomlib/gap/stdgen.gi", + "pkg/atlasrep/gap/ctbllib_only.g", + "pkg/ctbllib/gap4/atlasrep_only.g", + "pkg/ctbllib/gap4/tomlib_only.g", + "pkg/ctbllib/data/tom_tbl.json", + "pkg/ctbllib/gap4/spinsym_only.g", + "pkg/ctbllib/data/grp_atlas.json", + "pkg/ctbllib/data/attr_nccl.json", + "pkg/ctbllib/data/grp_small.json", + "pkg/ctbllib/data/grp_tom.json", + "pkg/ctbllib/data/grp_trans.json", + "pkg/ctbllib/data/grp_prim.json", + "pkg/ctbllib/data/grp_perf.json", + "pkg/fga/init.g", + "pkg/fga/lib/util.gd", + "pkg/fga/lib/Iterated.gd", + "pkg/fga/lib/Autom.gd", + "pkg/fga/lib/FreeGrps.gd", + "pkg/fga/lib/ReprAct.gd", + "pkg/fga/lib/Normal.gd", + "pkg/fga/lib/ExtAutom.gd", + "pkg/fga/lib/Hom.gd", + "pkg/fga/lib/AutGrp.gd", + "pkg/fga/lib/Intsect.gd", + "pkg/fga/lib/Whitehd.gd", + "pkg/fga/read.g", + "pkg/fga/lib/util.gi", + "pkg/fga/lib/Iterated.gi", + "pkg/fga/lib/Autom.gi", + "pkg/fga/lib/FreeGrps.gi", + "pkg/fga/lib/ReprAct.gi", + "pkg/fga/lib/Normal.gi", + "pkg/fga/lib/Central.gi", + "pkg/fga/lib/Index.gi", + "pkg/fga/lib/ExtAutom.gi", + "pkg/fga/lib/Hom.gi", + "pkg/fga/lib/AutGrp.gi", + "pkg/fga/lib/Intsect.gi", + "pkg/fga/lib/ReprActT.gi", + "pkg/fga/lib/Whitehd.gi", + "pkg/irredsol/init.g", + "pkg/irredsol/lib/util.g", + "pkg/irredsol/lib/util.gd", + "pkg/irredsol/lib/matmeths.gd", + "pkg/irredsol/lib/loading.gd", + "pkg/irredsol/lib/loadfp.gd", + "pkg/irredsol/lib/access.gd", + "pkg/irredsol/lib/iterators.gd", + "pkg/irredsol/lib/recognize.gd", + "pkg/irredsol/lib/primitive.gd", + "pkg/irredsol/lib/recognizeprim.gd", + "pkg/irredsol/lib/obsolete.gd", + "pkg/irredsol/read.g", + "pkg/irredsol/lib/matmeths.gi", + "pkg/irredsol/lib/loading.gi", + "pkg/irredsol/lib/loadfp.gi", + "pkg/irredsol/lib/access.gi", + "pkg/irredsol/lib/iterators.gi", + "pkg/irredsol/lib/recognize.gi", + "pkg/irredsol/lib/primitive.gi", + "pkg/irredsol/lib/recognizeprim.gi", + "pkg/irredsol/lib/util.gi", + "pkg/irredsol/lib/obsolete.gi", + "pkg/sophus/init.g", + "pkg/sophus/gap/sophus.gd", + "pkg/sophus/read.g", + "pkg/sophus/gap/general.gi", + "pkg/sophus/gap/lienp.gi", + "pkg/sophus/gap/liesct.gi", + "pkg/sophus/gap/liecover.gi", + "pkg/sophus/gap/nicestab.gi", + "pkg/sophus/gap/lieautoops.gi", + "pkg/sophus/gap/initauts.gi", + "pkg/sophus/gap/lieautgrp.gi", + "pkg/sophus/gap/allowable.gi", + "pkg/sophus/gap/descendant.gi", + "pkg/sophus/gap/lieisom.gi", + "pkg/sophus/gap/io.gi", + "pkg/laguna/init.g", + "pkg/laguna/lib/laguna.gd", + "pkg/laguna/lib/laguna.g", + "pkg/laguna/read.g", + "pkg/laguna/lib/laguna.gi", + "pkg/autodoc/init.g", + "pkg/autodoc/gap/DocumentationTree.gd", + "pkg/autodoc/gap/Parser.gd", + "pkg/autodoc/gap/AutoDocMainFunction.gd", + "pkg/autodoc/gap/ToolFunctions.gd", + "pkg/autodoc/gap/Magic.gd", + "pkg/autodoc/gap/Markdown.gd", + "pkg/autodoc/read.g", + "pkg/autodoc/gap/ToolFunctions.gi", + "pkg/autodoc/gap/DocumentationTree.gi", + "pkg/autodoc/gap/Parser.gi", + "pkg/autodoc/gap/AutoDocMainFunction.gi", + "pkg/autodoc/gap/Magic.gi", + "pkg/autodoc/gap/Markdown.gi", + "pkg/packagemanager/init.g", + "pkg/packagemanager/gap/PackageManager.gd", + "pkg/packagemanager/gap/archive.gd", + "pkg/packagemanager/gap/compile.gd", + "pkg/packagemanager/gap/directories.gd", + "pkg/packagemanager/gap/distro.gd", + "pkg/packagemanager/gap/doc.gd", + "pkg/packagemanager/gap/download.gd", + "pkg/packagemanager/gap/git.gd", + "pkg/packagemanager/gap/hg.gd", + "pkg/packagemanager/gap/interactive.gd", + "pkg/packagemanager/gap/packageinfo.gd", + "pkg/packagemanager/read.g", + "pkg/packagemanager/gap/PackageManager.gi", + "pkg/packagemanager/gap/archive.gi", + "pkg/packagemanager/gap/compile.gi", + "pkg/packagemanager/gap/directories.gi", + "pkg/packagemanager/gap/distro.gi", + "pkg/packagemanager/gap/doc.gi", + "pkg/packagemanager/gap/download.gi", + "pkg/packagemanager/gap/git.gi", + "pkg/packagemanager/gap/hg.gi", + "pkg/packagemanager/gap/interactive.gi", + "pkg/packagemanager/gap/packageinfo.gi", + "pkg/radiroot/init.g", + "pkg/radiroot/lib/Radicals.gd", + "pkg/radiroot/lib/SplittField.gd", + "pkg/radiroot/lib/Manipulations.gd", + "pkg/radiroot/lib/Strings.gd", + "pkg/radiroot/lib/Maple.gd", + "pkg/radiroot/read.g", + "pkg/radiroot/lib/Radicals.gi", + "pkg/radiroot/lib/SplittField.gi", + "pkg/radiroot/lib/Manipulations.gi", + "pkg/radiroot/lib/Strings.gi", + "pkg/radiroot/lib/Maple.gi", + "pkg/aclib/init.g", + "pkg/aclib/gap/groups.gd", + "pkg/cryst/init.g", + "pkg/cryst/gap/common.gd", + "pkg/cryst/gap/cryst.gd", + "pkg/cryst/gap/hom.gd", + "pkg/cryst/gap/wyckoff.gd", + "pkg/cryst/gap/zass.gd", + "pkg/cryst/gap/max.gd", + "pkg/cryst/gap/color.gd", + "pkg/cryst/gap/equiv.gd", + "pkg/cryst/grp/spacegrp.gd", + "pkg/crystcat/init.g", + "pkg/crystcat/lib/crystcat.gd", + "pkg/polenta/init.g", + "pkg/polenta/lib/finite.gd", + "pkg/polenta/lib/info.gd", + "pkg/polenta/lib/basic.gd", + "pkg/polenta/exam/test.gd", + "pkg/polenta/lib/cpcs.gd", + "pkg/polenta/lib/present.gd", + "pkg/polenta/lib/solvable.gd", + "pkg/polenta/lib/series.gd", + "pkg/polenta/lib/subgroups.gd", + "pkg/polenta/lib/ispolyz.gd", + "pkg/aclib/read.g", + "pkg/aclib/gap/matgrp3.gi", + "pkg/aclib/gap/matgrp4.gi", + "pkg/aclib/gap/matgrp.gi", + "pkg/aclib/gap/pcpgrp3.gi", + "pkg/aclib/gap/pcpgrp4.gi", + "pkg/aclib/gap/pcpgrp.gi", + "pkg/aclib/gap/betti.gi", + "pkg/aclib/gap/union.gi", + "pkg/aclib/gap/extend.gi", + "pkg/aclib/gap/crystgrp.gi", + "pkg/cryst/read.g", + "pkg/cryst/gap/common.gi", + "pkg/cryst/gap/hom.gi", + "pkg/cryst/gap/cryst.gi", + "pkg/cryst/gap/cryst2.gi", + "pkg/cryst/gap/fpgrp.gi", + "pkg/cryst/gap/zass.gi", + "pkg/cryst/gap/max.gi", + "pkg/cryst/gap/wyckoff.gi", + "pkg/cryst/gap/color.gi", + "pkg/cryst/gap/noxgap.gi", + "pkg/cryst/gap/pcpgrp.gi", + "pkg/cryst/gap/orbstab.gi", + "pkg/cryst/gap/equiv.gi", + "pkg/cryst/grp/spacegrp.grp", + "pkg/cryst/grp/spacegrp.gi", + "pkg/crystcat/read.g", + "pkg/crystcat/grp/crystcat.grp", + "pkg/crystcat/lib/crystcat.gi", + "pkg/crystcat/lib/normalizer.gi", + "pkg/polenta/read.g", + "pkg/polenta/lib/finite.gi", + "pkg/polenta/lib/basic.gi", + "pkg/polenta/lib/unipo.gi", + "pkg/polenta/lib/series.gi", + "pkg/polenta/lib/semi.gi", + "pkg/polenta/lib/ispoly.gi", + "pkg/polenta/lib/cpcs.gi", + "pkg/polenta/lib/present.gi", + "pkg/polenta/lib/isom.gi", + "pkg/polenta/lib/solvable.gi", + "pkg/polenta/exam/exam.gi", + "pkg/polenta/exam/test.gi", + "pkg/polenta/lib/subgroups.gi", + "pkg/polenta/lib/ispolyz.gi", + "pkg/resclasses/init.g", + "pkg/resclasses/lib/general.gd", + "pkg/resclasses/lib/z_pi.gd", + "pkg/resclasses/lib/resclass.gd", + "pkg/resclasses/lib/fixedrep.gd", + "pkg/resclasses/read.g", + "pkg/resclasses/lib/general.gi", + "pkg/resclasses/lib/resclaux.g", + "pkg/resclasses/lib/z_pi.gi", + "pkg/resclasses/lib/resclass.gi", + "pkg/resclasses/lib/fixedrep.gi", + "lib/obsolete.gi", + "pkg/4ti2interface/doc/manual.six", + "pkg/ace/doc/manual.six", + "pkg/aclib/doc/manual.six", + "pkg/agt/doc/manual.six", + "pkg/alco/doc/manual.six", + "pkg/alnuth/doc/manual.six", + "pkg/anupq/doc/manual.six", + "pkg/atlasrep/doc/manual.six", + "pkg/autodoc/doc/manual.six", + "pkg/automata/doc/manual.six", + "pkg/automgrp/doc/manual.six", + "pkg/autpgrp/doc/manual.six", + "pkg/browse/doc/manual.six", + "pkg/cap/doc/manual.six", + "pkg/caratinterface/doc/manual.six", + "pkg/cddinterface/doc/manual.six", + "pkg/circle/doc/manual.six", + "pkg/classicalmaximals/doc/manual.six", + "pkg/classicpres/doc/manual.six", + "pkg/cohomolo/doc/manual.six", + "pkg/congruence/doc/manual.six", + "pkg/corefreesub/doc/manual.six", + "pkg/corelg/doc/manual.six", + "pkg/crime/doc/manual.six", + "pkg/crisp/doc/manual.six", + "pkg/crypting/doc/manual.six", + "pkg/cryst/doc/manual.six", + "pkg/crystcat/doc/manual.six", + "pkg/ctbllib/doc/manual.six", + "pkg/ctbllib/doc2/manual.six", + "pkg/cubefree/doc/manual.six", + "pkg/curlinterface/doc/manual.six", + "pkg/cvec/doc/manual.six", + "pkg/datastructures/doc/manual.six", + "pkg/deepthought/doc/manual.six", + "pkg/design/doc/manual.six", + "pkg/difsets/doc/manual.six", + "pkg/digraphs/doc/manual.six", + "pkg/edim/doc/manual.six", + "pkg/example/doc/manual.six", + "pkg/examplesforhomalg/doc/manual.six", + "pkg/factint/doc/manual.six", + "pkg/ferret/doc/manual.six", + "pkg/fga/doc/manual.six", + "pkg/fining/doc/manual.six", + "pkg/float/doc/manual.six", + "pkg/format/doc/manual.six", + "pkg/forms/doc/manual.six", + "pkg/fplsa/doc/manual.six", + "pkg/fr/doc/manual.six", + "pkg/francy/doc/manual.six", + "pkg/fwtree/doc/manual.six", + "pkg/gapdoc/doc/manual.six", + "pkg/gapdoc/example/manual.six", + "pkg/gauss/doc/manual.six", + "pkg/gaussforhomalg/doc/manual.six", + "pkg/gbnp/doc/manual.six", + "pkg/generalizedmorphismsforcap/doc/manual.six", + "pkg/genss/doc/manual.six", + "pkg/gradedmodules/doc/manual.six", + "pkg/gradedringforhomalg/doc/manual.six", + "pkg/grape/doc/manual.six", + "pkg/groupoids/doc/manual.six", + "pkg/grpconst/doc/manual.six", + "pkg/guarana/doc/manual.six", + "pkg/guava/doc/manual.six", + "pkg/hap/doc/manual.six", + "pkg/hapcryst/doc/manual.six", + "pkg/hecke/doc/manual.six", + "pkg/help/doc/manual.six", + "pkg/homalg/doc/manual.six", + "pkg/homalgtocas/doc/manual.six", + "pkg/ibnp/doc/manual.six", + "pkg/idrel/doc/manual.six", + "pkg/images/doc/manual.six", + "pkg/inducereduce/doc/manual.six", + "pkg/intpic/doc/manual.six", + "pkg/io/doc/manual.six", + "pkg/io_forhomalg/doc/manual.six", + "pkg/irredsol/doc/manual.six", + "pkg/itc/doc/manual.six", + "pkg/json/doc/manual.six", + "pkg/jupyterkernel/doc/manual.six", + "pkg/jupyterviz/doc/manual.six", + "pkg/kan/doc/manual.six", + "pkg/kbmag/doc/manual.six", + "pkg/laguna/doc/manual.six", + "pkg/liealgdb/doc/manual.six", + "pkg/liepring/doc/manual.six", + "pkg/liering/doc/manual.six", + "pkg/linearalgebraforcap/doc/manual.six", + "pkg/lins/doc/manual.six", + "pkg/localizeringforhomalg/doc/manual.six", + "pkg/localnr/doc/manual.six", + "pkg/loops/doc/manual.six", + "pkg/lpres/doc/manual.six", + "pkg/majoranaalgebras/doc/manual.six", + "pkg/mapclass/doc/manual.six", + "pkg/matgrp/doc/manual.six", + "pkg/matricesforhomalg/doc/manual.six", + "pkg/modisom/doc/manual.six", + "pkg/modulargroup/doc/manual.six", + "pkg/modulepresentationsforcap/doc/manual.six", + "pkg/modules/doc/manual.six", + "pkg/monoidalcategories/doc/manual.six", + "pkg/nconvex/doc/manual.six", + "pkg/nilmat/doc/manual.six", + "pkg/nock/doc/manual.six", + "pkg/nofoma/doc/manual.six", + "pkg/normalizinterface/doc/manual.six", + "pkg/nq/doc/manual.six", + "pkg/numericalsgps/doc/manual.six", + "pkg/openmath/doc/manual.six", + "pkg/orb/doc/manual.six", + "pkg/origami/doc/manual.six", + "pkg/packagemaker/doc/manual.six", + "pkg/packagemanager/doc/manual.six", + "pkg/patternclass/doc/manual.six", + "pkg/permut/doc/manual.six", + "pkg/polenta/doc/manual.six", + "pkg/polycyclic/doc/manual.six", + "pkg/polymaking/doc/manual.six", + "pkg/primgrp/doc/manual.six", + "pkg/profiling/doc/manual.six", + "pkg/qdistrnd/doc/manual.six", + "pkg/qpa/doc/manual.six", + "pkg/quagroup/doc/manual.six", + "pkg/radiroot/doc/manual.six", + "pkg/rcwa/doc/manual.six", + "pkg/rds/doc/manual.six", + "pkg/recog/doc/manual.six", + "pkg/repndecomp/doc/manual.six", + "pkg/repsn/doc/manual.six", + "pkg/resclasses/doc/manual.six", + "pkg/ringsforhomalg/doc/manual.six", + "pkg/sco/doc/manual.six", + "pkg/scscp/doc/manual.six", + "pkg/semigroups/doc/manual.six", + "pkg/sglppow/doc/manual.six", + "pkg/sgpviz/doc/manual.six", + "pkg/simpcomp/doc/manual.six", + "pkg/singular/doc/manual.six", + "pkg/sl2reps/doc/manual.six", + "pkg/sla/doc/manual.six", + "pkg/smallantimagmas/doc/manual.six", + "pkg/smallclassnr/doc/manual.six", + "pkg/smallgrp/doc/manual.six", + "pkg/smallsemi/doc/manual.six", + "pkg/sonata/doc/ref/manual.six", + "pkg/sonata/doc/tut/manual.six", + "pkg/sophus/doc/manual.six", + "pkg/sotgrps/doc/manual.six", + "pkg/spinsym/doc/manual.six", + "pkg/standardff/doc/manual.six", + "pkg/symbcompcc/doc/manual.six", + "pkg/thelma/doc/manual.six", + "pkg/tomlib/doc/manual.six", + "pkg/toolsforhomalg/doc/manual.six", + "pkg/toric/doc/manual.six", + "pkg/transgrp/doc/manual.six", + "pkg/twistedconjugacy/doc/manual.six", + "pkg/typeset/doc/manual.six", + "pkg/ugaly/doc/manual.six", + "pkg/unipot/doc/manual.six", + "pkg/unitlib/doc/manual.six", + "pkg/utils/doc/manual.six", + "pkg/uuid/doc/manual.six", + "pkg/walrus/doc/manual.six", + "pkg/wedderga/doc/manual.six", + "pkg/wpe/doc/manual.six", + "pkg/xgap/doc/manual.six", + "pkg/xmod/doc/manual.six", + "pkg/xmodalg/doc/manual.six", + "pkg/yangbaxter/doc/manual.six", + "pkg/zeromqinterface/doc/manual.six" +] diff --git a/etc/emscripten/web-template/gap-fs.js b/etc/emscripten/web-template/gap-fs.js index f3a1467d42..ca8ea4f23d 100644 --- a/etc/emscripten/web-template/gap-fs.js +++ b/etc/emscripten/web-template/gap-fs.js @@ -1,3 +1,29 @@ +// Instrument fetch and XMLHttpRequest so the page can collect the list of +// URLs the worker actually requests, for rebuilding startup_manifest.json +// without scraping the browser network panel. Each unique URL is posted +// to the main thread as { type: "gap-fetched", url: ... }. +(function instrumentFetches() { + const seen = new Set(); + const report = (raw) => { + if (typeof raw !== "string") return; + if (seen.has(raw)) return; + seen.add(raw); + self.postMessage({ type: "gap-fetched", url: raw }); + }; + + const origFetch = self.fetch; + self.fetch = function(input, init) { + report(typeof input === "string" ? input : input && input.url); + return origFetch.apply(this, arguments); + }; + + const origOpen = XMLHttpRequest.prototype.open; + XMLHttpRequest.prototype.open = function(method, url) { + report(url); + return origOpen.apply(this, arguments); + }; +})(); + self.Module = self.Module || {}; self.Module.preRun = self.Module.preRun || []; @@ -43,8 +69,12 @@ self.Module.preRun.push(function() { if (p.startsWith('/')) p = p.substring(1); startupSet.add(p); }); + } else { + console.info("startup_manifest.json not present; falling back to fully lazy loading"); } - } catch (e) {} + } catch (e) { + console.warn("Failed to load startup_manifest.json:", e); + } var fetchPromises = fileList.map(async function(appPath) { var fetchRelativePath = appPath.split('/').map(encodeURIComponent).join('/'); @@ -58,16 +88,15 @@ self.Module.preRun.push(function() { FS.stat(idbfsPath); FS.writeFile(finalAppPath, FS.readFile(idbfsPath)); } catch (e) { - try { - const response = await fetch(fetchPath); - if (response.ok) { - const buffer = await response.arrayBuffer(); - const data = new Uint8Array(buffer); - FS.writeFile(finalAppPath, data); - FS.writeFile(idbfsPath, data); - needsSave = true; - } - } catch (fetchErr) {} + const response = await fetch(fetchPath); + if (!response.ok) { + throw new Error("Failed to fetch startup file " + fetchPath + ": " + response.status); + } + const buffer = await response.arrayBuffer(); + const data = new Uint8Array(buffer); + FS.writeFile(finalAppPath, data); + FS.writeFile(idbfsPath, data); + needsSave = true; } } else { var parts = appPath.split('/'); diff --git a/etc/emscripten/web-template/index.html b/etc/emscripten/web-template/index.html index b51df45fb8..d5f1bec759 100755 --- a/etc/emscripten/web-template/index.html +++ b/etc/emscripten/web-template/index.html @@ -1,22 +1,185 @@ - + + - gap-wasm + + + GAP in the browser + -

+
+

GAP in the browser

+

+ A WebAssembly build of GAP + running entirely in your browser — useful for trying things out + without installing. Not all packages work, working memory is + capped, and performance is reduced compared to a native build. + For real work, install GAP from + www.gap-system.org. +

+
+ +
+ What is this? · Licensing +

+ GAP is a system for + computational discrete algebra, with particular emphasis on + computational group theory. This page is a self-contained + WebAssembly build, served as a static site and run inside a + Web Worker; you interact with it through an + xterm-pty + terminal in the page below. +

+

+ To get started, try 1+1;, + Factorial(20);, or SymmetricGroup(5);. + The full GAP + manuals apply, with two caveats: some packages won't load + (anything that needs a native compiler or system library), and + anything that wants the local filesystem won't work. +

+

+ Files downloaded on first visit are cached in your browser's + IndexedDB, so subsequent visits start much faster. Clear the + site data to reset the cache. +

+

+ GAP is free software, distributed under the + GNU General Public License (version 2 or + later). See the copyright notice for + the full statement. +

+
+ +
+ Loading GAP… The first visit downloads several tens of megabytes; + subsequent visits are cached in your browser and load much faster. +
+ +
+ This page needs SharedArrayBuffer, which is only + available when the page is served with the headers + Cross-Origin-Opener-Policy: same-origin and + Cross-Origin-Embedder-Policy: require-corp. The + bundled service worker handles this on hosts where you can't set + headers (e.g. GitHub Pages); for local hosting use + etc/emscripten/serve.py. +
+ +
+
+
+ + + diff --git a/grp/glzmodmz.gi b/grp/glzmodmz.gi index 9271ea6976..97d5e7ca77 100644 --- a/grp/glzmodmz.gi +++ b/grp/glzmodmz.gi @@ -379,7 +379,7 @@ local oper,n,R,o,nrit, if fp <>fail then # extend presentation bas:=Basis(sub,bas); - RUN_IN_GGMBI:=true; + PushOptions( rec( Run_In_GGMBI:= true ) ); hom:=GroupGeneralMappingByImagesNC(g,fp,gens,GeneratorsOfGroup(fp)); hom:=LiftFactorFpHom(hom,g,SubgroupNC(g,basm),rec( pcgs:=basm, @@ -392,7 +392,7 @@ local oper,n,R,o,nrit, return List(Coefficients(bas,e),Int); end )); - RUN_IN_GGMBI:=false; + PopOptions(); #simplify Image to avoid explosion of generator number fp:=Range(hom); if true then @@ -412,11 +412,9 @@ local oper,n,R,o,nrit, k:=TzPreImagesNewGens(e); k:=List(k,x->j[1][Position(OldGeneratorsOfPresentation(e),x)]); - RUN_IN_GGMBI:=true; hom:=GroupHomomorphismByImagesNC(g,fp, k, - GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + GeneratorsOfGroup(fp) : Run_In_GGMBI:= true ); fi; SetIsomorphismFpGroup(g,hom); diff --git a/grp/perf13.grp b/grp/perf13.grp index 0f9a715bf9..9a66aacec6 100644 --- a/grp/perf13.grp +++ b/grp/perf13.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[96]:=[# 61440.1 [[1,"abcde", diff --git a/grp/perf14.grp b/grp/perf14.grp index eccd748827..fe20d8d587 100644 --- a/grp/perf14.grp +++ b/grp/perf14.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[111]:=[# 86016.1 [[1,"abcd", diff --git a/grp/perf15.grp b/grp/perf15.grp index 3e466c5c5b..96880d1a09 100644 --- a/grp/perf15.grp +++ b/grp/perf15.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[131]:=[# 122880.1 [[1,"abcdef", diff --git a/grp/perf16.grp b/grp/perf16.grp index 31da9f936f..3d74dd9c6e 100644 --- a/grp/perf16.grp +++ b/grp/perf16.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[150]:=[# 172032.1 [[1,"abc", diff --git a/grp/perf17.grp b/grp/perf17.grp index dce726788d..9f569b8930 100644 --- a/grp/perf17.grp +++ b/grp/perf17.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[179]:=[# 245760.1 [[1,"abcde", diff --git a/grp/perf18.grp b/grp/perf18.grp index e142e995b2..66d6548ebd 100644 --- a/grp/perf18.grp +++ b/grp/perf18.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[200]:=[# 344064.1 [[1,"abcd", diff --git a/grp/perf19.grp b/grp/perf19.grp index abcc2320e7..cbe80ff733 100644 --- a/grp/perf19.grp +++ b/grp/perf19.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[210]:=[# 368640.1 [[1,"abcdef", diff --git a/grp/perf20.grp b/grp/perf20.grp index d9fec32164..d14b2567e8 100644 --- a/grp/perf20.grp +++ b/grp/perf20.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[244]:=[# 491520.1 [[1,"abcde", diff --git a/grp/perf21.grp b/grp/perf21.grp index 5488fdc506..0a723692a3 100644 --- a/grp/perf21.grp +++ b/grp/perf21.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[276]:=[# 688128.1 [[1,"abcde", diff --git a/grp/perf22.grp b/grp/perf22.grp index ab14628e3f..873de9394a 100644 --- a/grp/perf22.grp +++ b/grp/perf22.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later number:=[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 7, 1, 1, 1, 1, 3, 1, 1, 1, 7, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 5, 1, 1, 3, 1, 1, 9, 4, 1, 1, diff --git a/grp/perf23.grp b/grp/perf23.grp index b260d3a331..e7cc9f0523 100644 --- a/grp/perf23.grp +++ b/grp/perf23.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[330]:=[# 983040.1 [[1,"abcdef", diff --git a/grp/perf24.grp b/grp/perf24.grp index 672b2f4d84..b48d5514f9 100644 --- a/grp/perf24.grp +++ b/grp/perf24.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[332]:=[# 1008000.1 [[1,"abcdef", diff --git a/grp/perf25.grp b/grp/perf25.grp index 1e51e86fc2..a3967e1db6 100644 --- a/grp/perf25.grp +++ b/grp/perf25.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[355]:=[# 1180980.1 [[1,"abcde", diff --git a/grp/perf26.grp b/grp/perf26.grp index f7486d8e91..7af1e2a545 100644 --- a/grp/perf26.grp +++ b/grp/perf26.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[371]:=[# 1290240.1 [[1,"abcdefg", diff --git a/grp/perf28.grp b/grp/perf28.grp index 69b0382d26..c9f45efb72 100644 --- a/grp/perf28.grp +++ b/grp/perf28.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[382]:=[# 1382400.1 [[1,"abcdefg", diff --git a/grp/perf29.grp b/grp/perf29.grp index fcffbacfd0..dcdc30b9e0 100644 --- a/grp/perf29.grp +++ b/grp/perf29.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[396]:=[# 1474560.1 [[1,"abcdefg", diff --git a/grp/perf30.grp b/grp/perf30.grp index 09144844f8..948a0c1e02 100644 --- a/grp/perf30.grp +++ b/grp/perf30.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[421]:=[# 1749600.1 [[1,"abcdefgh", diff --git a/grp/perf31.grp b/grp/perf31.grp index ca3418d68a..afc2d69797 100644 --- a/grp/perf31.grp +++ b/grp/perf31.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[435]:=[# 1843200.1 [[1,"abcdef", diff --git a/grp/perf32.grp b/grp/perf32.grp index a33d812d03..ee0f128a89 100644 --- a/grp/perf32.grp +++ b/grp/perf32.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[436]:=[# 1843968.1 [[1,"abcdef", diff --git a/grp/perf34.grp b/grp/perf34.grp index e78fe08416..683173f859 100644 --- a/grp/perf34.grp +++ b/grp/perf34.grp @@ -5,7 +5,7 @@ ## This data was computed by Alexander Hulpke ## It is distributed under the artistic license 2.0 ## https://opensource.org/licenses/Artistic-2.0 -## as well as (dual licensing) under GPL 2 +## as well as (dual licensing) under GPL-2.0-or-later PERFGRP[452]:=[# 1975680.1 [[1,"abcd", diff --git a/hpcgap/lib/ffeconway.gi b/hpcgap/lib/ffeconway.gi index ff9d82145e..d148ad64f5 100644 --- a/hpcgap/lib/ffeconway.gi +++ b/hpcgap/lib/ffeconway.gi @@ -80,7 +80,7 @@ FFECONWAY.SetUpConwayStuff := function(p,d) if not IsCheapConwayPolynomial(p,d) then Error("Conway Polynomial ",p,"^",d, - " will need to computed and might be slow\n", "return to continue"); + " will need to be computed and might be slow"); fi; cp := CoefficientsOfUnivariatePolynomial(ConwayPolynomial(p,d)); diff --git a/lib/algebra.gi b/lib/algebra.gi index e8457b37e1..df6d32f75f 100644 --- a/lib/algebra.gi +++ b/lib/algebra.gi @@ -3647,7 +3647,7 @@ InstallMethod( CentralIdempotentsOfAlgebra, until k>Length(ideals); - id:= List( ids, e -> PreImagesRepresentative( hom, e ) ); + id:= List( ids, e -> PreImagesRepresentativeNC( hom, e ) ); # Now we lift the idempotents to the big algebra `A'. The # first idempotent is lifted as follows: diff --git a/lib/algfp.gi b/lib/algfp.gi index c65a8ec796..51adff0b6d 100644 --- a/lib/algfp.gi +++ b/lib/algfp.gi @@ -705,7 +705,7 @@ InstallHandlingByNiceBasis( "IsFpAlgebraElementsSpace", rec( if hom = fail then TryNextMethod(); fi; - return PreImagesRepresentative( hom, r ); + return PreImagesRepresentativeNC( hom, r ); end ) ); diff --git a/lib/alghom.gi b/lib/alghom.gi index 8dc79c6efd..b28b163047 100644 --- a/lib/alghom.gi +++ b/lib/alghom.gi @@ -576,16 +576,29 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . for algebra g.m.b.i. #M PreImagesRepresentative( , ) . . . . . . for algebra g.m.b.i. ## +InstallMethod( PreImagesRepresentativeNC, + "for algebra g.m.b.i., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsAlgebraGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + return PreImagesRepresentativeNC( + AsLeftModuleGeneralMappingByImages(map), elm ); + end ); + InstallMethod( PreImagesRepresentative, "for algebra g.m.b.i., and element", FamRangeEqFamElm, [ IsGeneralMapping and IsAlgebraGeneralMappingByImagesDefaultRep, IsObject ], function( map, elm ) - return PreImagesRepresentative( AsLeftModuleGeneralMappingByImages(map), - elm ); + if not ( elm in Range( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); end ); @@ -902,6 +915,7 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## +#M PreImagesRepresentativeNC( , ) #M PreImagesRepresentative( , ) ## BindGlobal( "PreImagesRepresentativeOperationAlgebraHomomorphism", function( ophom, mat ) @@ -915,12 +929,22 @@ BindGlobal( "PreImagesRepresentativeOperationAlgebraHomomorphism", function( oph return mat; end ); -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for an operation algebra homomorphism, and an element", FamRangeEqFamElm, [ IsOperationAlgebraHomomorphismDefaultRep, IsMatrix ], PreImagesRepresentativeOperationAlgebraHomomorphism ); +InstallMethod( PreImagesRepresentative, + "for an operation algebra homomorphism, and an element", + FamRangeEqFamElm, + [ IsOperationAlgebraHomomorphismDefaultRep, IsMatrix ], + function( ophom, mat ) + if not ( mat in Range( ophom ) ) then + return fail; + fi; + return PreImagesRepresentativeOperationAlgebraHomomorphism( ophom, mat ); +end ); ############################################################################# ## @@ -1076,14 +1100,25 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## +#M PreImagesRepresentativeNC( , ) #M PreImagesRepresentative( , ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for an alg. hom. from f. p. algebra, and an element", FamRangeEqFamElm, [ IsAlgebraHomomorphismFromFpRep, IsMatrix ], PreImagesRepresentativeOperationAlgebraHomomorphism ); +InstallMethod( PreImagesRepresentative, + "for an alg. hom. from f. p. algebra, and an element", + FamRangeEqFamElm, + [ IsAlgebraHomomorphismFromFpRep, IsMatrix ], + function( ophom, mat ); + if not ( mat in Range( ophom ) ) then + return fail; + fi; + return PreImagesRepresentativeOperationAlgebraHomomorphism( ophom, mat ); + end ); ############################################################################# ## diff --git a/lib/alglie.gd b/lib/alglie.gd index 31cc718ee0..7200f28451 100644 --- a/lib/alglie.gd +++ b/lib/alglie.gd @@ -514,6 +514,11 @@ DeclareAttribute( "LieSolvableRadical", IsAlgebra and IsLieAlgebra ); ## Lie algebras. ## Then returns the type of L, i.e., ## a string containing the types of the simple summands of L. +## The field of L must not have characteristic 2 or 3, and the +## Killing form of L must be nondegenerate. +## If L has characteristic 0, the structure constants of L +## must be rational numbers; Lie algebras over arbitrary characteristic +## 0 fields are not supported. ## L:= SimpleLieAlgebra( "E", 8, Rationals );; ## gap> b:= BasisVectors( Basis( L ) );; diff --git a/lib/alglie.gi b/lib/alglie.gi index 322e003d6d..d682f71459 100644 --- a/lib/alglie.gi +++ b/lib/alglie.gi @@ -34,7 +34,7 @@ InstallMethod( LieUpperCentralSeries, # under the natural homomorphism. Add( S, C ); hom:= NaturalHomomorphismByIdeal( L, C ); - C:= PreImages( hom, LieCentre( Range( hom ) ) ); + C:= PreImagesNC( hom, LieCentre( Range( hom ) ) ); #T we would like to get ideals! #T is it possible to teach the hom. that the preimage of an ideal is an ideal? @@ -1706,7 +1706,7 @@ InstallMethod( LieSolvableRadical, quo:= ImagesSource( hom ); r1:= LieSolvableRadical( quo ); B:= BasisVectors( Basis( r1 ) ); - B:= List( B, x -> PreImagesRepresentative( hom, x ) ); + B:= List( B, x -> PreImagesRepresentativeNC( hom, x ) ); Append( B, BasisVectors( Basis( n ) ) ); fi; @@ -2092,7 +2092,7 @@ InstallMethod( DirectSumDecomposition, SetRadicalOfAlgebra( Q, Subalgebra( Q, [ Zero( Q ) ] ) ); id:= List( CentralIdempotentsOfAlgebra( Q ), - x->PreImagesRepresentative(hom,x)); + x->PreImagesRepresentativeNC(hom,x)); # Now we lift the idempotents to the big algebra `A'. The # first idempotent is lifted as follows: @@ -4017,9 +4017,10 @@ InstallMethod( ImagesRepresentative, ########################################################################### ## +#M PreImagesRepresentativeNC( f, x ) #M PreImagesRepresentative( f, x ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for Fp to SCA mapping, and element", FamRangeEqFamElm, [ IsFptoSCAMorphism, IsSCAlgebraObj ], 0, @@ -4095,6 +4096,19 @@ InstallMethod( PreImagesRepresentative, end); +InstallMethod( PreImagesRepresentative, + "for Fp to SCA mapping, and element", + FamRangeEqFamElm, + [ IsFptoSCAMorphism, IsSCAlgebraObj ], 0, + + function( f, x ) + if not ( x in Range( f ) ) then + return fail; + fi; + return PreImagesRepresentative( f, x ); + +end ); + ############################################################################# ## #M Dimension( ) @@ -5592,8 +5606,8 @@ InstallMethod( JenningsLieAlgebra, T:= EmptySCTable( dim , Zero(F) , "antisymmetric" ); pimgs := []; for i in [1..dim] do - a:= PreImagesRepresentative( Homs[pos[i]] , - PreImagesRepresentative( hom_pcg[pos[i]], gens[i] ) ); + a:= PreImagesRepresentativeNC( Homs[pos[i]] , + PreImagesRepresentativeNC( hom_pcg[pos[i]], gens[i] ) ); # calculate the p-th power image of `a': @@ -5610,8 +5624,8 @@ InstallMethod( JenningsLieAlgebra, # Calculate the commutator [a,b], and map the result into # the correct homogeneous component. - b:= PreImagesRepresentative( Homs[pos[j]], - PreImagesRepresentative( hom_pcg[pos[j]], gens[j] )); + b:= PreImagesRepresentativeNC( Homs[pos[j]], + PreImagesRepresentativeNC( hom_pcg[pos[j]], gens[j] )); c:= Image( hom_pcg[pos[i] + pos[j]], Image(Homs[pos[i] + pos[j]], a^-1*b^-1*a*b) ); e:= ExtRepOfObj(c); @@ -5788,8 +5802,8 @@ InstallMethod( PCentralLieAlgebra, T:= EmptySCTable( dim , Zero(F) , "antisymmetric" ); pimgs := []; for i in [1..dim] do - a:= PreImagesRepresentative( Homs[pos[i]] , - PreImagesRepresentative( hom_pcg[pos[i]], gens[i] ) ); + a:= PreImagesRepresentativeNC( Homs[pos[i]] , + PreImagesRepresentativeNC( hom_pcg[pos[i]], gens[i] ) ); # calculate the p-th power image of `a': @@ -5807,8 +5821,8 @@ InstallMethod( PCentralLieAlgebra, # Calculate the commutator [a,b], and map the result into # the correct homogeneous component. - b:= PreImagesRepresentative( Homs[pos[j]], - PreImagesRepresentative( hom_pcg[pos[j]], gens[j] )); + b:= PreImagesRepresentativeNC( Homs[pos[j]], + PreImagesRepresentativeNC( hom_pcg[pos[j]], gens[j] )); c:= Image( hom_pcg[pos[i] + pos[j]], Image(Homs[pos[i] + pos[j]], a^-1*b^-1*a*b) ); e:= ExtRepOfObj(c); diff --git a/lib/algrep.gi b/lib/algrep.gi index 8d331feee2..7607190b94 100644 --- a/lib/algrep.gi +++ b/lib/algrep.gi @@ -1212,24 +1212,24 @@ InstallMethod( NaturalHomomorphismBySubAlgebraModule, if IsLeftAlgebraModuleElementCollection( V ) then if IsRightAlgebraModuleElementCollection( V ) then left_op:= function( x, v ) - return ImagesRepresentative( f, x^PreImagesRepresentative( f, v ) ); + return ImagesRepresentative( f, x^PreImagesRepresentativeNC( f, v ) ); end; right_op:= function( v, x ) - return ImagesRepresentative( f, PreImagesRepresentative( f, v )^x ); + return ImagesRepresentative( f, PreImagesRepresentativeNC( f, v )^x ); end; qmod:= BiAlgebraModule( LeftActingAlgebra( V ), RightActingAlgebra( V ), left_op, right_op, quot ); else left_op:= function( x, v ) - return ImagesRepresentative( f, x^PreImagesRepresentative( f, v ) ); + return ImagesRepresentative( f, x^PreImagesRepresentativeNC( f, v ) ); end; qmod:= LeftAlgebraModule( LeftActingAlgebra( V ), left_op, quot); fi; else right_op:= function( v, x ) - return ImagesRepresentative( f, PreImagesRepresentative( f, v )^x ); + return ImagesRepresentative( f, PreImagesRepresentativeNC( f, v )^x ); end; qmod:= RightAlgebraModule( RightActingAlgebra( V ), right_op, quot ); diff --git a/lib/autsr.gi b/lib/autsr.gi index 241cc84115..704f9093dc 100644 --- a/lib/autsr.gi +++ b/lib/autsr.gi @@ -118,7 +118,7 @@ local C,M,p,all,gens,sub,q,hom,fp,rels,new,pre,i,free,cnt; rels:=Filtered(RelatorsOfFpGroup(fp),x->ForAll(ExponentSums(x),x->x mod p=0)); rels:=List(rels,x->ElementOfFpGroup(FamilyObj(One(fp)),x)); new:=RestrictedMapping(nat,C)*hom; - pre:=List(rels,x->PreImagesRepresentative(new,x)); + pre:=List(rels,x->PreImagesRepresentativeNC(new,x)); for i in [1..Length(rels)] do if not pre[i] in sub then Add(all,MappedWord(rels[i], @@ -141,7 +141,7 @@ local ocr,fphom,fpg,free,len,dim,tmp,L0,R,rels,mat,r,RS,i,g,v,cnt; fpg:=FreeGeneratorsOfFpGroup(Range(fphom)); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fphom))]; ocr.generators:=List(GeneratorsOfGroup(Range(fphom)), - i->PreImagesRepresentative(fphom,i)); + i->PreImagesRepresentativeNC(fphom,i)); OCAddMatrices(ocr,ocr.generators); OCAddRelations(ocr,ocr.generators); OCAddSumMatrices(ocr,ocr.generators); @@ -274,8 +274,8 @@ BindGlobal("AGSRAutomLift",function(ocr,nat,fhom,miso) # allow to deduce corresponding module aut. t:=ocr.trickrels; phom:=IdentityMapping(ocr.moduleauts); - s:=List(t.gens,x->PreImagesRepresentative(nat,x)); - l:=List(t.gens,x->PreImagesRepresentative(nat,ImagesRepresentative(fhom,x))); + s:=List(t.gens,x->PreImagesRepresentativeNC(nat,x)); + l:=List(t.gens,x->PreImagesRepresentativeNC(nat,ImagesRepresentative(fhom,x))); s:=List(t.rels,x->MappedWord(x,GeneratorsOfGroup(t.free),s)); l:=List(t.rels,x->MappedWord(x,GeneratorsOfGroup(t.free),l)); @@ -294,7 +294,7 @@ BindGlobal("AGSRAutomLift",function(ocr,nat,fhom,miso) Size(Image(phom))); fi; for ep in enum do - e:=PreImagesRepresentative(phom,ep); + e:=PreImagesRepresentativeNC(phom,ep); psim:=e*miso; psim:=psim^-1; w:=-List(v,i->i*psim); @@ -486,7 +486,7 @@ local S,c,hom,q,a,b,i,t,have,ups,new,u,good,abort,clim,worked,pp, cnt:=0; for b in t do - new:=PreImagesRepresentative(hom,b); + new:=PreImagesRepresentativeNC(hom,b); if (pp=false or new^pp in S) and locond(new) then S:=ClosureGroup(S,new); have:=true; @@ -1028,7 +1028,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, b:=MTX.BasisRadical(mo); fratsim:=Length(b)=0; if not fratsim then - b:=List(b,x->PreImagesRepresentative(hom,PcElementByExponents(MPcgs,x))); + b:=List(b,x->PreImagesRepresentativeNC(hom,PcElementByExponents(MPcgs,x))); for j in b do N:=ClosureSubgroup(N,b); od; @@ -1129,8 +1129,8 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, if perm in Aperm then return true; fi; - aut:=PreImagesRepresentative(AQiso,perm); - newgens:=List(gens,x->PreImagesRepresentative(comiso, + aut:=PreImagesRepresentativeNC(AQiso,perm); + newgens:=List(gens,x->PreImagesRepresentativeNC(comiso, ImagesRepresentative(aut,ImagesRepresentative(comiso,x)))); mo2:=GModuleByMats(LinearActionLayer(newgens,MPcgs),mo.field); @@ -1163,9 +1163,9 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, if perm in Aperm then return true; fi; - aut:=PreImagesRepresentative(AQiso,perm); + aut:=PreImagesRepresentativeNC(AQiso,perm); newgens:=List(GeneratorsOfGroup(Q), - x->PreImagesRepresentative(q,Image(aut,ImagesRepresentative(q,x)))); + x->PreImagesRepresentativeNC(q,Image(aut,ImagesRepresentative(q,x)))); mo2:=GModuleByMats(LinearActionLayer(newgens,MPcgs),mo.field); return MTX.IsomorphismModules(mo,mo2)<>fail; end; @@ -1175,9 +1175,9 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, if perm in Aperm then return true; fi; - aut:=PreImagesRepresentative(AQiso,perm); + aut:=PreImagesRepresentativeNC(AQiso,perm); newgens:=List(GeneratorsOfGroup(Q), - x->PreImagesRepresentative(q,Image(aut,ImagesRepresentative(q,x)))); + x->PreImagesRepresentativeNC(q,Image(aut,ImagesRepresentative(q,x)))); mo2:=GModuleByMats(LinearActionLayer(newgens,MPcgs),mo.field); iso:=MTX.IsomorphismModules(mo,mo2); if iso=fail then @@ -1234,12 +1234,12 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, # stabilize class k:=SmallGeneratingSet(sub); ac:=OrbitStabilizerAlgorithm(sub,false,false, - k,List(k,x->PreImagesRepresentative(AQiso,x)), + k,List(k,x->PreImagesRepresentativeNC(AQiso,x)), rec(pnt:=j, act:= function(set,phi) #local phi; - #phi:=PreImagesRepresentative(AQiso,perm); + #phi:=PreImagesRepresentativeNC(AQiso,perm); return Set(List(set,x->Image(phi,x))); end, onlystab:=true)); @@ -1367,7 +1367,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, GeneratorsOfGroup(rf), List(GeneratorsOfGroup(rf), y->ImagesRepresentative(hom,ImagesRepresentative(j, - PreImagesRepresentative(hom,y))))); + PreImagesRepresentativeNC(hom,y))))); Assert(2,IsBijective(k)); Add(ind,k); od; @@ -1390,7 +1390,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, proj:=GroupHomomorphismByImagesNC(AQP,Image(resperm), B[2],List(GeneratorsOfGroup(res),x->ImagesRepresentative(resperm,x))); C:=PreImage(proj,Image(resperm,ind)); - C:=List(SmallGeneratingSet(C),x->PreImagesRepresentative(AQiso,x)); + C:=List(SmallGeneratingSet(C),x->PreImagesRepresentativeNC(AQiso,x)); AQ:=Group(C); SetIsFinite(AQ,true); SetIsGroupOfAutomorphismsFiniteGroup(AQ,true); @@ -1416,7 +1416,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, C:=MappingGeneratorsImages(AQiso); if C[2]<>GeneratorsOfGroup(AQP) then C:=[List(GeneratorsOfGroup(AQP), - x->PreImagesRepresentative(AQiso,x)), + x->PreImagesRepresentativeNC(AQiso,x)), GeneratorsOfGroup(AQP)]; fi; for j in u do @@ -1450,7 +1450,7 @@ local ff,r,d,ser,u,v,i,j,k,p,bd,e,gens,lhom,M,N,hom,Q,Mim,q,ocr,split,MPcgs, substb:=SmallGeneratingSet(substb); AQP:=Group(substb); SetSize(AQP,B); - C:=[List(substb,x->PreImagesRepresentative(AQiso,x)),substb]; + C:=[List(substb,x->PreImagesRepresentativeNC(AQiso,x)),substb]; fi; od; @@ -1883,7 +1883,7 @@ local d,a,map,cG,nG,nH,i,j,u,v,asAutomorphism,K,L,conj,e1,e2, else gens:=SmallGeneratingSet(api); fi; - pre:=List(gens,x->PreImagesRepresentative(iso,x)); + pre:=List(gens,x->PreImagesRepresentativeNC(iso,x)); map:=RepresentativeAction(SubgroupNC(a,pre),u,v,asAutomorphism); if map=fail then return fail; @@ -1904,6 +1904,6 @@ local d,a,map,cG,nG,nH,i,j,u,v,asAutomorphism,K,L,conj,e1,e2, fi; return GroupHomomorphismByImagesNC(G,H,GeneratorsOfGroup(G), - List(GeneratorsOfGroup(G),x->PreImagesRepresentative(e2, + List(GeneratorsOfGroup(G),x->PreImagesRepresentativeNC(e2, Image(conj,Image(e1,x))))); end); diff --git a/lib/clas.gi b/lib/clas.gi index b933b7d50b..2a27e3cbba 100644 --- a/lib/clas.gi +++ b/lib/clas.gi @@ -395,7 +395,7 @@ local H,cl,a,c; H:=Image(hom,G); cl:=[]; for c in ConjugacyClasses(H) do - a:=ConjugacyClass(G,PreImagesRepresentative(hom,Representative(c))); + a:=ConjugacyClass(G,PreImagesRepresentativeNC(hom,Representative(c))); if HasStabilizerOfExternalSet(c) then SetStabilizerOfExternalSet(a,PreImage(hom,StabilizerOfExternalSet(c))); fi; diff --git a/lib/clashom.gi b/lib/clashom.gi index 201b2cd9b7..16c7c4f9c3 100644 --- a/lib/clashom.gi +++ b/lib/clashom.gi @@ -499,7 +499,7 @@ local clT, # classes T for k in clop do Info(InfoHomClass,1,"lifting class ",Representative(k)); - r:=PreImagesRepresentative(ophom,Representative(k)); + r:=PreImagesRepresentativeNC(ophom,Representative(k)); # try to make r of small order rp:=r^Order(Representative(k)); rp:=RepresentativeAction(M,Concatenation(components), @@ -564,7 +564,7 @@ local clT, # classes T orb:=[]; for p in [1..Length(clTR)] do - repres:=PreImagesRepresentative(projections[i],clTR[p]); + repres:=PreImagesRepresentativeNC(projections[i],clTR[p]); if i=1 or isdirprod or reps[j]*RestrictedPermNC(repres,components[i]) in Mproj[i] then @@ -586,8 +586,8 @@ local clT, # classes T #was: #clTR:=List(clTR,i->ConjugacyClass(localcent_r,i)); - #clTR:=List(clTR,j->[PreImagesRepresentative(projections[i], - # Representative(j)), + #clTR:=List(clTR,j->[PreImagesRepresentativeNC(projections[i], + # Representative(j)), # PreImage(centrhom,Centralizer(j)), # j]); @@ -706,7 +706,7 @@ local clT, # classes T #change the transversal element to map to the representative con:=trans[orpo]*gen; limg:=opfun(repres,con); - con:=con*PreImagesRepresentative(centrhom, + con:=con*PreImagesRepresentativeNC(centrhom, RepresentativeAction(localcent_r, Image(projections[i],limg), Representative(clTR[p][3]))); @@ -798,7 +798,7 @@ local clT, # classes T # centralizers_r-conjugation.) con:=trans[orpo]*gen; limg:=opfun(repres,con); - con:=con*PreImagesRepresentative(centrhom, + con:=con*PreImagesRepresentativeNC(centrhom, RepresentativeAction(localcent_r, Image(projections[i],limg), Representative(orb[p][3]))); @@ -870,7 +870,7 @@ local clT, # classes T # remember the element to try trymap:=[p,(cengen[genpos2]* - PreImagesRepresentative( + PreImagesRepresentativeNC( RestrictedMapping(projections[i], centralizers[j]), RepresentativeAction( @@ -1140,7 +1140,7 @@ local cs, # chief series of G # compute the classes of the simple nonabelian factor by random search hom:=NaturalHomomorphismByNormalSubgroupNC(G,lastM); cl:=ConjugacyClasses(Image(hom)); - cl:=List(cl,i->[PreImagesRepresentative(hom,Representative(i)), + cl:=List(cl,i->[PreImagesRepresentativeNC(hom,Representative(i)), PreImage(hom,StabilizerOfExternalSet(i))]); cs:=Concatenation([G],Filtered(cs,x->IsSubset(lastM,x))); fi; @@ -1207,7 +1207,7 @@ local cs, # chief series of G autos:=List(GeneratorsOfGroup(G), i->GroupHomomorphismByImagesNC(T1,T1,GeneratorsOfGroup(T1), List(GeneratorsOfGroup(T1), - j->Image(Thom,PreImagesRepresentative(Thom,j)^i)))); + j->Image(Thom,PreImagesRepresentativeNC(Thom,j)^i)))); # find (probably another) permutation rep for T1 for which all # automorphisms can be represented by permutations @@ -1268,7 +1268,7 @@ local cs, # chief series of G autos:=List(GeneratorsOfGroup(S), i->GroupHomomorphismByImagesNC(T1,T1,GeneratorsOfGroup(T1), List(GeneratorsOfGroup(T1), - j->Image(Thom,PreImagesRepresentative(Thom,j)^i)))); + j->Image(Thom,PreImagesRepresentativeNC(Thom,j)^i)))); # find (probably another) permutation rep for T1 for which all # automorphisms can be represented by permutations @@ -1288,7 +1288,7 @@ local cs, # chief series of G # define isomorphisms between the components reps:=List([1..n],i-> - PreImagesRepresentative(Qhom,RepresentativeAction(Q,1,i))); + PreImagesRepresentativeNC(Qhom,RepresentativeAction(Q,1,i))); genimages:=[]; for j in GeneratorsOfGroup(G) do @@ -1345,7 +1345,7 @@ local cs, # chief series of G SetSize(F,Size(G)); FM:=GroupHomomorphismByImagesNC(G,F,GeneratorsOfGroup(G),FM); clF:=ConjugacyClassesFittingFreeGroup(F); - clF:=List(clF,x->[PreImagesRepresentative(FM,x[1]),PreImage(FM,x[2])]); + clF:=List(clF,x->[PreImagesRepresentativeNC(FM,x[1]),PreImage(FM,x[2])]); return clF; fi; #fi; @@ -1374,9 +1374,9 @@ local cs, # chief series of G Info(InfoHomClass,1, "homomorphism is faithful for relevant factor, take preimages"); if Size(N)=1 and onlysizes=true then - cl:=List(clF,i->[PreImagesRepresentative(Fhom,i[1]),Size(i[2])]); + cl:=List(clF,i->[PreImagesRepresentativeNC(Fhom,i[1]),Size(i[2])]); else - cl:=List(clF,i->[PreImagesRepresentative(Fhom,i[1]), + cl:=List(clF,i->[PreImagesRepresentativeNC(Fhom,i[1]), PreImage(Fhom,i[2])]); fi; else @@ -1391,7 +1391,7 @@ local cs, # chief series of G for k in clF do # modify the representative with a kernel elm. to project # correctly on the second component - elm:=j[1]*PreImagesRepresentative(FMhom, + elm:=j[1]*PreImagesRepresentativeNC(FMhom, LeftQuotient(Image(Fhom,j[1]),k[1])); zentr:=Intersection(j[2],PreImage(Fhom,k[2])); Assert(3,ForAll(GeneratorsOfGroup(zentr), @@ -1449,7 +1449,7 @@ local cs, # chief series of G if Image(Qhom,elm)=jim then # modify the representative with a kernel elm. to project # correctly on the second component - elm:=l[1]*PreImagesRepresentative(FMhom, + elm:=l[1]*PreImagesRepresentativeNC(FMhom, LeftQuotient(Image(Fhom,l[1]),elm)); zentr:=PreImage(Fhom,k[2]^l1); zentr:=Intersection(zentr,l[2]); @@ -1957,7 +1957,7 @@ local classes, # classes to be constructed, the result c := [h * PcElementByExponentsNC( Npcgs,w*com.factorspace), stabrad,stabfacgens,stabfacimg,subsz,stabrsubsz]; #if reduce<>fail then - # Add(classes,[PreImagesRepresentative(reduce,c[1]), + # Add(classes,[PreImagesRepresentativeNC(reduce,c[1]), # PreImage(reduce,c[2])]); # else @@ -2022,7 +2022,7 @@ BindGlobal("LiftClassesEATrivRep", nsfgens:=NormalIntersection(fants[usent],Group(cl[4])); fasize:=Size(nsfgens); nsfgens:=SmallGeneratingSet(nsfgens); - nsgens:=List(nsfgens,x->PreImagesRepresentative(hom,x)); + nsgens:=List(nsfgens,x->PreImagesRepresentativeNC(hom,x)); nsimgs:=List(Concatenation(pcgs,nsgens),npcgsact); mo:=GModuleByMats(nsimgs,field); if not MTX.IsIrreducible(mo) then @@ -2338,7 +2338,7 @@ local r, #radical if IsPermGroup(Range(hom)) and not IsPermGroup(Source(hom)) then f:=Image(hom,G); cl:=ConjugacyClassesFittingFreeGroup(f:onlysizes:=false); - cl:=List(cl,x->[PreImagesRepresentative(hom,x[1]), + cl:=List(cl,x->[PreImagesRepresentativeNC(hom,x[1]), PreImage(hom,x[2])]); else cl:=ConjugacyClassesFittingFreeGroup(G:onlysizes:=false); @@ -2398,12 +2398,12 @@ local r, #radical if ntrihom then ncl:=[]; for i in cl do - new:=[PreImagesRepresentative(hom,i[1])]; + new:=[PreImagesRepresentativeNC(hom,i[1])]; if not IsInt(i[2]) then Add(new,[]); # no generators in radical yet gens:=SmallGeneratingSet(i[2]); Add(new, - List(gens,x->PreImagesRepresentative(hom,x))); + List(gens,x->PreImagesRepresentativeNC(hom,x))); Add(new,gens); #TODO: PreImage groups? #Add(new,PreImage(hom,i[2])); @@ -2886,10 +2886,10 @@ local r, #radical fi; prereps:=f!.classpreimgs; if not IsBound(prereps[j]) then - prereps[j]:=PreImagesRepresentative(hom,Representative(cl[j])); + prereps[j]:=PreImagesRepresentativeNC(hom,Representative(cl[j])); fi; - r:=PreImagesRepresentative(hom,conj); + r:=PreImagesRepresentativeNC(hom,conj); d:=GeneratorsOfGroup(Centralizer(cl[j])); # Format for cl is: @@ -2897,7 +2897,7 @@ local r, #radical # in factor, 4:conjugator, 5:cenpcgs, # 6:cenfac, 7:cenfacimgs, 8:censize, 9:cenfacsize Add(nreps,[i,i^r,prereps[j],r,[], - List(d,x->PreImagesRepresentative(hom,x)),d, + List(d,x->PreImagesRepresentativeNC(hom,x)),d, radsize*Size(Centralizer(cl[j])), Size(Centralizer(cl[j]))]); od; reps:=nreps; diff --git a/lib/csetgrp.gi b/lib/csetgrp.gi index 9c5955a8f3..c2d37bfba8 100644 --- a/lib/csetgrp.gi +++ b/lib/csetgrp.gi @@ -199,7 +199,7 @@ local cla,clb,i,j,k,bd,r,rep,b2,dc, r:=SmallerDegreePermutationRepresentation(b:cheap); k:=Image(r,b); gens:=MorFindGeneratingSystem(k,MorMaxFusClasses(MorRatClasses(k))); - gens:=List(gens,x->PreImagesRepresentative(r,x)); + gens:=List(gens,x->PreImagesRepresentativeNC(r,x)); else gens:=MorFindGeneratingSystem(b,MorMaxFusClasses(MorRatClasses(b))); fi; @@ -1064,7 +1064,7 @@ local c, flip, maxidx, cano, tryfct, p, r, t, Assert(2,Size(a2)*Size(tra)=Size(b)); SetKernelOfMultiplicativeGeneralMapping(r,a2); - dcs:=List(dcs,x->[PreImagesRepresentative(quot,x[1]),Size(a1)*x[2], + dcs:=List(dcs,x->[PreImagesRepresentativeNC(quot,x[1]),Size(a1)*x[2], PreImage(r,x[3])]); r:=List(dcs,x->x[1]); stabs:=List(dcs,x->x[3]); diff --git a/lib/ctblfuns.gi b/lib/ctblfuns.gi index c648c9401f..eec04e92e4 100644 --- a/lib/ctblfuns.gi +++ b/lib/ctblfuns.gi @@ -2049,8 +2049,8 @@ InstallMethod( InertiaSubgroup, if stab = permgrp then return G; else - return PreImagesSet( GroupHomomorphismByImages( G, permgrp, - GeneratorsOfGroup( G ), perms ), + return PreImagesSetNC( GroupHomomorphismByImages( G, permgrp, + GeneratorsOfGroup( G ), perms ), stab ); fi; end ); diff --git a/lib/ctblgrp.gi b/lib/ctblgrp.gi index 3b41dbb5be..914845923f 100644 --- a/lib/ctblgrp.gi +++ b/lib/ctblgrp.gi @@ -1606,7 +1606,7 @@ local tm,tme,piso,gpcgs,gals,ord,l,l2,f,fgens,rws,pow,pos,i,j,k,gen, # not easily transfer to mod p. k:=Image(piso,TrivialSubgroup(D.galMorphisms)); gpcgs:=Pcgs(k); - gals:=List(gpcgs,i->PreImagesRepresentative(piso,i)); + gals:=List(gpcgs,i->PreImagesRepresentativeNC(piso,i)); ord:=List(gpcgs,i->RelativeOrderOfPcElement(gpcgs,i)); l:=Length(gpcgs); @@ -1827,7 +1827,7 @@ local often,trans,e,neu,i,inv,cent,l,s,s1,x,dom; if dom=fail then x:=D.classreps[inv]; - l:=List(s,i->[x^PreImagesRepresentative(e, + l:=List(s,i->[x^PreImagesRepresentativeNC(e, RepresentativeAction(Image(e),1,i[1])),Size(cent)*Length(i)]); else l:=List(s,i->[dom[i[1]],Size(cent)*Length(i)]); diff --git a/lib/ctblsolv.gi b/lib/ctblsolv.gi index d18f10f6d7..fc787a2bb6 100644 --- a/lib/ctblsolv.gi +++ b/lib/ctblsolv.gi @@ -176,7 +176,7 @@ InstallGlobalFunction( ProjectiveCharDeg, function( G, z, q ) # `N' is a normal subgroup such that `N/' is a chief factor of `G' # of order `i' which is a power of `p'. - N:= PreImagesSet( h, N ); + N:= PreImagesSetNC( h, N ); i:= Size( N ) / oz; p:= Factors( i )[1]; @@ -184,7 +184,7 @@ InstallGlobalFunction( ProjectiveCharDeg, function( G, z, q ) # `c' is a list of complement classes of `N' modulo `z' c:= List( ComplementClassesRepresentatives( ImagesSource( h ), ImagesSet( h, N ) ), - x -> PreImagesSet( h, x ) ); + x -> PreImagesSetNC( h, x ) ); r:= Centralizer( G, N ); for L in c do if IsSubset( L, r ) then @@ -563,7 +563,7 @@ InstallGlobalFunction( CoveringTriplesCharacters, function( G, z ) N:= ChiefSeriesUnderAction( img, N ); N:= N[ Length( N ) - 1 ]; fi; - N:= PreImagesSet( h, N ); + N:= PreImagesSetNC( h, N ); if not IsAbelian( N ) then Info( InfoCharacterTable, 2, @@ -582,9 +582,9 @@ InstallGlobalFunction( CoveringTriplesCharacters, function( G, z ) h:= NaturalHomomorphismByNormalSubgroupNC( G, P ); r:= List( CoveringTriplesCharacters( ImagesSource( h ), ImageElm( h, z ) ), - x -> [ PreImagesSet( h, x[1] ), - PreImagesSet( h, x[2] ), - PreImagesRepresentative( h, x[3] ) ] ); + x -> [ PreImagesSetNC( h, x[1] ), + PreImagesSetNC( h, x[2] ), + PreImagesRepresentativeNC( h, x[3] ) ] ); if p = i then @@ -622,9 +622,9 @@ InstallGlobalFunction( CoveringTriplesCharacters, function( G, z ) c:= Stabilizer( img, zn ); fi; Append( r, List( CoveringTriplesCharacters( c, zn ), - x -> [ PreImagesSet( h, x[1] ), - PreImagesSet( h, x[2] ), - PreImagesRepresentative( h, x[3] ) ] ) ); + x -> [ PreImagesSetNC( h, x[1] ), + PreImagesSetNC( h, x[2] ), + PreImagesRepresentativeNC( h, x[3] ) ] ) ); od; return r; @@ -663,9 +663,9 @@ InstallGlobalFunction( CoveringTriplesCharacters, function( G, z ) img:= ImagesSource( h ); Append( r, List( CoveringTriplesCharacters( img, ImageElm( h, z ) ), - x -> [ PreImagesSet( h, x[1] ), - PreImagesSet( h, x[2] ), - PreImagesRepresentative( h, x[3] ) ] ) ); + x -> [ PreImagesSetNC( h, x[1] ), + PreImagesSetNC( h, x[2] ), + PreImagesRepresentativeNC( h, x[3] ) ] ) ); fi; od; return r; @@ -1067,7 +1067,7 @@ InstallMethod( BaumClausenInfo, for i in [ 2 .. Length( ssr.ds ) ] do j:= NaturalHomomorphismByNormalSubgroupNC( ssr.ds[ i-1 ], ssr.ds[i] ); Append( pcgs, List( SpecialPcgs( ImagesSource( j ) ), - x -> PreImagesRepresentative( j, x ) ) ); + x -> PreImagesRepresentativeNC( j, x ) ) ); od; Append( pcgs, SpecialPcgs( Last(ssr.ds) ) ); G:= ImagesSource( hom ); @@ -1911,7 +1911,7 @@ InstallMethod( BaumClausenInfo, k:= Pcgs( kernel ); pcgs:= PcgsByPcSequence( ElementsFamily( FamilyObj( kernel ) ), Concatenation( List( pcgs, - x -> PreImagesRepresentative( hom, x ) ), + x -> PreImagesRepresentativeNC( hom, x ) ), k ) ); k:= ListWithIdenticalEntries( Length( k ), 0 ); diff --git a/lib/error.g b/lib/error.g index de03ee813f..3a81bebffd 100644 --- a/lib/error.g +++ b/lib/error.g @@ -135,7 +135,8 @@ BIND_GLOBAL("PRETTY_PRINT_VARS", function(context) end); BIND_GLOBAL("WHERE", function(depth, context, activecontext, showlocals) - local bottom, lastcontext, f, level, totaldepth, countcontext; + local bottom, lastcontext, f, level, totaldepth, countcontext, + prefixwidth, location; if depth <= 0 then return; fi; @@ -144,6 +145,7 @@ BIND_GLOBAL("WHERE", function(depth, context, activecontext, showlocals) PrintTo(ERROR_OUTPUT, "called from read-eval loop "); return; fi; + PrintTo(ERROR_OUTPUT, "Stack trace:\n"); lastcontext := context; totaldepth := 0; countcontext := context; @@ -151,14 +153,20 @@ BIND_GLOBAL("WHERE", function(depth, context, activecontext, showlocals) totaldepth := totaldepth + 1; countcontext := ParentLVars(countcontext); od; + prefixwidth := Length(String(totaldepth)); level := 1; while depth > 0 and context <> bottom do - PRINT_CURRENT_STATEMENT( + location := PRINT_CURRENT_STATEMENT( ERROR_OUTPUT, context, activecontext, level, - totaldepth); + prefixwidth); + if location <> fail then + PrintTo(ERROR_OUTPUT, "\n", + ListWithIdenticalEntries(prefixwidth+2, ' '), + "@ ", location[1], ":", location[2]); + fi; if showlocals then PRETTY_PRINT_VARS(context); else @@ -228,7 +236,7 @@ end); # Unbind(ErrorInner); BIND_GLOBAL("ErrorInner", function(options, earlyMessage) - local context, tracebackContext, mayReturnVoid, mayReturnObj, + local context, tracebackContext, mayReturnVoid, lateMessage, x, prompt, res, errorLVars, errorTracebackLVars, kernelErrorLVars, justQuit, printEarlyMessage, printEarlyTraceback, printAutomaticTraceback, lastErrorStream; @@ -262,17 +270,6 @@ BIND_GLOBAL("ErrorInner", function(options, earlyMessage) mayReturnVoid := false; fi; - if IsBound(options.mayReturnObj) then - mayReturnObj := options.mayReturnObj; - if not mayReturnObj in [false, true] then - PrintTo(ERROR_OUTPUT, "ErrorInner: option mayReturnObj must be true or false\n"); - LEAVE_ALL_NAMESPACES(); - JUMP_TO_CATCH(1); - fi; - else - mayReturnObj := false; - fi; - if IsBound(options.tracebackContext) then tracebackContext := options.tracebackContext; if not IsLVarsBag(tracebackContext) then @@ -312,9 +309,6 @@ BIND_GLOBAL("ErrorInner", function(options, earlyMessage) printAutomaticTraceback := function() if IsBound(OnBreak) and IsFunction(OnBreak) then - if OnBreak = Where or OnBreak = WhereWithVars then - PrintTo(ERROR_OUTPUT, "Stack trace:\n"); - fi; OnBreak(); fi; end; @@ -410,7 +404,7 @@ BIND_GLOBAL("ErrorInner", function(options, earlyMessage) prompt := "brk> "; fi; if not justQuit then - res := SHELL(context,mayReturnVoid,mayReturnObj,true,prompt,false); + res := SHELL(context,mayReturnVoid,false,true,prompt,false); else res := fail; fi; @@ -455,8 +449,7 @@ BIND_GLOBAL("ErrorNoReturn", function(arg) rec( context := ParentLVars(GetCurrentLVars()), mayReturnVoid := false, - mayReturnObj := false, - lateMessage := "type 'quit;' to quit to outer loop", + lateMessage := "you can enter 'quit;' to quit to outer loop", ), arg); end); diff --git a/lib/ffe.gd b/lib/ffe.gd index 3eeddef057..aa93c7a24f 100644 --- a/lib/ffe.gd +++ b/lib/ffe.gd @@ -118,9 +118,9 @@ ## ]]> ## Z(11,40); -## Error, Conway Polynomial 11^40 will need to computed and might be slow -## return to continue -## *[1] Error( "Conway Polynomial ", p, "^", d, " will need to computed and might be slow\n", "return to continue" ); +## Error, Conway Polynomial 11^40 will need to be computed and might be slow +## Stack trace: +## *[1] Error( "Conway Polynomial ", p, "^", d, " will need to be computed and might be slow" ); ## @ GAPROOT/lib/ffeconway.gi:81 ## [2] FFECONWAY.SetUpConwayStuff( p, d ); ## @ GAPROOT/lib/ffeconway.gi:140 @@ -128,8 +128,8 @@ ## @ GAPROOT/lib/ffeconway.gi:167 ## ( ) ## called from read-eval loop at *stdin*:2 -## you can 'quit;' to quit to outer loop, or -## you can 'return;' to continue +## you can enter 'quit;' to quit to outer loop, or +## you can enter 'return;' to continue ## brk> ## ]]> ## diff --git a/lib/ffeconway.gi b/lib/ffeconway.gi index fd6f5b721d..04555686d4 100644 --- a/lib/ffeconway.gi +++ b/lib/ffeconway.gi @@ -78,7 +78,7 @@ FFECONWAY.SetUpConwayStuff := function(p,d) if not IsCheapConwayPolynomial(p,d) then Error("Conway Polynomial ",p,"^",d, - " will need to computed and might be slow\n", "return to continue"); + " will need to be computed and might be slow"); fi; cp := CoefficientsOfUnivariatePolynomial(ConwayPolynomial(p,d)); diff --git a/lib/field.gi b/lib/field.gi index f5eadb8ede..6223cf0535 100644 --- a/lib/field.gi +++ b/lib/field.gi @@ -1315,15 +1315,16 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesElm( , ) . . . . . . . . . . . . preimage of an elm +#M PreImagesElmNC( , ) . . . . . . . . . . . . preimage of an elm +#M PreImagesElm( , ) . . . . . . . . . . . . . preimage of an elm ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for field homomorphism and element", FamRangeEqFamElm, [ IsFieldHomomorphism, IsObject ], function ( hom, elm ) if IsInjective( hom ) = 1 then - return [ PreImagesRepresentative( hom, elm ) ]; + return [ PreImagesRepresentativeNC( hom, elm ) ]; elif IsZero( elm ) then return Source( hom ); else @@ -1331,18 +1332,41 @@ InstallMethod( PreImagesElm, fi; end ); +InstallMethod( PreImagesElm, + "for field homomorphism and element", + FamRangeEqFamElm, + [ IsFieldHomomorphism, IsObject ], + function ( hom, elm ) + if not (elm in Range(hom)) then + return fail; + fi; + return PreImagesElm( hom, elm ); + end ); ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . . . . . preimage of a set +#M PreImagesSetNC +#M PreImagesSet ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for field homomorphism and field", CollFamRangeEqFamElms, [ IsFieldHomomorphism, IsField ], function ( hom, elms ) elms:= FieldByGenerators( List( GeneratorsOfField( elms ), - gen -> PreImagesRepresentative( hom, gen ) ) ); + gen -> PreImagesRepresentativeNC( hom, gen ) ) ); UseSubsetRelation( Source( hom ), elms ); return elms; end ); + +InstallMethod( PreImagesSet, + "for field homomorphism and field", + CollFamRangeEqFamElms, + [ IsFieldHomomorphism, IsField ], + function ( hom, elms ) + if not IsSubset( Range(hom), elms ) then + return fail; + fi; + return PreImagesSet( hom, elms ); + end ); + diff --git a/lib/fitfree.gi b/lib/fitfree.gi index d68681ea93..e8669473c0 100644 --- a/lib/fitfree.gi +++ b/lib/fitfree.gi @@ -54,10 +54,10 @@ local ffs,pcisom,rest,kpc,k,x,ker,r,pool,i,xx,pregens,iso; rest:=GroupHomomorphismByImages(U,Range(ffs.factorhom),GeneratorsOfGroup(U), List(GeneratorsOfGroup(U),x->ImagesRepresentative(ffs.factorhom,x))); else - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment rest:=GroupHomomorphismByImagesNC(U,Range(ffs.factorhom),GeneratorsOfGroup(U), List(GeneratorsOfGroup(U),x->ImagesRepresentative(ffs.factorhom,x))); - RUN_IN_GGMBI:=false; + PopOptions(); fi; Assert(1,rest<>fail); @@ -81,7 +81,7 @@ local ffs,pcisom,rest,kpc,k,x,ker,r,pool,i,xx,pregens,iso; else iso:=IsomorphismFpGroup(Image(rest,U)); pregens:=List(GeneratorsOfGroup(Range(iso)),x-> - PreImagesRepresentative(rest,PreImagesRepresentative(iso,x))); + PreImagesRepresentativeNC(rest,PreImagesRepresentativeNC(iso,x))); # evaluate relators pool:=List(RelatorsOfFpGroup(Range(iso)), x->MappedWord(x,FreeGeneratorsOfFpGroup(Range(iso)),pregens)); @@ -91,7 +91,7 @@ local ffs,pcisom,rest,kpc,k,x,ker,r,pool,i,xx,pregens,iso; iso:=IsomorphismFpGroup(Image(rest,U)); pregens:=List(GeneratorsOfGroup(Range(iso)),x-> - PreImagesRepresentative(rest,PreImagesRepresentative(iso,x))); + PreImagesRepresentativeNC(rest,PreImagesRepresentativeNC(iso,x))); # evaluate relators pool:=List(RelatorsOfFpGroup(Range(iso)), x->MappedWord(x,FreeGeneratorsOfFpGroup(Range(iso)),pregens)); @@ -135,7 +135,7 @@ local ffs,pcisom,rest,kpc,k,x,ker,r,pool,i,xx,pregens,iso; # od; SetSize(U,Size(Image(rest))*Size(kpc)); k:=InducedPcgs(FamilyPcgs(Image(pcisom)),kpc); - k:=List(k,x->PreImagesRepresentative(pcisom,x)); + k:=List(k,x->PreImagesRepresentativeNC(pcisom,x)); k:=InducedPcgsByPcSequenceNC(ffs.pcgs,k); ker:=SubgroupNC(G,k); SetSize(ker,Size(kpc)); @@ -257,7 +257,7 @@ local ffs,hom,U,rest,ker,r,p,l,i,depths,pcisom,subsz,pcimgs; pcimgs:=List(ipcgs,x->ImagesRepresentative(ffs.pcisom,x)); ker:=SubgroupNC(G,List(MinimalGeneratingSet(Group(pcimgs,One(Range(ffs.pcisom)))), - x->PreImagesRepresentative(ffs.pcisom,x))); + x->PreImagesRepresentativeNC(ffs.pcisom,x))); SetPcgs(ker,ipcgs); if Length(ipcgs)=0 then SetSize(ker,1); @@ -276,9 +276,9 @@ local ffs,hom,U,rest,ker,r,p,l,i,depths,pcisom,subsz,pcimgs; if IsPermGroup(U) and AssertionLevel()>1 then rest:=GroupHomomorphismByImages(U,Range(hom),gens,imgs); else - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment rest:=GroupHomomorphismByImagesNC(U,Range(hom),gens,imgs); - RUN_IN_GGMBI:=false; + PopOptions(); fi; Assert(1,rest<>fail); @@ -319,11 +319,11 @@ local ffs,hom,U,rest,ker,r,p,l,i,depths,pcisom,subsz,pcimgs; else r:=SubgroupNC(G,ipcgs); fi; - RUN_IN_GGMBI:=true; + PushOptions( rec( Run_In_GGMBI:= true ) ); pcisom:=GroupHomomorphismByImagesNC(r, SubgroupNC(Range(ffs.pcisom),pcisom), ipcgs,pcisom); - RUN_IN_GGMBI:=false; + PopOptions(); fi; r:=rec(inducedfrom:=ffs, pcgs:=ipcgs, @@ -916,13 +916,14 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs,gens; s:=SylowSubgroup(Image(hom),prime); fphom:=IsomorphismFpGroup(s); fp:=Image(fphom); - sf:=List(GeneratorsOfGroup(Image(fphom)),x->PreImagesRepresentative(fphom,x)); - sg:=List(sf,x->PreImagesRepresentative(hom,x)); + sf:=List(GeneratorsOfGroup(Image(fphom)), + x->PreImagesRepresentativeNC(fphom,x)); + sg:=List(sf,x->PreImagesRepresentativeNC(hom,x)); sp:=[]; - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(Group(sg,One(G)),fp,sg, GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + PopOptions(); @@ -939,9 +940,9 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs,gens; Append(sp,mpcgs); else # extend presentation - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=LiftFactorFpHom(fphom,Source(fphom),false,mpcgs); - RUN_IN_GGMBI:=false; + PopOptions(); fp:=Image(fphom); sp:=Concatenation(sp,mpcgs); fi; @@ -953,10 +954,10 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs,gens; gens:=GeneratorsOfGroup(ocr.complement); sg:=gens{[1..Length(sg)]}; sp:=gens{[Length(sg)+1..Length(gens)]}; - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(ocr.complement,fp,gens, GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + PopOptions(); fi; od; @@ -1194,7 +1195,7 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, norm:=n); for j in [2..Length(i)] do c[i[j]]:=rec(orbit:=i,orbitpos:=j, - rep:=PreImagesRepresentative(act, + rep:=PreImagesRepresentativeNC(act, RepresentativeAction(Image(act),i[1],i[j])), component:=d[i[j]],hall:=h, norm:=n); od; @@ -1232,7 +1233,7 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, fp:=Range(fphom); gens:=MappingGeneratorsImages(fphom); imgs:=gens[2];gens:=gens[1]; - gens:=List(gens,x->PreImagesRepresentative(act,x)); + gens:=List(gens,x->PreImagesRepresentativeNC(act,x)); # adapt to normalize B gens:=List(gens,x->x/RepresentativeAction(t,b^x,b)); @@ -1240,11 +1241,11 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, # now do complements one by one for j in [1..Length(pcgs)] do h:=ClosureGroup(dser[j],gens); - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(h,fp, Concatenation(GeneratorsOfGroup(dser[j]),gens), Concatenation(List(GeneratorsOfGroup(dser[j]),x->One(fp)),imgs)); - RUN_IN_GGMBI:=false; + PopOptions(); ocr:=rec(group:=h,modulePcgs:=pcgs[j], factorfphom:=fphom); @@ -1256,18 +1257,18 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, if Size(b)>Size(s) then h:=ClosureGroup(b,gens); - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(h,fp, Concatenation(GeneratorsOfGroup(b),gens), Concatenation(List(GeneratorsOfGroup(b),x->One(fp)),imgs)); - RUN_IN_GGMBI:=false; + PopOptions(); # get elementary abelian series from b to s dser:=elabser(b,s); pcgs:=List([2..Length(dser)],x->ModuloPcgs(dser[x-1],dser[x])); for j in pcgs do - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=LiftFactorFpHom(fphom,Source(fphom),false,j); - RUN_IN_GGMBI:=false; + PopOptions(); od; gens:=MappingGeneratorsImages(fphom); imgs:=gens[2];gens:=gens[1]; @@ -1280,7 +1281,7 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, fp:=Image(fphom); gens:=MappingGeneratorsImages(fphom); imgs:=gens[2];gens:=gens[1]; - gens:=List(gens,x->PreImagesRepresentative(hom,x)); + gens:=List(gens,x->PreImagesRepresentativeNC(hom,x)); fi; # now run through the candidates for Hall in S @@ -1325,12 +1326,12 @@ local s,d,c,act,o,i,j,h,p,hf,img,n,k,ns,all,hl,hcomp, # now do complement to NS(k)/k for z in [1..Length(pcgs)] do h:=ClosureGroup(dser[z],cgens); - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(h,fp, Concatenation(GeneratorsOfGroup(dser[z]),cgens), Concatenation(List(GeneratorsOfGroup(dser[z]),x->One(fp)), imgs)); - RUN_IN_GGMBI:=false; + PopOptions(); ocr:=rec(group:=h,modulePcgs:=pcgs[z], factorfphom:=fphom); @@ -1408,13 +1409,14 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs, for s in HallsFittingFree(Image(hom),pi) do fphom:=IsomorphismFpGroup(s); fp:=Image(fphom); - sf:=List(GeneratorsOfGroup(Image(fphom)),x->PreImagesRepresentative(fphom,x)); - sg:=List(sf,x->PreImagesRepresentative(hom,x)); + sf:=List(GeneratorsOfGroup(Image(fphom)), + x->PreImagesRepresentativeNC(fphom,x)); + sg:=List(sf,x->PreImagesRepresentativeNC(hom,x)); sp:=[]; - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(Group(sg,One(G)),fp,sg, GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + PopOptions(); for d in [2..Length(ser.depths)] do mran:=[ser.depths[d-1]..len]; @@ -1429,9 +1431,9 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs, Append(sp,mpcgs); else # extend presentation - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=LiftFactorFpHom(fphom,Source(fphom),false,mpcgs); - RUN_IN_GGMBI:=false; + PopOptions(); fp:=Image(fphom); sp:=Concatenation(sp,mpcgs); fi; @@ -1443,10 +1445,10 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs, gens:=GeneratorsOfGroup(ocr.complement); sg:=gens{[1..Length(sg)]}; sp:=gens{[Length(sg)+1..Length(gens)]}; - RUN_IN_GGMBI:=true; # hack to skip Nice treatment + PushOptions( rec( Run_In_GGMBI:= true ) ); # hack to skip Nice treatment fphom:=GroupGeneralMappingByImagesNC(ocr.complement,fp,gens, GeneratorsOfGroup(fp)); - RUN_IN_GGMBI:=false; + PopOptions(); fi; od; diff --git a/lib/fldabnum.gi b/lib/fldabnum.gi index 5902772c5e..cfc60cc6d9 100644 --- a/lib/fldabnum.gi +++ b/lib/fldabnum.gi @@ -1918,9 +1918,10 @@ InstallMethod( PreImageElm, ############################################################################# ## +#M PreImagesElmNC( , ) . . . . . for autom. of ab. number fields #M PreImagesElm( , ) . . . . . . for autom. of ab. number fields ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for ANF automorphism and scalar", FamRangeEqFamElm, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], @@ -1929,12 +1930,23 @@ InstallMethod( PreImagesElm, mod Conductor( Range( aut ) ) ) ]; end ); +InstallMethod( PreImagesElm, + "for ANF automorphism and scalar", + FamRangeEqFamElm, + [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], + function ( aut, elm ) + if not ( elm in Range(aut) ) then + return fail; + fi; + return PreImagesElmNC( aut, elm ); + end ); ############################################################################# ## -#M PreImagesSet( , ) . . . . . for autom. of ab. number fields +#M PreImagesSetNC( , ) . . . . . for autom. of ab. number fields +#M PreImagesSet( , ) . . . . . . for autom. of ab. number fields ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for ANF automorphism and scalar", CollFamRangeEqFamElms, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsField ], @@ -1942,12 +1954,23 @@ InstallMethod( PreImagesSet, return F; end ); +InstallMethod( PreImagesSet, + "for ANF automorphism and scalar", + CollFamRangeEqFamElms, + [ IsFieldHomomorphism and IsANFAutomorphismRep, IsField ], + function ( aut, F ) + if not IsSubset( Range(aut), F ) then + return fail; + fi; + return PreImagesSetNC( aut, F ); + end ); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) for autom. of ab. number fields #M PreImagesRepresentative( , ) . for autom. of ab. number fields ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for ANF automorphism and scalar", FamRangeEqFamElm, [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], @@ -1956,6 +1979,16 @@ InstallMethod( PreImagesRepresentative, mod Conductor( Range( aut ) ) ); end ); +InstallMethod( PreImagesRepresentative, + "for ANF automorphism and scalar", + FamRangeEqFamElm, + [ IsFieldHomomorphism and IsANFAutomorphismRep, IsScalar ], + function ( aut, elm ) + if not ( elm in Range( aut ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( aut, elm ); + end ); ############################################################################# ## diff --git a/lib/ghom.gi b/lib/ghom.gi index bc217f1e32..29caa4a36b 100644 --- a/lib/ghom.gi +++ b/lib/ghom.gi @@ -253,9 +253,10 @@ end ); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . via images #M PreImagesRepresentative( , ) . . . . . . . . . . . via images -## -InstallMethod( PreImagesRepresentative, "for PBG-Hom", FamRangeEqFamElm, + +InstallMethod( PreImagesRepresentativeNC, "for PBG-Hom", FamRangeEqFamElm, [ IsPreimagesByAsGroupGeneralMappingByImages, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) @@ -264,8 +265,18 @@ function( hom, elm ) # group return ImagesRepresentative( RestrictedInverseGeneralMapping( hom ), elm ); else - return PreImagesRepresentative( AsGroupGeneralMappingByImages( hom ), elm ); + return PreImagesRepresentativeNC( AsGroupGeneralMappingByImages( hom ), elm ); + fi; +end ); + +InstallMethod( PreImagesRepresentative, "for PBG-Hom", FamRangeEqFamElm, + [ IsPreimagesByAsGroupGeneralMappingByImages, + IsMultiplicativeElementWithInverse ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; fi; + return PreImagesRepresentativeNC( hom, elm ); end ); InstallAttributeMethodByGroupGeneralMappingByImages( CoKernelOfMultiplicativeGeneralMapping ); @@ -875,9 +886,9 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . . for GHBI +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . . . for GHBI ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for GHBI and mult.-elm.-with-inverse", FamRangeEqFamElm, [ IsGroupGeneralMappingByImages, @@ -1225,9 +1236,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . for conjugator isomorphism +#M PreImagesRepresentativeNC( , ) . . . . for conjugator isomorphism ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for conjugator isomorphism", FamRangeEqFamElm, [ IsConjugatorIsomorphism, IsMultiplicativeElementWithInverse ], 0, @@ -1238,9 +1249,9 @@ InstallMethod( PreImagesRepresentative, ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . for conjugator isomorphism +#M PreImagesSetNC( , ) . . . . . . . . . for conjugator isomorphism ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for conjugator isomorphism, and group", CollFamRangeEqFamElms, [ IsConjugatorIsomorphism, IsGroup ], 0, diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index fcc83630d9..86d7fa5a9f 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -441,7 +441,7 @@ local q,r,tg,dtg,pemb,ugens,g,gi,d,o,gens,genims,i,gr,img,l,mapi; #better: orbit algo #r:=ShallowCopy(RightTransversal(q,qu)); #Sort(r,function(a,b) return 1^a<1^b;end); - #r:=List(r,i->PreImagesRepresentative(beta,i)); + #r:=List(r,i->PreImagesRepresentativeNC(beta,i)); # compute transversal with short words from orbit algorithm on points o:=[1]; @@ -527,9 +527,10 @@ end); ############################################################################# ## +#M PreImagesSetNC( , ) #M PreImagesSet( , ) ## -InstallMethod( PreImagesSet, "map from (sub)group of fp group", +InstallMethod( PreImagesSetNC, "map from (sub)group of fp group", CollFamRangeEqFamElms, [ IsFromFpGroupHomomorphism,IsGroup ],0, function(hom,u) @@ -624,6 +625,16 @@ local s,gens,t,p,w,c,q,chom,tg,thom,hi,i,lp,max; return SubgroupOfWholeGroupByQuotientSubgroup(FamilyObj(s),u,Stabilizer(u,1)); end); +InstallMethod( PreImagesSet, "map from (sub)group of fp group", + CollFamRangeEqFamElms, + [ IsFromFpGroupHomomorphism,IsGroup ],0, +function(hom,u) + if not IsSubset( Range(hom), u ) then + return fail; + fi; + return PreImagesSetNC(hom,u); +end); + ############################################################################# ## @@ -718,9 +729,10 @@ end); ############################################################################# ## +#M PreImagesRepresentativeNC #M PreImagesRepresentative ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "hom. to standard generators of fp group, using 'MappedWord'", FamRangeEqFamElm, [IsToFpGroupHomomorphismByImages,IsMultiplicativeElementWithInverse], @@ -747,6 +759,19 @@ local mapi; return mapi; end); +InstallMethod( PreImagesRepresentative, + "hom. to standard generators of fp group, using 'MappedWord'", + FamRangeEqFamElm, + [IsToFpGroupHomomorphismByImages,IsMultiplicativeElementWithInverse], + 1, +function(hom,elm) + if not (elm in Range(hom)) then + return fail; + fi; + return PreImagesRepresentativeNC(hom,elm); +end); + + ############################################################################# ## ## methods to construct homomorphisms to fp groups @@ -1282,7 +1307,7 @@ local v,aiu,aiv,G,primes,irrel,ma,mau,a,k,gens,imgs,q,dec,deco,piv,co; fi; gens:=SmallGeneratingSet(a); - imgs:=List(gens,x->Image(mau,Image(hom,PreImagesRepresentative(ma,x)))); + imgs:=List(gens,x->Image(mau,Image(hom,PreImagesRepresentativeNC(ma,x)))); q:=GroupHomomorphismByImages(a,Image(mau),gens,imgs); k:=KernelOfMultiplicativeGeneralMapping(q); @@ -1293,7 +1318,7 @@ local v,aiu,aiv,G,primes,irrel,ma,mau,a,k,gens,imgs,q,dec,deco,piv,co; dec:=EpimorphismFromFreeGroup(Group(gens)); deco:=function(x) local i; - x:=ExponentSums(PreImagesRepresentative(dec,x)); + x:=ExponentSums(PreImagesRepresentativeNC(dec,x)); for i in [1..Length(aiv)] do x[i]:=x[i] mod aiv[i]; od; @@ -1330,7 +1355,7 @@ local hom,pcgs,impcgs; impcgs:=FamilyPcgs(Image(hom,M)); pcgs:=PcgsByPcSequenceCons(IsPcgsDefaultRep,IsModuloPcgsFpGroupRep, ElementsFamily(FamilyObj(M)), - List(impcgs,i->PreImagesRepresentative(hom,i)), + List(impcgs,i->PreImagesRepresentativeNC(hom,i)), [] ); pcgs!.hom:=hom; diff --git a/lib/ghompcgs.gi b/lib/ghompcgs.gi index f17db8b36c..984f80f3f3 100644 --- a/lib/ghompcgs.gi +++ b/lib/ghompcgs.gi @@ -503,9 +503,10 @@ end); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . via images #M PreImagesRepresentative( , ) . . . . . . . . . . . via images ## -InstallMethod( PreImagesRepresentative, "method for pcgs hom", +InstallMethod( PreImagesRepresentativeNC, "method for pcgs hom", FamRangeEqFamElm, [ IsToPcGroupHomomorphismByImages,IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) @@ -530,6 +531,16 @@ function( hom, elm ) return pre; end); +InstallMethod( PreImagesRepresentative, "method for pcgs hom", + FamRangeEqFamElm, + [ IsToPcGroupHomomorphismByImages,IsMultiplicativeElementWithInverse ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #M NaturalHomomorphismByNormalSubgroup( , ) . . . . . . for pc groups @@ -627,9 +638,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . via depth map +#M PreImagesRepresentativeNC( , ) . . . . . . . . . via depth map ## -InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, +InstallMethod( PreImagesRepresentativeNC, FamRangeEqFamElm, [ IsPcgsToPcgsHomomorphism,IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) local exp; diff --git a/lib/ghomperm.gi b/lib/ghomperm.gi index 2f103a6a37..8b5c6a79dd 100644 --- a/lib/ghomperm.gi +++ b/lib/ghomperm.gi @@ -11,9 +11,9 @@ ############################################################################# ## -#M PreImagesSet( , ) . for s.p. gen. mapping resp. mult. & inv. +#M PreImagesSetNC( , ) . for s.p. gen. mapping resp. mult. & inv. ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for permgroup homs", CollFamRangeEqFamElms, [ IsPermGroupHomomorphism, IsGroup ], @@ -22,7 +22,7 @@ local genpreimages, pre,kg,sz,ol,orb,pos,dom,one; genpreimages:=GeneratorsOfMagmaWithInverses( elms ); genpreimages:= List(genpreimages, - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -1152,7 +1152,7 @@ local r, fgens, gens, kg; fi; fgens:=ShallowCopy(GeneratorsOfGroup(r)); gens:=List(fgens, - i->PreImagesRepresentative(hom2,PreImagesRepresentative(hom1,i))); + i->PreImagesRepresentativeNC(hom2,PreImagesRepresentativeNC(hom1,i))); kg:=GeneratorsOfGroup(KernelOfMultiplicativeGeneralMapping(hom2)); Append(gens,kg); Append(fgens,List(kg,i->One(r))); @@ -1162,15 +1162,26 @@ end); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . for perm group range #M PreImagesRepresentative( , ) . . . . . . for perm group range ## -InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, +InstallMethod( PreImagesRepresentativeNC, FamRangeEqFamElm, [ IsToPermGroupGeneralMappingByImages, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) return ImagesRepresentative( RestrictedInverseGeneralMapping( hom ), elm ); end ); +InstallMethod( PreImagesRepresentative, FamRangeEqFamElm, + [ IsToPermGroupGeneralMappingByImages, + IsMultiplicativeElementWithInverse ], 0, + function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #F StabChainPermGroupToPermGroupGeneralMappingByImages( ) . . . local @@ -1562,9 +1573,9 @@ InstallMethod( ImagesSource,"constituent homomorphism",true, ############################################################################# ## -#M PreImagesRepresentative( , ) +#M PreImagesRepresentativeNC( , ) ## -InstallMethod( PreImagesRepresentative,"constituent homomorphism", +InstallMethod( PreImagesRepresentativeNC,"constituent homomorphism", FamRangeEqFamElm,[IsConstituentHomomorphism,IsPerm], 0, function( hom, elm ) local D,DP; @@ -1579,9 +1590,9 @@ end); ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . . . . . . . . for const hom +#M PreImagesSetNC( , ) . . . . . . . . . . . . . . . for const hom ## -InstallMethod( PreImagesSet, "constituent homomorphism",CollFamRangeEqFamElms, +InstallMethod( PreImagesSetNC, "constituent homomorphism",CollFamRangeEqFamElms, [ IsConstituentHomomorphism, IsPermGroup ], 0, function( hom, I ) local H, # preimage of , result @@ -1594,7 +1605,7 @@ InstallMethod( PreImagesSet, "constituent homomorphism",CollFamRangeEqFamElms, # create the preimage group H := EmptyStabChain( [ ], One( Source( hom ) ) ); S := ConjugateStabChain( StabChainMutable( I ), H, x -> - PreImagesRepresentative( hom, x ), hom!.conperm ^ -1 ); + PreImagesRepresentativeNC( hom, x ), hom!.conperm ^ -1 ); T := H; while IsBound( T.stabilizer ) do AddGeneratorsExtendSchreierTree( T, GeneratorsOfGroup( K ) ); @@ -1817,9 +1828,9 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . for blocks hom +#M PreImagesRepresentativeNC( , ) . . . . . . . . for blocks hom ## -InstallMethod( PreImagesRepresentative, "blocks homomorphism", +InstallMethod( PreImagesRepresentativeNC, "blocks homomorphism", FamRangeEqFamElm, [ IsBlocksHomomorphism, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) @@ -1869,9 +1880,9 @@ end) ; ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . . . . . . . . for blocks hom +#M PreImagesSetNC( , ) . . . . . . . . . . . . . . for blocks hom ## -InstallMethod( PreImagesSet, CollFamRangeEqFamElms, +InstallMethod( PreImagesSetNC, CollFamRangeEqFamElms, [ IsBlocksHomomorphism, IsPermGroup ], 0, function( hom, I ) local H; # preimage of under , result @@ -1905,7 +1916,7 @@ InstallGlobalFunction( PreImageSetStabBlocksHomomorphism, function( hom, I ) H := PreImageSetStabBlocksHomomorphism( hom, I.stabilizer ); ChangeStabChain( H, [ pnt ], false ); for gen in I.generators do - pre := PreImagesRepresentative( hom, gen ); + pre := PreImagesRepresentativeNC( hom, gen ); if not IsBound( H.translabels[ pnt ^ pre ] ) then AddGeneratorsExtendSchreierTree( H, [ pre ] ); fi; diff --git a/lib/gpfpiso.gi b/lib/gpfpiso.gi index 202d9419a7..8095dd5be1 100644 --- a/lib/gpfpiso.gi +++ b/lib/gpfpiso.gi @@ -91,7 +91,7 @@ local l,iso,fp,stbc,gens; fp:=IsomorphismFpGroup(l); iso:=GroupHomomorphismByImagesNC(G,Range(fp), List(MappingGeneratorsImages(fp)[1], - i->PreImagesRepresentative(iso,i)), + i->PreImagesRepresentativeNC(iso,i)), MappingGeneratorsImages(fp)[2]); SetIsBijective(iso,true); return iso; @@ -171,8 +171,8 @@ function( G, str ) IsNaturalAlternatingGroup(H); new:=IsomorphismFpGroup(H,"@"); gensH:=List(GeneratorsOfGroup(Image(new)), - i->PreImagesRepresentative(new,i)); - preiH := List( gensH, x -> PreImagesRepresentative( hom, x ) ); + i->PreImagesRepresentativeNC(new,i)); + preiH := List( gensH, x -> PreImagesRepresentativeNC( hom, x ) ); c := Length( gensH ); @@ -190,7 +190,7 @@ function( G, str ) w := MappedWord( rel, gensT, gensE{[1..c]} ); t := MappedWord( rel, gensT, imgsE{[1..c]} ); if not t = One( G ) then - t := PreImagesRepresentative( free, t ); + t := PreImagesRepresentativeNC( free, t ); t := MappedWord( t, gensF, gensE{[c+1..n+c]} ); else t := One( E ); @@ -204,7 +204,7 @@ function( G, str ) w := Comm( gensE[c+j], gensE[i] ); t := Comm( imgsE[c+j], imgsE[i] ); if not t = One( G ) then - t := PreImagesRepresentative( free, t ); + t := PreImagesRepresentativeNC( free, t ); t := MappedWord( t, gensF, gensE{[c+1..n+c]} ); else t := One( E ); @@ -293,7 +293,7 @@ function(g,str,N) gens:=Union(gens,Union(List(ser,SmallGeneratingSet))); fi; if f<>g then - gens:=List(gens,x->PreImagesRepresentative(hom,x)); + gens:=List(gens,x->PreImagesRepresentativeNC(hom,x)); ser:=List(ser,x->PreImage(hom,x)); fi; # change generators to make split @@ -397,7 +397,8 @@ function(g,str,N) fgens:=GeneratorsOfGroup(f); auts:=List(GeneratorsOfGroup(g),i-> GroupHomomorphismByImagesNC(f,f,fgens, - List(fgens,j->Image(hom,PreImagesRepresentative(hom,j)^i)):noassert)); + List(fgens, + j->Image(hom,PreImagesRepresentativeNC(hom,j)^i)):noassert)); for j in auts do SetIsBijective(j,true); od; @@ -426,7 +427,7 @@ function(g,str,N) else a:=IsomorphismFpGroup(sf:noassert); fi; - ad:=List(GeneratorsOfGroup(Range(a)),i->PreImagesRepresentative(a,i)); + ad:=List(GeneratorsOfGroup(Range(a)),i->PreImagesRepresentativeNC(a,i)); lad:=Length(ad); n:=Length(orb); @@ -461,7 +462,7 @@ function(g,str,N) fp:=fg/rels; a:=GroupHomomorphismByImagesNC(f,fp,fgens,GeneratorsOfGroup(fp):noassert); fi; - Append(gens,List(fgens,i->PreImagesRepresentative(hom,i))); + Append(gens,List(fgens,i->PreImagesRepresentativeNC(hom,i))); # here we really want a composed homomorphism, to avoid extra work for # a new stabilizer chain @@ -640,7 +641,7 @@ local fpq, qgens, qreps, fpqg, rels, pcgs, p, f, qimg, idx, nimg, decomp, ngen, fp, hom2, di, source, dih, dec, i, j; fpq:=Range(hom); qgens:=GeneratorsOfGroup(fpq); - qreps:=List(qgens,i->PreImagesRepresentative(hom,i)); + qreps:=List(qgens,i->PreImagesRepresentativeNC(hom,i)); fpqg:=FreeGeneratorsOfFpGroup(fpq); rels:=[]; if IsModuloPcgs(mnsf) then @@ -694,7 +695,7 @@ local fpq, qgens, qreps, fpqg, rels, pcgs, p, f, qimg, idx, nimg, decomp, ngen:=FreeGeneratorsOfFpGroup(p); # This is not really a pcgs, but treated as layer generators the same # way, thus use the same variable name - pcgs:=List(GeneratorsOfGroup(p),i->PreImagesRepresentative(mnsf,i)); + pcgs:=List(GeneratorsOfGroup(p),i->PreImagesRepresentativeNC(mnsf,i)); f:=FreeGroup(Length(fpqg)+Length(pcgs)); qimg:=GeneratorsOfGroup(f){[1..Length(fpqg)]}; idx:=[Length(fpqg)+1..Length(fpqg)+Length(pcgs)]; @@ -966,7 +967,7 @@ function( G, series, str ) gensH := GeneratorsOfGroup( H ); gensH := Filtered( gensH, x -> x <> One(H) ); - preiH := List( gensH, x -> PreImagesRepresentative( hom, x ) ); + preiH := List( gensH, x -> PreImagesRepresentativeNC( hom, x ) ); c := Length( gensH ); # compute presentation of H @@ -989,7 +990,7 @@ function( G, series, str ) w := MappedWord( rel, gensT, gensE{[1..c]} ); t := MappedWord( rel, gensT, imgsE{[1..c]} ); if not t = One( G ) then - t := PreImagesRepresentative( free, t ); + t := PreImagesRepresentativeNC( free, t ); t := MappedWord( t, gensF, gensE{[c+1..n+c]} ); else t := One( E ); @@ -1003,7 +1004,7 @@ function( G, series, str ) w := Comm( gensE[c+j], gensE[i] ); t := Comm( imgsE[c+j], imgsE[i] ); if not t = One( G ) then - t := PreImagesRepresentative( free, t ); + t := PreImagesRepresentativeNC( free, t ); t := MappedWord( t, gensF, gensE{[c+1..n+c]} ); else t := One( E ); @@ -1228,8 +1229,8 @@ local iso,fp,dec,homs,mos,i,j,ffp,imo,m,k,gens,fm,mgens,rules, for r in Rules(k) do left:=MappedWord(r[1],FreeGeneratorsOfFpMonoid(m),monreps); right:=MappedWord(r[2],FreeGeneratorsOfFpMonoid(m),monreps); - diff:=LeftQuotient(PreImagesRepresentative(iso,right), - PreImagesRepresentative(iso,left)); + diff:=LeftQuotient(PreImagesRepresentativeNC(iso,right), + PreImagesRepresentativeNC(iso,left)); diff:=ImagesRepresentative(iso,diff); left:=MappedWord(r[1],FreeGeneratorsOfFpMonoid(m),monreal); @@ -1248,7 +1249,7 @@ local iso,fp,dec,homs,mos,i,j,ffp,imo,m,k,gens,fm,mgens,rules, if reduce(mgens[k])=mgens[k] then right:=fmgens[j]^-1*fmgens[k]*fmgens[j]; #collect - right:=ImagesRepresentative(iso,PreImagesRepresentative(iso,right)); + right:=ImagesRepresentative(iso,PreImagesRepresentativeNC(iso,right)); right:=Product(List(LetterRepAssocWord(UnderlyingElement(right)), x->mgens[Position(nums,x)])); right:=reduce(mgens[j]*right); @@ -1320,7 +1321,7 @@ local pcgs,iso,fp,i,j,gens,numi,ord,fm,fam,mword,k,r,addrule,a,e,m; pcgs:=Pcgs(G); iso:=IsomorphismFpGroup(G); fp:=Range(iso); - if List(GeneratorsOfGroup(fp),x->PreImagesRepresentative(iso,x))<>pcgs then + if List(GeneratorsOfGroup(fp),x->PreImagesRepresentativeNC(iso,x))<>pcgs then Error("pcgs"); fi; gens:=[]; @@ -1520,7 +1521,7 @@ local iso,n,fn,sz,bigcount,tryweyl; iso:=IsomorphismGroups(G,P); if iso<>fail then P:=List(GeneratorsOfGroup(H), - x->PreImagesRepresentative(iso,ImagesRepresentative(isp,x))); + x->PreImagesRepresentativeNC(iso,ImagesRepresentative(isp,x))); iso:=GroupHomomorphismByImagesNC(G,H,P,GeneratorsOfGroup(H)); fi; return iso; @@ -1728,13 +1729,13 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, # force going to pc group, as this will give better ordering isob:=GroupHomomorphismByFunction(borel,Range(cb.fphom), x->ImagesRepresentative(cb.fphom,ImagesRepresentative(pciso,x)), - x->PreImagesRepresentative(pciso,PreImagesRepresentative(cb.fphom,x))); + x->PreImagesRepresentativeNC(pciso,PreImagesRepresentativeNC(cb.fphom,x))); b:=Range(isob); wgens:=GeneratorsOfGroup(weyl); - bgens:=List(GeneratorsOfGroup(b),x->PreImagesRepresentative(isob,x)); + bgens:=List(GeneratorsOfGroup(b),x->PreImagesRepresentativeNC(isob,x)); if newstyle and bgens<>GeneratorsOfGroup(borel) then Error("gens");fi; bpairs:=Concatenation(List(bgens,x->[x,x^-1])); @@ -1879,7 +1880,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, x:=UnderlyingElement(ImagesRepresentative(cb.monhom,x)); x:=reduce(x,RelationsOfFpMonoid(monoid),mdag,fail); x:=ElementOfFpMonoid(FamilyObj(One(monoid)),x); - return PreImagesRepresentative(cb.monhom,x); + return PreImagesRepresentativeNC(cb.monhom,x); end; mdag:=EmptyKBDAG(Union(List(FreeGeneratorsOfFpMonoid(monoid), @@ -1924,7 +1925,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, x:=UnderlyingElement(ImagesRepresentative(cs.monhom,x)); x:=reduce(x,RelationsOfFpMonoid(Range(cs.monhom)),wdag,fail); x:=ElementOfFpMonoid(FamilyObj(One(Range(cs.monhom))),x); - return PreImagesRepresentative(cs.monhom,x); + return PreImagesRepresentativeNC(cs.monhom,x); end; wdag:=EmptyKBDAG(Union(List(FreeGeneratorsOfFpMonoid(Range(cs.monhom)), @@ -1966,7 +1967,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, a:=Group(SmallGeneratingSet(group)); # so nothing stores csetperm:=List(GeneratorsOfGroup(a),x->Permutation(x,rt,OnRight)); iso:=EpimorphismFromFreeGroup(a); - csetperm:=List(bgens,x->MappedWord(PreImagesRepresentative(iso,x), + csetperm:=List(bgens,x->MappedWord(PreImagesRepresentativeNC(iso,x), MappingGeneratorsImages(iso)[1],csetperm)); act:=Group(csetperm,()); @@ -2014,7 +2015,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, a:=PositionCanonical(rt,elm); b:=rti[a]; rep:=RepresentativeAction(Image(bhom),a,dcnums[b][1]); - rep:=PreImagesRepresentative(bhom,rep); + rep:=PreImagesRepresentativeNC(bhom,rep); if single then a:=[CanonicalRightCosetElement(ac[1],rt[dcnums[b][1]]),rep]; else @@ -2074,9 +2075,8 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, # a:=Group(SmallGeneratingSet(group)); # so nothing stores # csetperm:=List(GeneratorsOfGroup(a),x->Permutation(x,rt,OnRight)); # iso:=EpimorphismFromFreeGroup(a); -# csetperm:=List(bgens,x->MappedWord(PreImagesRepresentative(iso,x),MappingGeneratorsImages(iso)[1],csetperm)); -# act:=Group(csetperm,()); -# +# csetperm:=List(bgens,x->MappedWord(PreImagesRepresentativeNC(iso,x), +# MappingGeneratorsImages(iso)[1],csetperm)); act:=Group(csetperm,()); # bhom:=GroupHomomorphismByImagesNC(borel,act,bgens,csetperm); # #Assert(0,bhom<>fail); # @@ -2119,7 +2119,7 @@ local isob,isos,iso,gens,a,rels,l,i,j,bgens,cb,cs,b,f,k,w,monoid, # pos:=rti[PositionCanonical(rt,elm)]; # #rep:=RepresentativeAction(borel,PositionCanonical(rt,elm), # # PositionCanonical(rt,dcreps[pos]),bgens,csetperm,OnPoints); -# rep:=PreImagesRepresentative(bhom, +# rep:=PreImagesRepresentativeNC(bhom, # RepresentativeAction(Range(bhom),PositionCanonical(rt,elm), # PositionCanonical(rt,dcreps[pos]))); # rep:=[elm*rep/dcreps[pos],dcreps[pos],rep^-1]; @@ -2441,7 +2441,7 @@ if rule[1]=rule[2] then return;fi; else # BN-style reductions - pcgs:=List(GeneratorsOfGroup(b),x->PreImagesRepresentative(isob,x)); + pcgs:=List(GeneratorsOfGroup(b),x->PreImagesRepresentativeNC(isob,x)); # remove powers pcgs:=pcgs{ Filtered([1..Length(pcgs)],i->not ForAny([1..i-1], @@ -2455,7 +2455,7 @@ if rule[1]=rule[2] then return;fi; # which elements b*i can we write as i*\tilde b. Then b^i=\tilde b, that # is b\in B\cvap B^(i^-1) - pri:=PreImagesRepresentative(isos,i); + pri:=PreImagesRepresentativeNC(isos,i); stb:=Intersection(borel,borel^(pri^-1)); Info(InfoFpGroup,2,i," ",Size(stb)); @@ -2511,14 +2511,14 @@ if rule[1]=rule[2] then return;fi; Info(InfoFpGroup,3,"borelrun ",Position(wo,i)," of ",Length(wo)); # rewrite i*b*j as \tilde b*k*\hat b. - pri:=PreImagesRepresentative(isos,i); + pri:=PreImagesRepresentativeNC(isos,i); stb:=Intersection(borel^pri,borel); for j in wo do Info(InfoFpGroup,2,"DC:",i,", ",j," from ",Length(rels)); for k in borelelm do #RightTransversal(borel,stb) do - a:=PreImagesRepresentative(isos,i)*k* - PreImagesRepresentative(isos,j); + a:=PreImagesRepresentativeNC(isos,i)*k* + PreImagesRepresentativeNC(isos,j); a:=decomp(a); a:=[nofob(ImagesRepresentative(isob,a[1])), nofow(ImagesRepresentative(isos,a[2])), @@ -2684,7 +2684,7 @@ end); # if List(mg,x->LetterRepAssocWord(UnderlyingElement(x)))<> # List([1..Length(mg)],x->[x]) then Error("gens!"); fi; # pre:=List(mg,x->LetterRepAssocWord(UnderlyingElement( -# PreImagesRepresentative(miso,x)))); +# PreImagesRepresentativeNC(miso,x)))); # if ForAny(pre,x->Length(x)<>1) then Error("double");fi; # Add(l,Concatenation(pre)); # if IsBound(m!.rewritingSystem) then @@ -2896,7 +2896,7 @@ local d,f,group,act,g,sy,b,c,borel,weyl,a,i,iso,ucs,gens,gl; fi; c:=c[1]; a:=SubgroupNC(group,List(GeneratorsOfGroup(weyl), - x->PreImagesRepresentative(c,x))); + x->PreImagesRepresentativeNC(c,x))); Size(a); a!.epiweyl:=weyl; weyl:=a; diff --git a/lib/gpprmsya.gi b/lib/gpprmsya.gi index a88508a2bb..d0af65692e 100644 --- a/lib/gpprmsya.gi +++ b/lib/gpprmsya.gi @@ -1265,7 +1265,7 @@ syll, act, typ, sel, bas, wdom, comp, lperm, other, away, i, j,b0,opg,bp; w:=AutomorphismGroup(b); opg:=NaturalHomomorphismByNormalSubgroupNC(w, InnerAutomorphismsAutomorphismGroup(w)); - ll:=List(AsSSortedList(Image(opg)),x->PreImagesRepresentative(opg,x)); + ll:=List(AsSSortedList(Image(opg)),x->PreImagesRepresentativeNC(opg,x)); ll:=Filtered(ll,IsConjugatorAutomorphism); ll:=List(ll,ConjugatorInnerAutomorphism); pg:=b; diff --git a/lib/gprd.gi b/lib/gprd.gi index e32bf13af7..49b091d983 100644 --- a/lib/gprd.gi +++ b/lib/gprd.gi @@ -715,7 +715,7 @@ InstallGlobalFunction(InnerSubdirectProducts2,function( D, U, V ) # and obtain double coset reps reps := List( DoubleCosets( P, autU, autV ), Representative ); - reps := List( reps, x -> PreImagesRepresentative( gamma, x ) ); + reps := List( reps, x -> PreImagesRepresentativeNC( gamma, x ) ); # loop over automorphisms for rep in reps do @@ -724,9 +724,9 @@ InstallGlobalFunction(InnerSubdirectProducts2,function( D, U, V ) gens := Concatenation( GeneratorsOfGroup( N ), GeneratorsOfGroup( M ) ); for r in GeneratorsOfGroup( UN ) do - g := PreImagesRepresentative( pair[1], r ); + g := PreImagesRepresentativeNC( pair[1], r ); h := Image( iso, Image( rep, r ) ); - h := PreImagesRepresentative( pair[2], h ); + h := PreImagesRepresentativeNC( pair[2], h ); Add( gens, g * h ); od; S := SubgroupNC( D, gens ); @@ -1094,7 +1094,7 @@ local info,map,U,mapfun,P; function(elm) elm:=elm![n]; if n>info.degI then - elm:=PreImagesRepresentative(info.alpha,elm); + elm:=PreImagesRepresentativeNC(info.alpha,elm); fi; return elm; end); @@ -1118,7 +1118,7 @@ local info,map,np; map:=GroupHomomorphismByFunction(G,info.groups[2], function(elm) - return PreImagesRepresentative(info.alpha,elm![np]); + return PreImagesRepresentativeNC(info.alpha,elm![np]); end, false, # not bijective function(elm) @@ -1179,7 +1179,7 @@ local giso,niso,P,gens,a,Go,No,i; N:=Image(niso,N); gens:=[]; for i in GeneratorsOfGroup(G) do - i:=Image(aut,PreImagesRepresentative(giso,i)); + i:=Image(aut,PreImagesRepresentativeNC(giso,i)); i:=InducedAutomorphism(niso,i); Add(gens,i); od; @@ -1220,9 +1220,9 @@ local Go,No,giso,niso,FG,GP,FN,NP,F,GI,NI,rels,i,j,P; N:=Image(niso,N); FG:=FreeGeneratorsOfFpGroup(G); - GP:=List(GeneratorsOfGroup(G),x->PreImagesRepresentative(giso,x)); + GP:=List(GeneratorsOfGroup(G),x->PreImagesRepresentativeNC(giso,x)); FN:=FreeGeneratorsOfFpGroup(N); - NP:=List(GeneratorsOfGroup(N),x->PreImagesRepresentative(niso,x)); + NP:=List(GeneratorsOfGroup(N),x->PreImagesRepresentativeNC(niso,x)); F:=FreeGroup(List(Concatenation(FG,FN),String)); GI:=GeneratorsOfGroup(F){[1..Length(FG)]}; diff --git a/lib/gprdmat.gi b/lib/gprdmat.gi index 2480d861d1..d73b63e568 100644 --- a/lib/gprdmat.gi +++ b/lib/gprdmat.gi @@ -143,9 +143,10 @@ end); ############################################################################# ## -#M PreImagesRepresentative(,) . . . . . . . . . . . of embedding +#M PreImagesRepresentativeNC(,) . . . . . . . . . . . of embedding +#M PreImagesRepresentative(,) . . . . . . . . . . . . of embedding ## -InstallMethod(PreImagesRepresentative,"matrix direct product embedding", +InstallMethod(PreImagesRepresentativeNC,"matrix direct product embedding", FamRangeEqFamElm, [ IsEmbeddingDirectProductMatrixGroup, IsMultiplicativeElementWithInverse ], @@ -162,6 +163,17 @@ local info,a,b; fi; end); +InstallMethod(PreImagesRepresentative,"matrix direct product embedding", + FamRangeEqFamElm, + [ IsEmbeddingDirectProductMatrixGroup, + IsMultiplicativeElementWithInverse ], +function(emb,g) + if not (g in Range(emb)) then + return fail; + fi; + return PreImagesRepresentativeNC(emb,g); +end); + ############################################################################# ## #R IsProjectionDirectProductMatrixGroup() projection onto direct factor @@ -206,9 +218,10 @@ end); ############################################################################# ## -#M PreImagesRepresentative(,) . . . . . . . . . . . of projection +#M PreImagesRepresentativeNC(,) . . . . . . . . . . . of projection +#M PreImagesRepresentative(,) . . . . . . . . . . . . of projection ## -InstallMethod(PreImagesRepresentative,"matrix direct product projection", +InstallMethod(PreImagesRepresentativeNC,"matrix direct product projection", FamRangeEqFamElm, [ IsProjectionDirectProductMatrixGroup, IsMultiplicativeElementWithInverse ],0, @@ -220,6 +233,17 @@ local info,a; return ImmutableMatrix(info.field,a); end); +InstallMethod(PreImagesRepresentative,"matrix direct product projection", + FamRangeEqFamElm, + [ IsProjectionDirectProductMatrixGroup, + IsMultiplicativeElementWithInverse ],0, +function(prj,m) + if not (m in Range(prj)) then + return fail; + fi; + return PreImagesRepresentativeNC(prj,m); +end); + ############################################################################# ## #M KernelOfMultiplicativeGeneralMapping() . . . . . . . of projection @@ -382,9 +406,10 @@ end); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of embedding +#M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "imprim matrix wreath product embedding", FamRangeEqFamElm, [ IsEmbeddingImprimitiveWreathProductMatrixGroup, IsMultiplicativeElementWithInverse ], 0, @@ -401,6 +426,16 @@ local info,a,b; fi; end); +InstallMethod( PreImagesRepresentative, + "imprim matrix wreath product embedding", FamRangeEqFamElm, + [ IsEmbeddingImprimitiveWreathProductMatrixGroup, + IsMultiplicativeElementWithInverse ], 0, +function( emb, g ) + if not (g in Range(emb)) then + return fail; + fi; + return PreImagesRepresentativeNC(emb,g); +end); ############################################################################# ## diff --git a/lib/gprdpc.gi b/lib/gprdpc.gi index 6994897c39..a17e46436a 100644 --- a/lib/gprdpc.gi +++ b/lib/gprdpc.gi @@ -421,7 +421,7 @@ local pg,ph,kg,kh,ig,ih,mg,mh,S,info; ig:=InducedPcgs(pg,kg); ih:=InducedPcgs(ph,kh); mg:=pg mod ig; - mh:=List(mg,i->PreImagesRepresentative(hh,Image(gh,i))); + mh:=List(mg,i->PreImagesRepresentativeNC(hh,Image(gh,i))); pg:=Concatenation(mg,ig,List(ih,i->One(G))); ph:=Concatenation(mh,List(ig,i->One(H)),ih); S:=SubdirProdPcGroups(G,pg,H,ph); diff --git a/lib/gprdperm.gi b/lib/gprdperm.gi index 327f812adc..75583f7a0d 100644 --- a/lib/gprdperm.gi +++ b/lib/gprdperm.gi @@ -169,9 +169,10 @@ end ); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of embedding #M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding ## -InstallMethod( PreImagesRepresentative, "perm direct product embedding", +InstallMethod( PreImagesRepresentativeNC, "perm direct product embedding", FamRangeEqFamElm, [ IsEmbeddingDirectProductPermGroup, IsMultiplicativeElementWithInverse ], @@ -191,6 +192,17 @@ InstallMethod( PreImagesRepresentative, "perm direct product embedding", fi; end ); +InstallMethod( PreImagesRepresentative, "perm direct product embedding", + FamRangeEqFamElm, + [ IsEmbeddingDirectProductPermGroup, + IsMultiplicativeElementWithInverse ], + function( emb, g ) + if not ( g in Range( emb ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( emb, g ); +end ); + ############################################################################# ## #M ImagesSource( ) . . . . . . . . . . . . . . . . . . . of embedding @@ -292,9 +304,10 @@ end ); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of projection #M PreImagesRepresentative( , ) . . . . . . . . . . . of projection ## -InstallMethod( PreImagesRepresentative,"perm direct product projection", +InstallMethod( PreImagesRepresentativeNC,"perm direct product projection", FamRangeEqFamElm, [ IsProjectionDirectProductPermGroup, IsMultiplicativeElementWithInverse ], 0, @@ -302,6 +315,17 @@ InstallMethod( PreImagesRepresentative,"perm direct product projection", return g ^ DirectProductInfo( Source( prj ) ).perms[ prj!.component ]; end ); +InstallMethod( PreImagesRepresentative,"perm direct product projection", + FamRangeEqFamElm, + [ IsProjectionDirectProductPermGroup, + IsMultiplicativeElementWithInverse ], 0, + function( prj, g ) + if not ( g in Range( prj ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( prj, g ); +end ); + ############################################################################# ## #M KernelOfMultiplicativeGeneralMapping( ) . . . . . . . of projection @@ -388,7 +412,7 @@ InstallMethod( SubdirectProductOp,"permgroup", true, # over the generators of the kernel of $phi_2$. gens := []; for gen in GeneratorsOfGroup( G1 ) do - Add( gens, gen^emb1 * PreImagesRepresentative(phi2,gen^phi1)^emb2 ); + Add( gens, gen^emb1 * PreImagesRepresentativeNC(phi2,gen^phi1)^emb2 ); od; for gen in GeneratorsOfGroup( KernelOfMultiplicativeGeneralMapping( phi2 ) ) do @@ -466,9 +490,10 @@ end ); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of projection #M PreImagesRepresentative( , ) . . . . . . . . . . . of projection ## -InstallMethod( PreImagesRepresentative,"perm subdirect product projection", +InstallMethod( PreImagesRepresentativeNC,"perm subdirect product projection", FamRangeEqFamElm, [ IsProjectionSubdirectProductPermGroup, IsMultiplicativeElementWithInverse ], 0, @@ -487,17 +512,28 @@ InstallMethod( PreImagesRepresentative,"perm subdirect product projection", # compute the preimage if 1 = prj!.component then - elm := img ^ info.perms[1] - * PreImagesRepresentative(phi2,img^phi1) ^ info.perms[2]; + elm := img ^ info.perms[1] + * PreImagesRepresentativeNC(phi2,img^phi1) ^ info.perms[2]; else - elm := img ^ info.perms[2] - * PreImagesRepresentative(phi1,img^phi2) ^ info.perms[1]; + elm := img ^ info.perms[2] + * PreImagesRepresentativeNC(phi1,img^phi2) ^ info.perms[1]; fi; # return the preimage return elm; end ); +InstallMethod( PreImagesRepresentative,"perm subdirect product projection", + FamRangeEqFamElm, + [ IsProjectionSubdirectProductPermGroup, + IsMultiplicativeElementWithInverse ], 0, + function( prj, img ) + if not ( img in Range( prj ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( prj, img ); +end ); + ############################################################################# ## #M KernelOfMultiplicativeGeneralMapping( ) . . . . . . . of projection @@ -799,9 +835,10 @@ end ); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . of embedding #M PreImagesRepresentative( , ) . . . . . . . . . . . of embedding ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "imprim perm wreath product embedding", FamRangeEqFamElm, [ IsEmbeddingImprimitiveWreathProductPermGroup, IsMultiplicativeElementWithInverse ], 0, @@ -820,6 +857,16 @@ InstallMethod( PreImagesRepresentative, ^ (info.perms[ emb!.component ] ^ -1); end ); +InstallMethod( PreImagesRepresentative, + "imprim perm wreath product embedding", FamRangeEqFamElm, + [ IsEmbeddingImprimitiveWreathProductPermGroup, + IsMultiplicativeElementWithInverse ], 0, + function( emb, g ) + if not ( g in Range( emb ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( emb, g ); +end ); ############################################################################# ## diff --git a/lib/grp.gd b/lib/grp.gd index f9127d72c0..2a83f80eba 100644 --- a/lib/grp.gd +++ b/lib/grp.gd @@ -4250,8 +4250,8 @@ DeclareGlobalFunction( "AllSmallNonabelianSimpleGroups" ); ## returns an isomorphism from G onto an isomorphic pc group. ## The series chosen for this pc representation depends on ## the method chosen. -## G must be a polycyclic group of any kind, for example a solvable -## permutation group. +## G must be a finite polycyclic group of any kind, for example a solvable +## permutation group. If G is finite but not solvable, fail is returned. ## G := Group( (1,2,3), (3,4,1) );; ## gap> iso := IsomorphismPcGroup( G ); @@ -4278,8 +4278,8 @@ DeclareAttribute( "IsomorphismPcGroup", IsGroup ); ## returns an isomorphism from G onto an isomorphic pc group ## whose family pcgs is a special pcgs. ## (This can be beneficial to the runtime of calculations.) -## G may be a polycyclic group of any kind, for example a solvable -## permutation group. +## G must be a finite polycyclic group of any kind, for example a solvable +## permutation group. If G is finite but not solvable, fail is returned. ## ## ## <#/GAPDoc> diff --git a/lib/grp.gi b/lib/grp.gi index e46a66da6f..27f3644271 100644 --- a/lib/grp.gi +++ b/lib/grp.gi @@ -515,12 +515,12 @@ local p, hom, reps, as, a, b, ap, bp, ab, ap_bp, ab_p, g, h, H, N; reps := ConjugacyClasses(Image(hom)); reps := List(reps, Representative); reps := Filtered(reps, g -> not IsOne(g)); - reps := List(reps, g -> PreImagesRepresentative(hom, g)); + reps := List(reps, g -> PreImagesRepresentativeNC(hom, g)); as := List(reps, a -> [a,a^p]); for b in Image(hom) do - b := PreImagesRepresentative(hom, b); + b := PreImagesRepresentativeNC(hom, b); bp := b^p; for a in as do ap := a[2]; a := a[1]; @@ -1793,7 +1793,7 @@ local hom,gens; fi; hom:=IsomorphismPermGroup(G); gens:=IndependentGeneratorsOfAbelianGroup(Image(hom,G)); - return List(gens,i->PreImagesRepresentative(hom,i)); + return List(gens,i->PreImagesRepresentativeNC(hom,i)); end); @@ -2090,8 +2090,8 @@ InstallGlobalFunction( SupersolvableResiduumDefault, function( G ) # dual space of the module, w.r.t. `pcgs'. mg:= List( gs, x -> TransposedMat( List( pcgs, y -> one * ExponentsOfPcElement( pcgs, Image( ph, - Image( dh, PreImagesRepresentative( - dh, PreImagesRepresentative(ph,y) )^x ) ) )))^-1); + Image( dh, PreImagesRepresentativeNC( + dh, PreImagesRepresentativeNC(ph,y) )^x ) ) )))^-1); #T inverting is not necessary, or? mg:= Filtered( mg, x -> x <> idm ); @@ -2141,11 +2141,11 @@ InstallGlobalFunction( SupersolvableResiduumDefault, function( G ) # Construct a group element corresponding to # the basis element of the submodule. - Add( tmp2, PreImagesRepresentative( ph, + Add( tmp2, PreImagesRepresentativeNC( ph, PcElementByExponentsNC( pcgs, v ) ) ); od; - Add( ds, PreImagesSet( dh, + Add( ds, PreImagesSetNC( dh, SubgroupNC( df, Concatenation( tmp2, gen ) ) ) ); od; Append( gen, tmp2 ); @@ -2154,14 +2154,14 @@ InstallGlobalFunction( SupersolvableResiduumDefault, function( G ) else # cyclic case - Add( ds, PreImagesSet( dh, + Add( ds, PreImagesSetNC( dh, SubgroupNC( df, AsSSortedList( gen ) ) ) ); fi; od; # Generate the new candidate. - ssr:= PreImagesSet( dh, SubgroupNC( df, AsSSortedList( gen ) ) ); + ssr:= PreImagesSetNC( dh, SubgroupNC( df, AsSSortedList( gen ) ) ); fi; @@ -2392,7 +2392,7 @@ InstallMethod( UpperCentralSeriesOfGroup, Add( S, C ); Info( InfoGroup, 2, "UpperCentralSeriesOfGroup: step ", Length(S) ); hom := NaturalHomomorphismByNormalSubgroupNC( G, C ); - C := PreImages( hom, Centre( Image( hom ) ) ); + C := PreImagesNC( hom, Centre( Image( hom ) ) ); od; if Last(S) = G then @@ -3598,7 +3598,7 @@ InstallMethod( HallSubgroupOp, iso := IsomorphismPermGroup( G ); H := HallSubgroup( ImagesSource( iso ), pi ); - return PreImagesSet(iso, H); + return PreImagesSetNC(iso, H); end ); @@ -5337,7 +5337,7 @@ InstallMethod (MinimalNormalSubgroups, local hom; hom := NiceMonomorphism (grp); return List (MinimalNormalSubgroups (NiceObject (grp)), - N -> PreImagesSet (hom, N)); + N -> PreImagesSetNC(hom, N)); end); diff --git a/lib/grpcompl.gi b/lib/grpcompl.gi index 9adf68a175..5058cd8610 100644 --- a/lib/grpcompl.gi +++ b/lib/grpcompl.gi @@ -100,11 +100,11 @@ local G,N,K,s, h, q, fpi, factorpres, com, comgens, cen, ocrels, fpcgs, ncom, factorpres:=[FreeGeneratorsOfFpGroup(Range(fpi)), RelatorsOfFpGroup(Range(fpi)), List(GeneratorsOfGroup(Range(fpi)), - i->PreImagesRepresentative(fpi,i))]; - Assert(1,ForAll(factorpres[3],i->Image(h,PreImagesRepresentative(h,i))=i)); + i->PreImagesRepresentativeNC(fpi,i))]; + Assert(1,ForAll(factorpres[3],i->Image(h,PreImagesRepresentativeNC(h,i))=i)); # initialize com:=[G]; - comgens:=[List(factorpres[3],i->PreImagesRepresentative(h,i))]; + comgens:=[List(factorpres[3],i->PreImagesRepresentativeNC(h,i))]; cen:=[s[1]]; ocrels:=false; diff --git a/lib/grpfp.gd b/lib/grpfp.gd index eaa41d6421..8e373a6ec3 100644 --- a/lib/grpfp.gd +++ b/lib/grpfp.gd @@ -90,9 +90,9 @@ fi; ## [5] CosetTableInWholeGroup( H ) ## @ GAPROOT/lib/grpfp.gi:1733 ## ... at *stdin*:3 -## type 'return;' if you want to continue with a new limit of 8192000 cosets, -## type 'quit;' if you want to quit the coset enumeration, -## type 'maxlimit := 0; return;' in order to continue without a limit +## you can enter 'return;' to continue with a new limit of 8192000 cosets, +## you can enter 'quit;' to abort the coset enumeration, +## you can enter 'maxlimit := 0; return;' in order to continue without a limit ## brk> quit; ## ]]> ##

diff --git a/lib/grpfp.gi b/lib/grpfp.gi index 8f9d97983b..414ee482c8 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -319,7 +319,7 @@ local fam,hom; if hom=fail then TryNextMethod(); fi; - return PreImagesRepresentative(hom,Random(rs, Image(hom,gp))); + return PreImagesRepresentativeNC(hom,Random(rs, Image(hom,gp))); end ); ############################################################################# @@ -1113,10 +1113,10 @@ BindGlobal("GTC_CosetTableFromGensAndRels",function(arg) # to give tidy instructions if one enters a break-loop SavedOnBreakMessage := OnBreakMessage; TCEOnBreakMessage := function(n) - Print( "type 'return;' if you want to continue with a new limit of ", + Print( "you can enter 'return;' to continue with a new limit of ", n, " cosets,\n", - "type 'quit;' if you want to quit the coset enumeration,\n", - "type 'maxlimit := 0; return;' in order to continue without a ", + "you can enter 'quit;' to abort the coset enumeration,\n", + "you can enter 'maxlimit := 0; return;' in order to continue without a ", "limit\n" ); OnBreakMessage := SavedOnBreakMessage; end; @@ -2031,11 +2031,11 @@ local d,A,B,e1,e2,Ag,Bg,s,sg,u,v,map,sz; # instead of intersecting both preimages with s we only intersect the # intersection - u:=PreImagesSet(Projection(d,1),G!.sub); + u:=PreImagesSetNC(Projection(d,1),G!.sub); if HasSize(B) then SetSize(u,Size(G!.sub)*Size(B)); fi; - v:=PreImagesSet(Projection(d,2),H!.sub); + v:=PreImagesSetNC(Projection(d,2),H!.sub); if HasSize(A) then SetSize(v,Size(H!.sub)*Size(A)); fi; @@ -3167,7 +3167,7 @@ InstallMethod( LowIndexSubgroupsFpGroupIterator, local u, v; u:= NextIterator( iter!.fullIterator ); - v:= PreImagesSet( fpi, u ); + v:= PreImagesSetNC( fpi, u ); SetIndexInWholeGroup( v, IndexInWholeGroup( G ) * IndexInWholeGroup( u ) ); return v; @@ -3236,7 +3236,7 @@ local fpi,u,l,i,a; l:=[]; for i in u do - a:=PreImagesSet(fpi,i); + a:=PreImagesSetNC(fpi,i); SetIndexInWholeGroup(a,IndexInWholeGroup(G)*IndexInWholeGroup(i)); Add(l,a); od; @@ -3379,8 +3379,8 @@ local d,A,B,e1,e2,Ag,Bg,s,sg,u,v; # get both subgroups in the direct product via the projections # instead of intersecting both preimages with s we only intersect the # intersection - u:=PreImagesSet(Projection(d,1),G!.sub); - v:=PreImagesSet(Projection(d,2),H!.sub); + u:=PreImagesSetNC(Projection(d,1),G!.sub); + v:=PreImagesSetNC(Projection(d,2),H!.sub); u:=Intersection(u,s); v:=Intersection(v,s); @@ -4332,7 +4332,7 @@ local s, a, hom; fi; hom:=EpimorphismSolvableQuotient(G,s); if Size(Image(hom))<>s then - Error("group is not solvable"); + return fail; else SetIsInjective(hom, true); fi; @@ -5497,7 +5497,7 @@ local G,T,gens,g,reps,ng,index,i,j,ndef,n,iso; subgroup := U, iso:=iso, table:=T, - reps:=List(reps,i->PreImagesRepresentative(iso,i)))); + reps:=List(reps,i->PreImagesRepresentativeNC(iso,i)))); fi; ndef := 1; @@ -5517,7 +5517,7 @@ local G,T,gens,g,reps,ng,index,i,j,ndef,n,iso; subgroup := U, iso:=iso, table:=T, - reps:=List(reps,i->PreImagesRepresentative(iso,i)))); + reps:=List(reps,i->PreImagesRepresentativeNC(iso,i)))); fi; fi; od; diff --git a/lib/grplatt.gi b/lib/grplatt.gi index 5563219bf7..7419486e85 100644 --- a/lib/grplatt.gi +++ b/lib/grplatt.gi @@ -955,7 +955,7 @@ InstallGlobalFunction(LatticeViaRadical,function(arg) #k:=PreImage(hom,a); # make generators of homomorphism fit nicely to presentation gf:=IsomorphismFpGroup(a); - e:=List(MappingGeneratorsImages(gf)[1],x->PreImagesRepresentative(hom,x)); + e:=List(MappingGeneratorsImages(gf)[1],x->PreImagesRepresentativeNC(hom,x)); # we cannot guarantee that the parent contains e, so no # ClosureSubgroup. k:=ClosureGroup(KernelOfMultiplicativeGeneralMapping(hom),e); @@ -2779,7 +2779,7 @@ local fgi,inducedfactorautos,projs,psubs,info,n,l,nl,emb,u,pos, auts:=[]; for i in GeneratorsOfGroup(n) do aut:=GroupHomomorphismByImages(f,f,gens,List(gens,x-> - Image(hom,PreImagesRepresentative(hom,x)^i))); + Image(hom,PreImagesRepresentativeNC(hom,x)^i))); SetIsBijective(aut,true); Add(auts,aut); od; @@ -2856,7 +2856,7 @@ local fgi,inducedfactorautos,projs,psubs,info,n,l,nl,emb,u,pos, for dc in DoubleCosetRepsAndSizes(t[7],ind,t[8]) do # form the subdirect product g:=List(GeneratorsOfGroup(j[1]), - x->x*Image(emb,PreImagesRepresentative(t[5], + x->x*Image(emb,PreImagesRepresentativeNC(t[5], Image(dc[1],Image(iso,x))) )); Append(g,List(GeneratorsOfGroup(t[1]),x->Image(emb,x))); g:=Subgroup(D,g); diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 5766951a76..25d07eab9b 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -424,13 +424,11 @@ local field, dict, acts, start, j, zerov, zero, dim, base, partbas, heads, SetRange(hom,R); SetImagesSource(hom,R); SetMappingGeneratorsImages(hom,[acts,permimg]); -# p:=RUN_IN_GGMBI; # no niceomorphism translation here -# RUN_IN_GGMBI:=true; +# # no niceomorphism translation here # SetAsGroupGeneralMappingByImages ( hom, GroupHomomorphismByImagesNC -# ( G, R, acts, permimg ) ); +# ( G, R, acts, permimg : Run_In_GGMBI:= true ) ); # # SetFilterObj( hom, IsActionHomomorphismByBase ); -# RUN_IN_GGMBI:=p; if act=OnRight or act=OnPoints then # only store for action on right. projective action needs is own call to # `LinearActionBase' as this will set other needed parameters. @@ -623,7 +621,7 @@ local gens,s,dom,mon,no; # call the recursive function to do the work gens:= SCMinSmaGens( no, s, [], One( no ), true ).gens; SetMinimalStabChain(G,s); - return List(gens,i->PreImagesRepresentative(mon,i)); + return List(gens,i->PreImagesRepresentativeNC(mon,i)); end); ############################################################################# @@ -660,7 +658,7 @@ local s,dom,mon, img; i->Position(HomeEnumerator(dom),i)))); # call the recursive function to do the work s:= LargestElementStabChain( s, One( img ) ); - return PreImagesRepresentative(mon,s); + return PreImagesRepresentativeNC(mon,s); end); ############################################################################# @@ -699,7 +697,7 @@ local mon,dom,S,o,oimgs,p,i,g; od; # change by corresponding matrix element - e:=PreImagesRepresentative(mon,g)*e; + e:=PreImagesRepresentativeNC(mon,g)*e; S:=S.stabilizer; od; @@ -1202,9 +1200,10 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . for a blow up isomorphism +#M PreImagesRepresentativeNC( , ) . . . for a blow up isomorphism +#M PreImagesRepresentative( , ) . . . . for a blow up isomorphism ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for a blow up isomorphism, and a matrix in the range", FamRangeEqFamElm, [ IsBlowUpIsomorphism, IsMatrix ], @@ -1257,6 +1256,17 @@ InstallMethod( PreImagesRepresentative, return preim; end ); +InstallMethod( PreImagesRepresentative, + "for a blow up isomorphism, and a matrix in the range", + FamRangeEqFamElm, + [ IsBlowUpIsomorphism, IsMatrix ], + function( iso, mat ) + if not ( mat in Range(iso) ) then + return fail; + fi; + return PreImagesRepresentativeNC( iso, mat ); + end ); + ############################################################################# ## @@ -1341,7 +1351,12 @@ InstallMethod( ConjugateGroup, ", ", IsCollsElms, if HasIsSubgroupSL( G ) then SetIsSubgroupSL( H, IsSubgroupSL( G ) ); fi; - F:= FieldOfMatrixList( [ g ] ); + + F:= DefaultScalarDomainOfMatrixList( [ g ] ); + if not IsField( F ) then + return H; + fi; + if HasInvariantBilinearForm( G ) then if not IsBound( ginv ) then ginv := g^-1; diff --git a/lib/grpnames.gi b/lib/grpnames.gi index 8220d79e88..695923570d 100644 --- a/lib/grpnames.gi +++ b/lib/grpnames.gi @@ -173,7 +173,7 @@ InstallMethod( NormalComplementNC, i:=0; for gF in IndependentGeneratorsOfAbelianGroup(F) do i := i+1; - g := PreImagesRepresentative(nat, gF); + g := PreImagesRepresentativeNC(nat, gF); R := RightCoset(N, g); # DirectFactorsOfGroup already computed Center and RationalClasses # when calling NormalComplement @@ -893,9 +893,11 @@ InstallMethod( DecompositionTypesOfGroup, # abelian special case if IsAbelian(G) then AG := AbelianInvariants(G); - if Length(AG) = 1 then DTypes := Set([AG[1]]); else + if Length(AG) = 1 then + DTypes := Set([AG[1]]); + else T := ["x"]; - for a in AG do Add(T,a); od; + Append(T, AG); DTypes := Set([T]); fi; return DTypes; @@ -942,7 +944,9 @@ InstallMethod( DecompositionTypesOfGroup, od; # default: a non-split extension - if Length(DTypes) = 0 then DTypes := Set([["non-split",Size(G)]]); fi; + if Length(DTypes) = 0 then + DTypes := Set([["non-split",Size(G)]]); + fi; return DTypes; end ); @@ -999,9 +1003,8 @@ function(G) gens := DoComputeDihedralGenerators(G); if gens = fail then return false; - else - SetDihedralGenerators(G, gens); fi; + SetDihedralGenerators(G, gens); return true; end); @@ -1198,27 +1201,31 @@ InstallMethod( IsAlternatingGroup, function ( G ) - local n, ids, info; + local info; if not IsFinite(G) then TryNextMethod(); fi; - if IsNaturalAlternatingGroup(G) then return true;fi; - if Size(G) < 60 then + if IsNaturalAlternatingGroup(G) then + return true; + elif Size(G) < 60 then if Size(G) = 1 then - SetAlternatingDegree(G,0); return true; + SetAlternatingDegree(G,0); + return true; elif Size(G) = 3 then - SetAlternatingDegree(G,3); return true; + SetAlternatingDegree(G,3); + return true; elif Size(G) = 12 and Size(DerivedSubgroup(G)) = 4 then - SetAlternatingDegree(G,4); return true; - else return false; fi; + SetAlternatingDegree(G,4); + return true; + fi; + elif IsSimpleGroup(G) then + info := IsomorphismTypeInfoFiniteSimpleGroup(G); + if info.series = "A" then + SetAlternatingDegree(G,info.parameter); + return true; + fi; fi; - - if not IsSimpleGroup(G) then return false; fi; - - info := IsomorphismTypeInfoFiniteSimpleGroup(G); - if info.series = "A" - then SetAlternatingDegree(G,info.parameter); return true; - else return false; fi; + return false; end ); ############################################################################# @@ -1272,7 +1279,9 @@ InstallMethod( IsSymmetricGroup, if not IsFinite(G) then TryNextMethod(); fi; # special treatment of small cases - if Size(G)<=2 then SetSymmetricDegree(G,Size(G)); return true; + if Size(G)<=2 then + SetSymmetricDegree(G,Size(G)); + return true; elif Size(G)=6 and not IsAbelian(G) then SetSymmetricDegree(G,3); return true; @@ -1407,15 +1416,15 @@ InstallGlobalFunction( LinearGroupParameters, if not IsPosInt(N) then Error(" must be positive integer"); fi; - # Formeln: + # Formulas: # |GL(n, q)| = Product(q^n - q^k : k in [0..n-1]) # |SL(n, q)| = |GL(n, q)| / (q - 1) # |PSL(n, q)| = |SL(n, q)| / gcd(n, q - 1) - # mit q = p^e f"ur p prim, e >= 1, n >= 1. + # where q = p^e for p prime, e >= 1, n >= 1. - # Betrachte N = |GL(n,q)|. Dann gilt f"ur n >= 2 - # (1) nu_p(N) = e * Binomial(n,2) und - # (2) (q - 1)^n teilt N. + # Consider N = |GL(n,q)|. Then we have for n >= 2 + # (1) nu_p(N) = e * Binomial(n,2) and + # (2) (q - 1)^n divides N. npeGL := [ ]; npeSL := [ ]; npePSL := [ ]; if N = 1 then return rec( npeGL := npeGL, npeSL := npeSL, npePSL := npePSL ); @@ -1470,8 +1479,9 @@ InstallMethod( IsPSL, # more than one npe-triple should only # occur in the cases |G| in [60, 168, 20160] - if Length(npes) > 1 and not( Size(G) in [60, 168, 20160] ) - then Error("algebraic panic! probably npe does not work"); fi; + if Length(npes) > 1 and not( Size(G) in [60, 168, 20160] ) then + Error("algebraic panic! probably npe does not work"); + fi; # set the parameters npe := npes[1]; @@ -1483,12 +1493,10 @@ InstallMethod( IsPSL, # PSL(2, 2) if npes[1] = [2, 2, 1] then if IsAbelian(G) then return false; fi; - SetParametersOfGroupViewedAsPSL(G,npe); return true; # PSL(2, 3) elif npes[1] = [2, 3, 1] then if Size(DerivedSubgroup(G)) <> 4 then return false; fi; - SetParametersOfGroupViewedAsPSL(G,npe); return true; # PSL(3, 4) / PSL(4, 2) \cong A_8 elif npes = [ [ 4, 2, 1 ], [ 3, 2, 2 ] ] then @@ -1497,13 +1505,13 @@ InstallMethod( IsPSL, else npe := npes[2]; fi; - SetParametersOfGroupViewedAsPSL(G,npe); return true; # other cases - else - if not IsSimpleGroup(G) then return false; fi; - SetParametersOfGroupViewedAsPSL(G,npe); return true; + elif not IsSimpleGroup(G) then + return false; fi; + SetParametersOfGroupViewedAsPSL(G,npe); + return true; end ); ############################################################################# @@ -1563,12 +1571,10 @@ InstallMethod( IsSL, # SL(2, 2) if npes = [2, 2, 1] then if IsAbelian(G) then return false; fi; - SetParametersOfGroupViewedAsSL(G,npes); return true; # SL(2, 3) elif npes = [2, 3, 1] then if Size(DerivedSubgroup(G)) <> 8 then return false; fi; - SetParametersOfGroupViewedAsSL(G,npes); return true; # other cases, in which the contained PSL is simple else @@ -1583,8 +1589,9 @@ InstallMethod( IsSL, then return false; fi; if IsomorphismGroups(G,SL(npes[1],npes[2]^npes[3])) = fail then return false; fi; - SetParametersOfGroupViewedAsSL(G,npes); return true; fi; + SetParametersOfGroupViewedAsSL(G,npes); + return true; end ); ############################################################################# @@ -1649,7 +1656,6 @@ InstallMethod( IsGL, # GL(2, 2) if npes = [2, 2, 1] then if IsAbelian(G) then return false; fi; - SetParametersOfGroupViewedAsGL(G,npes); return true; # GL(2, 3) elif npes = [2, 3, 1] then @@ -1668,7 +1674,6 @@ InstallMethod( IsGL, # elements of order 4 in one case, and 2 in the other; this is also # how e.g. IdGroup distinguishes them if Number(G, g -> Order(g) = 2) < 13 then return false; fi; - SetParametersOfGroupViewedAsGL(G,npes); return true; # other cases, in which contained PSL is simple else @@ -1687,8 +1692,9 @@ InstallMethod( IsGL, then return false; fi; if IsomorphismGroups(G,GL(npes[1],npes[2]^npes[3])) = fail then return false; fi; - SetParametersOfGroupViewedAsGL(G,npes); return true; fi; + SetParametersOfGroupViewedAsGL(G,npes); + return true; end ); ############################################################################# @@ -1728,23 +1734,21 @@ InstallMethod( GLUnderlyingField, BindGlobal( "SD_insertsep", # function to join parts of name function ( strs, sep, brack ) - local short, s, i; - - short := ValueOption("short") = true; + local s, i; if strs = [] then return ""; fi; strs := Filtered(strs,str->str<>""); if Length(strs) > 1 then for i in [1..Length(strs)] do - if Intersection(strs[i],brack) <> "" - then strs[i] := Concatenation("(",strs[i],")"); fi; + if Intersection(strs[i],brack) <> "" then + strs[i] := Concatenation("(",strs[i],")"); + fi; od; fi; - s := strs[1]; - for i in [2..Length(strs)] do - s := Concatenation(s,sep,strs[i]); - od; - if short then RemoveCharacters(s," "); fi; + s := JoinStringsWithSeparator(strs,sep); + if ValueOption("short") = true then + RemoveCharacters(s," "); + fi; return s; end); @@ -1759,27 +1763,29 @@ BindGlobal( "SD_cyclic", BindGlobal( "SD_cycsaspowers", # function to write C2 x C2 x C2 as 2^3, etc. function ( name, cycsizes ) - local short, g, d, k, j, n; + local g, d, k, j, n; - short := ValueOption("short") = true; - if not short then return name; fi; + if ValueOption("short") <> true then + return name; + fi; RemoveCharacters(name," "); - cycsizes := Collected(cycsizes); - for n in cycsizes do - d := n[1]; k := n[2]; - g := SD_cyclic(d); - if d = 0 then - d := "Z"; - else - d := String(d); - fi; - if k > 1 then - for j in Reversed([2..k]) do - name := ReplacedString(name,SD_insertsep(List([1..j],i->g),"x",""), - Concatenation(d,"^",String(j))); - od; - fi; - od; + cycsizes := Collected(cycsizes); + for n in cycsizes do + d := n[1]; + k := n[2]; + g := SD_cyclic(d); + if d = 0 then + d := "Z"; + else + d := String(d); + fi; + if k > 1 then + for j in Reversed([2..k]) do + name := ReplacedString(name,SD_insertsep(List([1..j],i->g),"x",""), + Concatenation(d,"^",String(j))); + od; + fi; + od; RemoveCharacters(name,"C"); return name; end); @@ -1810,11 +1816,14 @@ BindGlobal( "StructureDescriptionForFiniteSimpleGroups", # for simple groups parameter; # parameters of G in series # special case abelian group - if IsAbelian(G) then return StructureDescriptionForAbelianGroups(G); fi; + if IsAbelian(G) then + return StructureDescriptionForAbelianGroups(G); + fi; # special case alternating group - if IsAlternatingGroup(G) - then return Concatenation("A",String(AlternatingDegree(G))); fi; + if IsAlternatingGroup(G) then + return Concatenation("A",String(AlternatingDegree(G))); + fi; # special case PSL if IsPSL(G) then @@ -1913,30 +1922,39 @@ BindGlobal( "StructureDescriptionForFiniteGroups", # for finite groups fi; # special case trivial group - if IsTrivial(G) then return "1"; fi; + if IsTrivial(G) then + return "1"; + fi; # special case abelian group - if IsAbelian(G) then return StructureDescriptionForAbelianGroups(G); fi; + if IsAbelian(G) then + return StructureDescriptionForAbelianGroups(G); + fi; # special case alternating group - if IsAlternatingGroup(G) - then return Concatenation("A",String(AlternatingDegree(G))); fi; + if IsAlternatingGroup(G) then + return Concatenation("A",String(AlternatingDegree(G))); + fi; # special case symmetric group - if IsSymmetricGroup(G) - then return Concatenation("S",String(SymmetricDegree(G))); fi; + if IsSymmetricGroup(G) then + return Concatenation("S",String(SymmetricDegree(G))); + fi; # special case dihedral group - if IsDihedralGroup(G) and Size(G) > 6 - then return Concatenation("D",String(Size(G))); fi; + if IsDihedralGroup(G) and Size(G) > 6 then + return Concatenation("D",String(Size(G))); + fi; # special case quaternion group - if IsQuaternionGroup(G) - then return Concatenation("Q",String(Size(G))); fi; + if IsQuaternionGroup(G) then + return Concatenation("Q",String(Size(G))); + fi; # special case quasidihedral group - if IsQuasiDihedralGroup(G) - then return Concatenation("QD",String(Size(G))); fi; + if IsQuasiDihedralGroup(G) then + return Concatenation("QD",String(Size(G))); + fi; # special case PSL if IsPSL(G) then @@ -1975,7 +1993,9 @@ BindGlobal( "StructureDescriptionForFiniteGroups", # for finite groups cycsizes := Filtered(cycsizes,n->n<>1); cycname := SD_cycsaspowers(SD_insertsep(List(cycsizes, SD_cyclic), " x ",":."), cycsizes); - else cycname := ""; fi; + else + cycname := ""; + fi; noncyclics := Difference(Gs,cyclics); noncycname := SD_insertsep(List(noncyclics,StructureDescription), " x ",":."); @@ -2049,32 +2069,33 @@ BindGlobal( "StructureDescriptionForFiniteGroups", # for finite groups # non-splitting, non-simple group if not IsTrivial(Centre(G)) then cname := SD_insertsep([StructureDescription(Centre(G)), - StructureDescription(G/Centre(G))]," . ","x:."); + StructureDescription(G/Centre(G))], + " . ","x:."); fi; if not IsPerfectGroup(G) then dname := SD_insertsep([StructureDescription(DerivedSubgroup(G)), StructureDescription(G/DerivedSubgroup(G))], " . ","x:."); fi; - if IsBound(cname) and IsBound(dname) and cname <> dname - then return Concatenation(cname," = ",dname); - elif IsBound(cname) then return cname; - elif IsBound(dname) then return dname; - elif not IsTrivial(FrattiniSubgroup(G)) - then return SD_insertsep([StructureDescription(FrattiniSubgroup(G)), - StructureDescription(G/FrattiniSubgroup(G))], - " . ","x:."); - elif IsPosInt(NrPerfectGroups(Size(G))) - and not Size(G) in [ 86016, 368640, 737280 ] - # this does not happen for Size(G)<10^6 - then - id := PerfectIdentification(G); - return Concatenation("PerfectGroup(",String(id[1]),",", - String(id[2]),")"); - else return Concatenation(""); + if IsBound(cname) and IsBound(dname) and cname <> dname then + return Concatenation(cname," = ",dname); + elif IsBound(cname) then + return cname; + elif IsBound(dname) then + return dname; + elif not IsTrivial(FrattiniSubgroup(G)) then + return SD_insertsep([StructureDescription(FrattiniSubgroup(G)), + StructureDescription(G/FrattiniSubgroup(G))], + " . ","x:."); + elif IsPosInt(NrPerfectGroups(Size(G))) then + id := PerfectIdentification(G); + return Concatenation("PerfectGroup(",String(id[1]),",", + String(id[2]),")"); + else + return Concatenation(""); fi; end ); diff --git a/lib/grpnice.gd b/lib/grpnice.gd index 5a9480fd86..8d7dee5536 100644 --- a/lib/grpnice.gd +++ b/lib/grpnice.gd @@ -189,6 +189,9 @@ InstallSubsetMaintenance( IsHandledByNiceMonomorphism, IsHandledByNiceMonomorphism and IsGroup, IsGroup); +# We recommend the (documented) global option `Run_In_GGMBI` +# instead of the global variable `RUN_IN_GGMBI`, +# but `RUN_IN_GGMBI` is still supported because GAP packages might use it. RUN_IN_GGMBI:=false; # If somebody would call `GHBI' to make a # NiceMonomorphism, we would get an infinite recursion. # This flag can be set to avoid GHBIs to be translated @@ -363,7 +366,7 @@ BindGlobal( "AttributeMethodByNiceMonomorphismList", function( oper, par ) local nice; nice:= NiceMonomorphism( obj ); return List( oper( NiceObject( obj ) ), - x -> PreImagesRepresentative( nice, x ) ); + x -> PreImagesRepresentativeNC( nice, x ) ); end ); end ); @@ -398,7 +401,7 @@ BindGlobal( "AttributeMethodByNiceMonomorphismCollElm", function( oper, par ) img := ImagesRepresentative( nice, obj2 : actioncanfail:= true ); if img = fail or not ( img in ImagesSource( nice ) and - PreImagesRepresentative( nice, img ) = obj2 ) then + PreImagesRepresentativeNC( nice, img ) = obj2 ) then TryNextMethod(); fi; return oper( NiceObject( obj1 ), img ); @@ -441,7 +444,7 @@ BindGlobal( "AttributeMethodByNiceMonomorphismElmColl", img := ImagesRepresentative( nice, obj1 : actioncanfail:= true ); if img = fail or not (img in ImagesSource( nice ) and - PreImagesRepresentative( nice, img ) = obj1) then + PreImagesRepresentativeNC( nice, img ) = obj1) then TryNextMethod(); fi; return oper( img, NiceObject( obj2 ) ); @@ -525,7 +528,7 @@ BindGlobal( "GroupMethodByNiceMonomorphismCollElm", img := ImagesRepresentative( nice, obj2 : actioncanfail:= true ); if img = fail or not (img in ImagesSource( nice ) and - PreImagesRepresentative( nice, img ) = obj2) then + PreImagesRepresentativeNC( nice, img ) = obj2) then TryNextMethod(); fi; img1 := oper( NiceObject( obj1 ), img ); @@ -613,7 +616,7 @@ BindGlobal( "SubgroupMethodByNiceMonomorphismCollColl", function( oper, par ) img:=ImagesSet( nice, obj2 ); if img = fail or not ( IsSubset( ImagesSource( nice ), img ) and - PreImagesSet( nice, img ) = obj2 ) then + PreImagesSetNC( nice, img ) = obj2 ) then TryNextMethod(); fi; img := oper( NiceObject( obj1 ), img ); @@ -637,7 +640,7 @@ BindGlobal( "SubgroupMethodByNiceMonomorphismCollElm", function( oper, par ) img := ImagesRepresentative( nice, obj2 : actioncanfail:= true ); if img = fail or not ( img in ImagesSource( nice ) and - PreImagesRepresentative (nice , img ) = obj2 ) then + PreImagesRepresentativeNC( nice, img ) = obj2 ) then TryNextMethod(); fi; img1 := oper( NiceObject( obj1 ), img ); @@ -764,7 +767,7 @@ BindGlobal( "GroupSeriesMethodByNiceMonomorphismCollElm", img := ImagesRepresentative( nice, obj2 : actioncanfail:= true ); if img = fail or not ( img in ImagesSource( nice ) and - PreImagesRepresentative( nice, img ) = obj2 ) then + PreImagesRepresentativeNC( nice, img ) = obj2 ) then TryNextMethod(); fi; list := ShallowCopy( oper( NiceObject( obj1 ), img ) ); diff --git a/lib/grpnice.gi b/lib/grpnice.gi index f72d348e81..faf214a1f3 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -212,7 +212,7 @@ function( elm, G ) nice := NiceMonomorphism( G ); img := ImagesRepresentative( nice, elm:actioncanfail:=true ); return img<>fail and img in NiceObject( G ) - and PreImagesRepresentative( nice, img ) = elm; + and PreImagesRepresentativeNC( nice, img ) = elm; end ); @@ -284,7 +284,7 @@ function( obj1, obj2 ) img := ImagesRepresentative( nice, obj2:actioncanfail:=true ); if img = fail or not (img in ImagesSource(nice) and - PreImagesRepresentative(nice,img)=obj2) then + PreImagesRepresentativeNC(nice,img)=obj2) then TryNextMethod(); fi; no:=NiceObject(obj1); @@ -344,10 +344,10 @@ local mon,cl,clg,c,i; cl:=ConjugacyClasses(NiceObject(g)); clg:=[]; for i in cl do - c:=ConjugacyClass(g,PreImagesRepresentative(mon,Representative(i))); + c:=ConjugacyClass(g,PreImagesRepresentativeNC(mon,Representative(i))); c!.niceClass:=i; if HasStabilizerOfExternalSet(i) then - SetStabilizerOfExternalSet(c,PreImages(mon,StabilizerOfExternalSet(i))); + SetStabilizerOfExternalSet(c,PreImagesNC(mon,StabilizerOfExternalSet(i))); fi; Add(clg,c); od; @@ -767,7 +767,7 @@ SubgroupMethodByNiceMonomorphism( SolvableRadical, InstallMethodWithRandomSource( Random, "for a random source and a group handled by nice monomorphism", [ IsRandomSource, IsGroup and IsHandledByNiceMonomorphism ], 0, - {rs, G} -> PreImagesRepresentative( NiceMonomorphism( G ), + {rs, G} -> PreImagesRepresentativeNC( NiceMonomorphism( G ), Random( rs, NiceObject( G ) ) ) ); @@ -783,9 +783,9 @@ local mon,cl,clg,c,i; cl:=RationalClasses(NiceObject(g)); clg:=[]; for i in cl do - c:=RationalClass(g,PreImagesRepresentative(mon,Representative(i))); + c:=RationalClass(g,PreImagesRepresentativeNC(mon,Representative(i))); if HasStabilizerOfExternalSet(i) then - SetStabilizerOfExternalSet(c,PreImages(mon,StabilizerOfExternalSet(i))); + SetStabilizerOfExternalSet(c,PreImagesNC(mon,StabilizerOfExternalSet(i))); fi; if HasGaloisGroup(i) then SetGaloisGroup(c,GaloisGroup(i)); @@ -806,7 +806,7 @@ function(g,u) local mon,rt; mon:=NiceMonomorphism(g); rt:=RightTransversal(ImagesSet(mon,g),ImagesSet(mon,u)); - rt:=List(rt,i->RightCoset(u,PreImagesRepresentative(mon,i))); + rt:=List(rt,i->RightCoset(u,PreImagesRepresentativeNC(mon,i))); return rt; end); @@ -878,7 +878,7 @@ local hom,rep; rep:= RepresentativeAction( NiceObject( G ), ImageElm( hom, a ), ImageElm( hom, b ), OnPoints ); if rep<>fail then - rep:=PreImagesRepresentative(hom,rep); + rep:=PreImagesRepresentativeNC(hom,rep); fi; return rep; end); @@ -927,16 +927,22 @@ InstallMethod( GroupGeneralMappingByImagesNC, "from a group handled by a niceomorphism",true, [ IsGroup and IsHandledByNiceMonomorphism, IsGroup, IsList, IsList ], 0, function( G, H, gens, imgs ) -local nice,geni,map2,tmp; - if RUN_IN_GGMBI=true then +local nice,geni,map2; + if ValueOption( "Run_In_GGMBI" ) = true then + TryNextMethod(); + elif RUN_IN_GGMBI = true then + # Code was called that does not know about the global option. + # Make it work but print a warning. + Info( InfoWarning, 1, + "use the global option 'Run_In_GGMBI' not the global variable ", + "'RUN_IN_GGMBI', see '?Run_In_GGMBI'" ); TryNextMethod(); fi; - tmp := RUN_IN_GGMBI; - RUN_IN_GGMBI:=true; + PushOptions( rec( Run_In_GGMBI:= true ) ); nice:=RestrictedNiceMonomorphism(G); geni:=List(gens,i->ImageElm(nice,i)); map2:=GroupGeneralMappingByImagesNC(NiceObject(G),H,geni,imgs); - RUN_IN_GGMBI:=tmp; + PopOptions(); return CompositionMapping(map2,nice); end ); @@ -956,38 +962,52 @@ InstallMethod( AsGroupGeneralMappingByImages, [IsGroupGeneralMapping and IsNiceMonomorphism], {} -> RankFilter( IsHandledByNiceMonomorphism ), function(hom) -local h, tmp; - # we actually want to use the next method with `RUN_IN_GGMBI' set to + # we actually want to use the next method with `Run_In_GGMBI' set to # `true'. Therefore we redispatch, but will skip this method the second # time. - if RUN_IN_GGMBI=true then + if ValueOption( "Run_In_GGMBI" ) = true then + TryNextMethod(); + elif RUN_IN_GGMBI = true then + # Code was called that does not know about the global option. + # Make it work but print a warning. + Info( InfoWarning, 1, + "use the global option 'Run_In_GGMBI' not the global variable ", + "'RUN_IN_GGMBI', see '?Run_In_GGMBI'" ); TryNextMethod(); fi; - tmp := RUN_IN_GGMBI; - RUN_IN_GGMBI:=true; - h:=AsGroupGeneralMappingByImages(hom); - RUN_IN_GGMBI:=tmp; - return h; + return AsGroupGeneralMappingByImages( hom : Run_In_GGMBI:= true ); end); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . . . . . . via images #M PreImagesRepresentative( , ) . . . . . . . . . . . via images ## -InstallMethod( PreImagesRepresentative, "for PBG-Niceo", +InstallMethod( PreImagesRepresentativeNC, "for PBG-Niceo", FamRangeEqFamElm, [ IsPreimagesByAsGroupGeneralMappingByImages and IsNiceMonomorphism, IsMultiplicativeElementWithInverse ], 0, function( hom, elm ) -local p, tmp; +local p; # avoid the double dispatch for `AsGroupGeneralMappingByImages' tmp := RUN_IN_GGMBI; RUN_IN_GGMBI:=true; - p:=PreImagesRepresentative( AsGroupGeneralMappingByImages( hom ), elm ); + p:=PreImagesRepresentativeNC( AsGroupGeneralMappingByImages( hom ), elm ); RUN_IN_GGMBI:=tmp; return p; end ); +InstallMethod( PreImagesRepresentative, "for PBG-Niceo", + FamRangeEqFamElm, + [ IsPreimagesByAsGroupGeneralMappingByImages and IsNiceMonomorphism, + IsMultiplicativeElementWithInverse ], 0, +function( hom, elm ) + if not ( elm in Range(hom) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## #M NiceMonomorphism( ) . . @@ -1078,7 +1098,7 @@ InstallMethod( \[\],"enum-by-niceo", true, function( enum, pos ) local img; img:=enum!.niceEnumerator[pos]; - return PreImagesRepresentative(enum!.morphism,img); + return PreImagesRepresentativeNC(enum!.morphism,img); end); diff --git a/lib/grppc.gi b/lib/grppc.gi index f01a7af92d..9233d045e2 100644 --- a/lib/grppc.gi +++ b/lib/grppc.gi @@ -2147,7 +2147,7 @@ local e, # EAS if iso<>false then V:=PreImage(iso,V); no:=PreImage(iso,no); - ce:=PreImagesRepresentative(iso,ce); + ce:=PreImagesRepresentativeNC(iso,ce); fi; return [V,no,ce]; end ); @@ -2568,7 +2568,7 @@ local q, pcgs, sub, hom, f, ex, C; ex:=ExponentOfPGroupAndElm(f,q); while ex[1]>q do # take the element of highest order in f and take power of its preimage - ex:=PreImagesRepresentative(hom,ex[2]^q); + ex:=PreImagesRepresentativeNC(hom,ex[2]^q); sub:=NormalClosure(G,ClosureSubgroupNC(sub,ex)); hom:=NaturalHomomorphismByNormalSubgroup(G,sub); f:=Range(hom); @@ -2646,7 +2646,7 @@ function(G,p,e) local f; f:=MaximalAbelianQuotient(G); IsAbelian(Image(f)); - return SubgroupByPcgs(G,Pcgs(PreImagesSet(f,Omega(Image(f),p,e)))); + return SubgroupByPcgs(G,Pcgs(PreImagesSetNC(f,Omega(Image(f),p,e)))); end); # Efficiency notes: @@ -2679,7 +2679,7 @@ local z,f; f:=NaturalHomomorphismByNormalSubgroup(G,Subgroup(G,[z])); IsAbelian(Image(f)); # Probably is not, but quick to check - return SubgroupByPcgs(G,Pcgs(PreImagesSet(f,Omega(Image(f),p,e)))); + return SubgroupByPcgs(G,Pcgs(PreImagesSetNC(f,Omega(Image(f),p,e)))); end); # Efficiency Points: @@ -2820,7 +2820,7 @@ InstallMethod (HallSubgroupOp, "via IsomoprhismPcGroup", true, function (grp, pi) local iso; iso := IsomorphismPcGroup (grp); - return PreImagesSet (iso, HallSubgroup (ImagesSource (iso), pi)); + return PreImagesSetNC(iso, HallSubgroup (ImagesSource (iso), pi)); end); @@ -2841,7 +2841,7 @@ InstallMethod (SylowComplementOp, "via IsomoprhismPcGroup", true, function (grp, p) local iso; iso := IsomorphismPcGroup (grp); - return PreImagesSet (iso, SylowComplement (ImagesSource (iso), p)); + return PreImagesSetNC(iso, SylowComplement (ImagesSource (iso), p)); end); diff --git a/lib/grppcaut.gi b/lib/grppcaut.gi index 2840694725..eb3e7a5f51 100644 --- a/lib/grppcaut.gi +++ b/lib/grppcaut.gi @@ -437,7 +437,7 @@ local spec,s,n,M, if d = 1 then hom := IsomorphismPermGroup( B ); pcgs := Pcgs( Image( hom ) ); - pcs := List( pcgs, x -> PreImagesRepresentative( hom, x ) ); + pcs := List( pcgs, x -> PreImagesRepresentativeNC( hom, x ) ); TransferPcgsInfo( B, pcs, RelativeOrders( pcgs ) ); return B; fi; @@ -509,12 +509,12 @@ local spec,s,n,M, Info( InfoOverGr, 1, "computed normalizer of size ", Size(L)); # go back to mat group - B := List( GeneratorsOfGroup(L), x -> PreImagesRepresentative(hom,x) ); + B := List( GeneratorsOfGroup(L), x -> PreImagesRepresentativeNC(hom,x) ); w := PrimitiveRoot(field)* Immutable( IdentityMat( d, field ) ); B := SubgroupNC( S, Concatenation( B, [w] ) ); if IsSolvableGroup( L ) then - pcgs := List( Pcgs(L), x -> PreImagesRepresentative( hom, x ) ); + pcgs := List( Pcgs(L), x -> PreImagesRepresentativeNC( hom, x ) ); Add( pcgs, w ); rels := ShallowCopy( RelativeOrders( Pcgs(L) ) ); Add( rels, p-1 ); @@ -536,7 +536,7 @@ BindGlobal( "CocycleSQ", function( epi, field ) H := Source( epi ); F := Image( epi ); N := KernelOfMultiplicativeGeneralMapping( epi ); - pcsH := List( Pcgs( F ), x -> PreImagesRepresentative( epi, x ) ); + pcsH := List( Pcgs( F ), x -> PreImagesRepresentativeNC( epi, x ) ); pcsN := Pcgs( N ); pcgsH := PcgsByPcSequence( ElementsFamily( FamilyObj( H ) ), Concatenation( pcsH, pcsN ) ); @@ -646,7 +646,7 @@ BindGlobal( "LiftInduciblePair", function( epi, ind, M, weight ) pcgsF := Pcgs( F ); - pcsH := List( pcgsF, x -> PreImagesRepresentative( epi, x ) ); + pcsH := List( pcgsF, x -> PreImagesRepresentativeNC( epi, x ) ); pcsN := Pcgs( N ); pcgsH := PcgsByPcSequence( ElementsFamily( FamilyObj( H ) ), Concatenation( pcsH, pcsN ) ); @@ -656,7 +656,7 @@ BindGlobal( "LiftInduciblePair", function( epi, ind, M, weight ) # use automorphism of F imgsF := List( pcgsF, x -> Image( ind[1], x ) ); opmats := List( imgsF, x -> MappedPcElement( x, pcgsF, M.generators ) ); - imgsF := List( imgsF, x -> PreImagesRepresentative( epi, x ) ); + imgsF := List( imgsF, x -> PreImagesRepresentativeNC( epi, x ) ); # use automorphism of N imgsN := List( pcsN, x -> ExponentsOfPcElement( pcsN, x ) ); @@ -1418,11 +1418,11 @@ InstallGlobalFunction(AutomorphismGroupSolvableGroup,function( G ) hom := ActionHomomorphism( xset, "surjective"); P := Image( hom ); if IsSolvableGroup( P ) then - pcsA := List( Pcgs(P), x -> PreImagesRepresentative( hom, x )); + pcsA := List( Pcgs(P), x -> PreImagesRepresentativeNC( hom, x )); TransferPcgsInfo( A, pcsA, RelativeOrders( Pcgs(P) ) ); else imgs := SmallGeneratingSet( P ); - gens := List( imgs, x -> PreImagesRepresentative( hom, x ) ); + gens := List( imgs, x -> PreImagesRepresentativeNC( hom, x ) ); tmp := Size( A ); A := GroupByGenerators( gens, One( A ) ); SetSize( A, tmp ); @@ -1543,10 +1543,10 @@ InstallGlobalFunction(AutomorphismGroupFrattFreeGroup,function( G ) imgs := []; for i in [1..Length(gensK)] do m := gensU[i]^n; - a := PreImagesRepresentative( hom, m ); + a := PreImagesRepresentativeNC( hom, m ); Add( imgs, a ); od; - l := PreImagesRepresentative( iso, n ); + l := PreImagesRepresentativeNC( iso, n ); Append( imgs, List( gensF, x -> Image( l, x ) ) ); new := GroupHomomorphismByImagesNC( G, G, gensG, imgs ); SetIsBijective( new, true ); diff --git a/lib/grppccom.gi b/lib/grppccom.gi index 2dc5682575..bb59eef42e 100644 --- a/lib/grppccom.gi +++ b/lib/grppccom.gi @@ -19,7 +19,7 @@ local r,img,i,gens,img2; gens:=GeneratorsOfGroup(img); img2:=Image(h[i],G); r[i]:=GroupHomomorphismByImagesNC(img,img2,gens,List(gens,j-> - Image(h[i],PreImagesRepresentative(h[i+1],j)))); + Image(h[i],PreImagesRepresentativeNC(h[i+1],j)))); SetKernelOfMultiplicativeGeneralMapping(r[i], Image(h[i+1],KernelOfMultiplicativeGeneralMapping(h[i]))); img:=img2; @@ -890,7 +890,7 @@ local H, E, cor, a, i, fun2,pcgs,home; #a :=NaturalHomomorphism( G, G / N ); #cor:=PPrimeSetsOC( Image( a ) ); #cor.generators:=List( cor.generators, x -> - # PreImagesRepresentative( a, x ) ); + # PreImagesRepresentativeNC( a, x ) ); cor:=rec(home:=home,generators:=pcgs mod InducedPcgs(pcgs,N)); cor.useCentralSK:=true; fi; diff --git a/lib/grppcext.gi b/lib/grppcext.gi index 4cfb4063a1..bcc5e554a9 100644 --- a/lib/grppcext.gi +++ b/lib/grppcext.gi @@ -378,11 +378,11 @@ local ag, p1iso, agp, p2iso, DP, p1, p2, gens, genimgs, triso,s,i,u,opt, genimgs:=List(gens, i->ImagesRepresentative(Embedding(D,1), - PreImagesRepresentative(p1iso, - PreImagesRepresentative(pc1,ImagesRepresentative(p1,i)))) + PreImagesRepresentativeNC(p1iso, + PreImagesRepresentativeNC(pc1,ImagesRepresentative(p1,i)))) *ImagesRepresentative(Embedding(D,2), - PreImagesRepresentative(p2iso, - PreImagesRepresentative(pc2,ImagesRepresentative(p2,i)))) ); + PreImagesRepresentativeNC(p2iso, + PreImagesRepresentativeNC(pc2,ImagesRepresentative(p2,i)))) ); else opt:=rec(limit:=s,random:=1); @@ -426,9 +426,9 @@ local ag, p1iso, agp, p2iso, DP, p1, p2, gens, genimgs, triso,s,i,u,opt, genimgs:=List(gens, i->ImagesRepresentative(Embedding(D,1), - PreImagesRepresentative(p1iso,ImagesRepresentative(p1,i))) + PreImagesRepresentativeNC(p1iso,ImagesRepresentative(p1,i))) *ImagesRepresentative(Embedding(D,2), - PreImagesRepresentative(p2iso,ImagesRepresentative(p2,i))) ); + PreImagesRepresentativeNC(p2iso,ImagesRepresentative(p2,i))) ); fi; triso:=GroupHomomorphismByImagesNC(DP,D,gens,genimgs); @@ -528,7 +528,7 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, gens,M.generators); test:=function(perm) local aut,imgs,mat; - aut:=PreImagesRepresentative(triso,perm); + aut:=PreImagesRepresentativeNC(triso,perm); imgs:=List(gens,x->ImagesRepresentative(aut,x)); imgs:=List(imgs,x->ImagesRepresentative(modulehom,x)); mat:=MTX.IsomorphismModules(M,GModuleByMats(imgs,M.field)); @@ -696,9 +696,9 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, basicact:=function( tup, elm ) local gens; - #gens := List( tup[1], x -> PreImagesRepresentative( elm[1], x ) ); + #gens := List( tup[1], x -> PreImagesRepresentativeNC( elm[1], x ) ); #gens := List( gens, x -> MappedPcElement( x, tup[1], tup[2] ) ); - gens := List( Ggens, x -> PreImagesRepresentative( elm[1], x ) ); + gens := List( Ggens, x -> PreImagesRepresentativeNC( elm[1], x ) ); gens := List( gens, x -> MappedPcElement( x, Ggens, tup ) ); gens := List( gens, x -> x ^ elm[2] ); return gens; @@ -711,10 +711,10 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, Assert(1,MappingGeneratorsImages(epi)[2]=Ggens); f:=function( tup, elm ) local gens; - #gens := List( tup[1], x -> PreImagesRepresentative( elm[1], x ) ); + #gens := List( tup[1], x -> PreImagesRepresentativeNC( elm[1], x ) ); #gens := List( gens, x -> MappedPcElement( x, tup[1], tup[2] ) ); - gens := List( Ggens, x -> PreImagesRepresentative( elm[1], x ) ); - gens := List( gens, x -> MappedWord( PreImagesRepresentative(epi,x), + gens := List( Ggens, x -> PreImagesRepresentativeNC( elm[1], x ) ); + gens := List( gens, x -> MappedWord( PreImagesRepresentativeNC(epi,x), GeneratorsOfGroup(Source(epi)), tup ) ); gens := List( gens, x -> x ^ elm[2] ); return gens; @@ -730,13 +730,13 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, elmlist:=[]; tmp:=List(genimgs,x->x[1]); - preimlist:=List(tmp,x->[x,List(Ggens,y->PreImagesRepresentative(x,y))]); + preimlist:=List(tmp,x->[x,List(Ggens,y->PreImagesRepresentativeNC(x,y))]); f:=function( tup, elm ) local gens,p; p:=PositionProperty(preimlist,x->IsIdenticalObj(x[1],elm[1])); if p=fail then - gens := List( Ggens, x -> PreImagesRepresentative( elm[1], x ) ); + gens := List( Ggens, x -> PreImagesRepresentativeNC( elm[1], x ) ); else gens:=preimlist[p][2]; fi; @@ -781,7 +781,7 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, if elmlist<>fail then tmp:=List(genimgs,x->x[1]); - preimlist:=List(tmp,x->[x,List(Ggens,y->PreImagesRepresentative(x,y))]); + preimlist:=List(tmp,x->[x,List(Ggens,y->PreImagesRepresentativeNC(x,y))]); # ensure we also account for action u:=Group(tup); @@ -911,7 +911,7 @@ BindGlobal( "MatrixOperationOfCPGroup", function( cc, gens ) mats := List( gens, x -> [] ); base := Basis( Image( cc.cohom ) ); - prei := List( base, x -> PreImagesRepresentative( cc.cohom, x ) ); + prei := List( base, x -> PreImagesRepresentativeNC( cc.cohom, x ) ); pcgs := Pcgs( cc.group ); ords := RelativeOrders( pcgs ); @@ -1008,7 +1008,7 @@ function( G, M, C ) return [ExtensionSQ( cc.collector, G, M, 0 )]; elif Dimension( Image(cc.cohom)) = 1 then c := Basis(Image(cc.cohom))[1]; - c := PreImagesRepresentative(cc.cohom, c); + c := PreImagesRepresentativeNC(cc.cohom, c); return [ExtensionSQ( cc.collector, G, M, 0 ), ExtensionSQ( cc.collector, G, M, c )]; fi; @@ -1018,7 +1018,7 @@ function( G, M, C ) # compute orbit of mats on H^2( G, M ) Mgrp := GroupByGenerators( mats ); orbs := OrbitsDomain( Mgrp, Image(cc.cohom), OnRight ); - orbs := List( orbs, x -> PreImagesRepresentative( cc.cohom, x[1] ) ); + orbs := List( orbs, x -> PreImagesRepresentativeNC( cc.cohom, x[1] ) ); ext := List( orbs, x -> ExtensionSQ( cc.collector, G, M, x ) ); return ext; end); @@ -1113,7 +1113,7 @@ BindGlobal( "NonSplitExtensions", function( arg ) red := true; elif Dimension( Image(cc.cohom ) ) = 1 then - c := PreImagesRepresentative(cc.cohom, Basis(Image(cc.cohom))[1]); + c := PreImagesRepresentativeNC(cc.cohom, Basis(Image(cc.cohom))[1]); all := [ExtensionSQ( C, G, M, c)]; red := true; @@ -1121,7 +1121,7 @@ BindGlobal( "NonSplitExtensions", function( arg ) elif IsBound( arg[3] ) and not arg[3] then all := NormedRowVectors( Image(cc.cohom) ); all := List( all, x -> ExtensionSQ(cohom.collector, G, M, - PreImagesRepresentative(cc.cohom,x ))); + PreImagesRepresentativeNC(cc.cohom,x ))); red := false; # sometimes we do not want to reduce @@ -1132,7 +1132,7 @@ BindGlobal( "NonSplitExtensions", function( arg ) then all := NormedRowVectors( Image(cc.cohom) ); all := List( all, x -> ExtensionSQ(cc.collector, G, M, - PreImagesRepresentative(cc.cohom, x ))); + PreImagesRepresentativeNC(cc.cohom, x ))); red := false; # then we want to reduce @@ -1151,7 +1151,7 @@ BindGlobal( "NonSplitExtensions", function( arg ) # create extensions and add info all := List( all, x -> ExtensionSQ(cc.collector, G, M, - PreImagesRepresentative(cc.cohom, x ))); + PreImagesRepresentativeNC(cc.cohom, x ))); fi; if red then diff --git a/lib/grppclat.gi b/lib/grppclat.gi index 4b8113783e..b313ba6359 100644 --- a/lib/grppclat.gi +++ b/lib/grppclat.gi @@ -86,7 +86,7 @@ local f; else aut:= GroupHomomorphismByImagesNC(f,f,GeneratorsOfGroup(f), List(GeneratorsOfGroup(f), - i->Image(epi,Image(aut,PreImagesRepresentative(epi,i))))); + i->Image(epi,Image(aut,PreImagesRepresentativeNC(epi,i))))); SetIsInjective(aut,true); SetIsSurjective(aut,true); fi; @@ -672,7 +672,7 @@ local g, # group # hom:=[]; # for i in func do # hom2:=GroupHomomorphismByImagesNC(g,g,g.generators,List(g.generators, -# j->Image(isom,Image(i,PreImagesRepresentative(isom,j))))); +# j->Image(isom,Image(i,PreImagesRepresentativeNC(isom,j))))); # hom2.isMapping:=true; # Add(hom,hom2); # od; @@ -788,7 +788,7 @@ local g, # group hom:= GroupHomomorphismByImagesNC(f,fa,GeneratorsOfGroup(f), List(GeneratorsOfGroup(f),i-> - Image(hom,PreImagesRepresentative(epi,i)))); + Image(hom,PreImagesRepresentativeNC(epi,i)))); Assert(2,KernelOfMultiplicativeGeneralMapping(hom)=n); # lift the known groups diff --git a/lib/grpperm.gi b/lib/grpperm.gi index 020398dfe5..08f7805298 100644 --- a/lib/grpperm.gi +++ b/lib/grpperm.gi @@ -1592,7 +1592,7 @@ InstallGlobalFunction( SylowSubgroupPermGroup, function( G, p ) O := Orbit( S, D[1] ); f := ActionHomomorphism( S, O,"surjective" ); T := SylowSubgroupPermGroup( Range( f ), p ); - S := PreImagesSet( f, T ); + S := PreImagesSetNC( f, T ); SubtractSet( D, O ); od; return S; @@ -1605,7 +1605,7 @@ InstallGlobalFunction( SylowSubgroupPermGroup, function( G, p ) f := ActionHomomorphism( G, B, OnSets,"surjective" ); T := SylowSubgroupPermGroup( Range( f ), p ); if Size( T ) < Size( Range( f ) ) then - T := PreImagesSet( f, T ); + T := PreImagesSetNC( f, T ); S := SylowSubgroupPermGroup( T , p) ; return S; fi; @@ -1630,7 +1630,7 @@ InstallGlobalFunction( SylowSubgroupPermGroup, function( G, p ) Info(InfoGroup,1,"PermSylow: cycleaction"); f := ActionHomomorphism( C, B, OnSets,"surjective" ); T := SylowSubgroupPermGroup( Range( f ), p ); - S := PreImagesSet( f, T ); + S := PreImagesSetNC( f, T ); return S; end ); diff --git a/lib/grpprmcs.gi b/lib/grpprmcs.gi index c8a8a1166a..8ba3001d28 100644 --- a/lib/grpprmcs.gi +++ b/lib/grpprmcs.gi @@ -1173,7 +1173,7 @@ InstallGlobalFunction( PullbackKernelCSPG, fi; for g in gens do for j in [1..i-1] do - g := PreImagesRepresentative(homlist[i-j],g); + g := PreImagesRepresentativeNC(homlist[i-j],g); od; Add(normals[index],g); Add(factors[index],()); @@ -1193,7 +1193,7 @@ InstallGlobalFunction( PullbackCSPG, function(p,homlist) # compute a preimage of the permutation p in the input group lenhomlist := Length(homlist); for i in [1..lenhomlist] do - p := PreImagesRepresentative(homlist[lenhomlist+1-i],p); + p := PreImagesRepresentativeNC(homlist[lenhomlist+1-i],p); od; return p; end ); @@ -1522,7 +1522,7 @@ InstallMethod( PCoreOp, for g in GeneratorsOfGroup( KernelOfMultiplicativeGeneralMapping( homlist[i] ) ) do for j in [1..i-1] do - g := PreImagesRepresentative(homlist[i-j],g); + g := PreImagesRepresentativeNC(homlist[i-j],g); od; Add(pgenlist,g); od; @@ -1747,7 +1747,7 @@ InstallMethod( SolvableRadical, for g in GeneratorsOfGroup( KernelOfMultiplicativeGeneralMapping( homlist[i] ) ) do for j in [1..i-1] do - g := PreImagesRepresentative(homlist[i-j],g); + g := PreImagesRepresentativeNC(homlist[i-j],g); od; Add(solvable,g); od; @@ -1873,7 +1873,7 @@ InstallMethod( Centre, else order := Size( centr ); cent := IntersectionNormalClosurePermGroup(GG,centr,order*Size(GG)); - cent:= PreImages(tchom,cent); + cent:= PreImagesNC(tchom,cent); Assert( 1, IsAbelian( cent ) ); SetIsAbelian( cent, true ); return cent; @@ -1917,7 +1917,7 @@ InstallMethod( Centre, cent := IntersectionNormalClosurePermGroup ( GG, GroupByGenerators(hgens,()), order*Size(GG) ); if n <> len then - cent:= PreImages( tchom, cent ); + cent:= PreImagesNC( tchom, cent ); fi; Assert( 1, IsAbelian( cent ) ); SetIsAbelian( cent, true ); @@ -2012,7 +2012,7 @@ InstallGlobalFunction( CentralizerNormalCSPG, function(G,N) # handle case of transitive GG directly if Length(significant) = 1 then centrnorm := CentralizerNormalTransCSPG(GG,NN); - return PreImages(tchom,centrnorm); + return PreImagesNC(tchom,centrnorm); fi; # case of intransitive GG @@ -2054,7 +2054,7 @@ InstallGlobalFunction( CentralizerNormalCSPG, function(G,N) if n = len then return central; else - return PreImages(tchom,central); + return PreImagesNC(tchom,central); fi; end ); diff --git a/lib/info.gi b/lib/info.gi index 7436dfa86b..7c873f9661 100644 --- a/lib/info.gi +++ b/lib/info.gi @@ -45,11 +45,7 @@ DeclareRepresentation("IsInfoClassListRep", IsAtomicPositionalObjectRep); # A list of all created InfoClassListReps -INFO_CLASSES := []; - -# InfoData is unused, but we keep it for now, to avoid warnings in GAPDoc. -# TODO: remove InfoData -InfoData := rec(); +BIND_GLOBAL( "INFO_CLASSES", [] ); if IsHPCGAP then ShareInternalObj(INFO_CLASSES); diff --git a/lib/init.g b/lib/init.g index 03601c810a..f6061f1e58 100644 --- a/lib/init.g +++ b/lib/init.g @@ -34,8 +34,8 @@ OnBreak := function() Print("An error has occurred before the traceback ", ## break loop. ## OnBreakMessage := function() - Print("you can 'quit;' to quit to outer loop, or\n", - "you can 'return;' to continue\n"); + Print("you can enter 'quit;' to quit to outer loop, or\n", + "you can enter 'return;' to continue\n"); end; ############################################################################# @@ -434,7 +434,7 @@ function( prefix, values, suffix ) end); BindGlobal( "ShowKernelInformation", function() - local sysdate, btop, vert, bbot, config, str, gap; + local sysdate, btop, bmid, bbot, config, str, gap; if GAPInfo.Date <> "today" then sysdate := " of "; @@ -447,19 +447,23 @@ BindGlobal( "ShowKernelInformation", function() fi; if GAPInfo.TermEncoding = "UTF-8" then - btop := "┌───────┐\c"; vert := "│"; bbot := "└───────┘\c"; + btop := " ● G"; + bmid := "● ● A"; + bbot := " ● P"; else - btop := "*********"; vert := "*"; bbot := btop; + btop := " o G"; + bmid := "o o A"; + bbot := " o P"; fi; if IsHPCGAP then gap := "HPC-GAP"; else gap := "GAP"; fi; - Print( " ",btop," ",gap," ", GAPInfo.BuildVersion, + Print( " ",btop," ",gap," ", GAPInfo.BuildVersion, sysdate, "\n", - " ",vert," GAP ",vert," https://www.gap-system.org\n", - " ",bbot," Architecture: ", GAPInfo.Architecture, "\n" ); + " ",bmid," https://www.gap-system.org\n", + " ",bbot," Architecture: ", GAPInfo.Architecture, "\n" ); if IsHPCGAP then Print( " Maximum concurrent threads: ", GAPInfo.KernelInfo.NUM_CPUS, "\n"); diff --git a/lib/integer.gd b/lib/integer.gd index 20ca4e07ed..29be88cae8 100644 --- a/lib/integer.gd +++ b/lib/integer.gd @@ -249,12 +249,13 @@ DeclareGlobalFunction( "BestQuoInt" ); ## ChineseRem( [ 6, 10, 14 ], [ 1, 2, 3 ] ); ## Error, the residues must be equal modulo 2 +## Stack trace: ## *[1] Error( "the residues must be equal modulo ", g.gcd ); ## @ GAPROOT/lib/integer.gi:391 ## ( ) ## called from read-eval loop at *stdin*:2 -## you can 'quit;' to quit to outer loop, or -## you can 'return;' to continue +## you can enter 'quit;' to quit to outer loop, or +## you can enter 'return;' to continue ## brk> ## ]]> ## diff --git a/lib/integer.gi b/lib/integer.gi index b5da9421d7..9928ff6cb3 100644 --- a/lib/integer.gi +++ b/lib/integer.gi @@ -727,7 +727,7 @@ InstallGlobalFunction(FactorsInt,function ( n ) return Factors(n_orig); else Error( "sorry, cannot factor ", tmp[2], - "\ntype 'return;' to try again with a larger number of trials in\n", + "\nyou can enter 'return;' to try again with a larger number of trials in\n", "FactorsRho (or use option 'RhoTrials')\n"); if ValueOption("RhoTrials") <> fail then rt := 5 * ValueOption("RhoTrials"); diff --git a/lib/liefam.gi b/lib/liefam.gi index 6122a753b0..0f9f70c53f 100644 --- a/lib/liefam.gi +++ b/lib/liefam.gi @@ -447,7 +447,7 @@ InstallMethod( ImagesElm, return [ LieObject( elm ) ]; end ); -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for Lie embedding and Lie object in default representation", FamRangeEqFamElm, [ IsGeneralMapping and IsLieEmbeddingRep, @@ -456,6 +456,17 @@ InstallMethod( PreImagesElm, return [ elm![1] ]; end ); +InstallMethod( PreImagesElm, + "for Lie embedding and Lie object in default representation", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLieEmbeddingRep, + IsLieObject and IsPackedElementDefaultRep ], 0, + function( emb, elm ) + if not ( elm in Range(emb) ) then + return fail; + fi; + return PreImagesElm( emb, elm ); + end ); ############################################################################# ## diff --git a/lib/list.gd b/lib/list.gd index 5a44805bae..f595715899 100644 --- a/lib/list.gd +++ b/lib/list.gd @@ -379,7 +379,7 @@ DeclareSynonym( "AsSSortedListList", AS_LIST_SORTED_LIST ); ## Lists with holes are sometimes convenient when the list represents ## a mapping from a finite, but not consecutive, ## subset of the positive integers. -## IsDenseList( [ 1, 2, 3 ] ); ## true ## gap> l := [ , 4, 9,, 25,, 49,,,, 121 ];; IsDenseList( l ); @@ -387,22 +387,12 @@ DeclareSynonym( "AsSSortedListList", AS_LIST_SORTED_LIST ); ## gap> l[3]; ## 9 ## gap> l[4]; -## List Element: [4] must have an assigned value -## not in any function -## Entering break read-eval-print loop ... -## you can 'quit;' to quit to outer loop, or -## you can 'return;' after assigning a value to continue -## brk> l[4] := 16;; # assigning a value -## brk> return; # to escape the break-loop -## 16 -## gap> -## ]]> +## Error, List Element: [4] must have an assigned value +## ]]> ##

## Observe that requesting the value of l[4], which was not ## assigned, caused the entry of a break-loop ## (see Section ). -## After assigning a value and typing return;, &GAP; is finally -## able to comply with our request (by responding with 16). ## ## ## <#/GAPDoc> diff --git a/lib/mapphomo.gi b/lib/mapphomo.gi index 3e396945ff..fbd38cb004 100644 --- a/lib/mapphomo.gi +++ b/lib/mapphomo.gi @@ -330,9 +330,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesElm( , ) . for s.p. gen. mapping resp. mult. & inv. +#M PreImagesElmNC( , ) . for s.p. gen. mapping resp. mult. & inv. ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "method for s.p. general mapping respecting mult. & inv., and element", FamRangeEqFamElm, [ IsSPGeneralMapping and RespectsMultiplication and RespectsInverses, @@ -340,7 +340,7 @@ InstallMethod( PreImagesElm, function( map, elm ) local pre; - pre:= PreImagesRepresentative( map, elm ); + pre:= PreImagesRepresentativeNC( map, elm ); if pre = fail then return []; else @@ -351,9 +351,9 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) . for s.p. gen. mapping resp. mult. & inv. +#M PreImagesSetNC( , ) . for s.p. gen. mapping resp. mult. & inv. ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for s.p. general mapping respecting mult. & inv., and group", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsMultiplication and RespectsInverses, @@ -367,7 +367,7 @@ InstallMethod( PreImagesSet, fi; genpreimages:= List(genpreimages, - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -384,7 +384,7 @@ InstallMethod( PreImagesSet, return pre; end ); -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for injective s.p. mapping respecting mult. & inv., and group", CollFamRangeEqFamElms, [ IsSPGeneralMapping and IsMapping and IsInjective and @@ -395,7 +395,7 @@ InstallMethod( PreImagesSet, pre := SubgroupNC( Source( map ), List( GeneratorsOfMagmaWithInverses( elms ), - gen -> PreImagesRepresentative( map, gen ) ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ) ); UseIsomorphismRelation( elms, pre ); return pre; end ); @@ -684,9 +684,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesElm( , ) for s.p. gen. mapping resp. add. & add.inv. +#M PreImagesElmNC( , ) for s.p. gen. mapping resp. add. & add.inv. ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "method for s.p. gen. mapping respecting add. & add.inv., and element", FamRangeEqFamElm, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses, @@ -694,7 +694,7 @@ InstallMethod( PreImagesElm, function( map, elm ) local pre; - pre:= PreImagesRepresentative( map, elm ); + pre:= PreImagesRepresentativeNC( map, elm ); if pre = fail then return []; else @@ -705,9 +705,9 @@ InstallMethod( PreImagesElm, ############################################################################# ## -#M PreImagesSet( , ) for s.p. gen. mapping resp. add. & add.inv. +#M PreImagesSetNC( , ) for s.p. gen. mapp. resp. add. & add.inv. ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for s.p. gen. mapping resp. add. & add.inv., and add. group", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses, @@ -715,7 +715,7 @@ InstallMethod( PreImagesSet, function( map, elms ) local genpreimages; genpreimages:= List( GeneratorsOfAdditiveGroup( elms ), - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -890,9 +890,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesSet( , ) . . . . for linear mapping and left module +#M PreImagesSetNC( , ) . . . for linear mapping and left module ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for linear mapping and left module", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses @@ -901,7 +901,7 @@ InstallMethod( PreImagesSet, function( map, elms ) local genpreimages; genpreimages:= List( GeneratorsOfLeftModule( elms ), - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -984,9 +984,9 @@ InstallMethod( ImagesSet, ############################################################################# ## -#M PreImagesSet( , ) . . . . . . . . for algebra hom. and FLMLOR +#M PreImagesSetNC( , ) . . . . . . . for algebra hom. and FLMLOR ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for algebra hom. and FLMLOR", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses @@ -995,7 +995,7 @@ InstallMethod( PreImagesSet, function( map, elms ) local genpreimages; genpreimages:= List( GeneratorsOfLeftOperatorRing( elms ), - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; @@ -1010,9 +1010,9 @@ InstallMethod( PreImagesSet, ############################################################################# ## -#M PreImagesSet( , ) for alg.-with-one hom. and FLMLOR-with-one +#M PreImagesSetNC( , ) for alg-with-one hom. and FLMLOR-with-one ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "method for algebra-with-one hom. and FLMLOR-with-one", CollFamRangeEqFamElms, [ IsSPGeneralMapping and RespectsAddition and RespectsAdditiveInverses @@ -1022,7 +1022,7 @@ InstallMethod( PreImagesSet, function( map, elms ) local genpreimages; genpreimages:= List( GeneratorsOfLeftOperatorRingWithOne( elms ), - gen -> PreImagesRepresentative( map, gen ) ); + gen -> PreImagesRepresentativeNC( map, gen ) ); if fail in genpreimages then TryNextMethod(); fi; diff --git a/lib/mapping.gd b/lib/mapping.gd index 12d2ff39dc..2b391b67cb 100644 --- a/lib/mapping.gd +++ b/lib/mapping.gd @@ -751,7 +751,7 @@ DeclareAttribute( "ImagesSource", IsGeneralMapping ); ## ## is the set of preimages of the range of the general mapping map. ##

-## delegates to , +## delegates to , ## it is introduced only to store the preimage of map as attribute ## value. ## @@ -968,7 +968,8 @@ DeclareGlobalFunction( "Images" ); ############################################################################# ## -#O PreImagesElm( , ) . all preimages of elm under a gen. mapping +#O PreImagesElm( , ) . . . . . . . . . . . . all preimages of elm +#O PreImagesElmNC( , ) . . . . . . . . . . . under a gen. mapping ## ## <#GAPDoc Label="PreImagesElm"> ## @@ -976,16 +977,23 @@ DeclareGlobalFunction( "Images" ); ## ## ## If elm is an element of the range of the general mapping -## map then returns the set of all +## map then returns the set of all ## preimages of elm under map. ##

-## Anything may happen if elm is not an element of the range of -## map. +## From &GAP; version 4.16.0 +## PreImagesElm was renamed PreImagesElmNC +## throughout the library, and PreImagesElm now checks that +## elm is an element of the range before calling PreImagesElmNC. +##

+## When using PreImagesElmNC anything may happen if elm +## is not an element of the range of map. +##

## ## ## <#/GAPDoc> ## DeclareOperation( "PreImagesElm", [ IsGeneralMapping, IsObject ] ); +DeclareOperation( "PreImagesElmNC", [ IsGeneralMapping, IsObject ] ); ############################################################################# @@ -1015,11 +1023,12 @@ DeclareOperation( "PreImageElm", ############################################################################# ## #O PreImagesRepresentative( , ) . . . one preimage of an element -## under a gen. mapping +#O PreImagesRepresentativeNC( , ) . . . . under a general mapping ## ## <#GAPDoc Label="PreImagesRepresentative"> ## ## +## ## ## ## If elm is an element of the range of the general mapping @@ -1028,36 +1037,51 @@ DeclareOperation( "PreImageElm", ## fail, the latter if and only if elm ## has no preimages under map. ##

-## Anything may happen if elm is not an element of the range of -## map. +## From &GAP; version 4.16.0 PreImagesRepresentative +## was renamed PreImagesRepresentativeNC throughout the library, +## and PreImagesRepresentative now checks that elm is an +## element of the range before calling PreImagesRepresentativeNC. +##

+## When using PreImagesRepresentativeNC anything may happen if +## elm is not an element of the range of map. +##

## ## ## <#/GAPDoc> ## -DeclareOperation( "PreImagesRepresentative", - [ IsGeneralMapping, IsObject ] ); +DeclareOperation( "PreImagesRepresentative", [ IsGeneralMapping, IsObject ] ); +DeclareOperation( "PreImagesRepresentativeNC", [ IsGeneralMapping, IsObject ] ); ############################################################################# ## #O PreImagesSet( , ) +#O PreImagesSetNC( , ) ## ## <#GAPDoc Label="PreImagesSet"> ## ## +## ## ## ## If elms is a subset of the range of the general mapping map ## then returns the set of all preimages of ## elms under map. ##

-## Anything may happen if elms is not a subset of the range of -## map. +## From &GAP; version 4.16.0 PreImagesSet +## has been renamed PreImagesSetNC throughout the library, +## and PreImagesSet now checks that elms is a +## subset of the range before calling PreImagesSetNC. +##

+## When using PreImagesSetNC anything may happen if elms +## is not a subset of the range of map. +##

## ## ## <#/GAPDoc> ## DeclareOperation( "PreImagesSet", [ IsGeneralMapping, IsListOrCollection ] ); +DeclareOperation( "PreImagesSetNC", [ IsGeneralMapping, IsListOrCollection ] ); ############################################################################# @@ -1119,18 +1143,27 @@ DeclareGlobalFunction( "PreImage" ); ############################################################################# ## #F PreImages( ) . . . set of preimages of the range of a gen. mapping +#F PreImagesNC( ) . . set of preimages of the range of a gen. mapping #F PreImages(,) . set of preimages of an elm under a gen. mapping -#F PreImages(,) set of preimages of a coll. under a gen. mapping +#F PreImagesNC(,) set of preimages of an elm under a gen. mapping +#F PreImages(,) set of preimages of a coll. under a gen. mapping +#F PreImagesNC(,) set of preimages of a coll. under a gen. mapping ## ## <#GAPDoc Label="PreImages"> ## ## PreImages ## +## ## +## ## +## ## ## ## PreImages( map ) is the preimage of the general mapping @@ -1152,18 +1185,24 @@ DeclareGlobalFunction( "PreImage" ); ## entries do in general not correspond.) ##

## -## delegates to when -## called with one argument, +## delegates to when called with one argument, ## and to resp. when ## called with two arguments. ##

-## If the second argument is not an element or a subset of the range of -## the first argument, an error is signalled. +## From &GAP; version 4.16.0 PreImages +## has been renamed PreImagesNC throughout the library, +## and PreImages now checks that elm or coll +## belong to the range before calling PreImagesNC. +##

+## When using PreImagesNC anything may happen if elm +## or coll do not belong to the range of map. +##

## ## ## <#/GAPDoc> ## DeclareGlobalFunction( "PreImages" ); +DeclareGlobalFunction( "PreImagesNC" ); ############################################################################# diff --git a/lib/mapping.gi b/lib/mapping.gi index 7ae902e971..5069534ba6 100644 --- a/lib/mapping.gi +++ b/lib/mapping.gi @@ -273,9 +273,9 @@ InstallGlobalFunction( PreImage, function ( arg ) fi; if IsDomain( img ) or IsSSortedList( img ) then - return PreImagesSet( map, img ); + return PreImagesSetNC( map, img ); elif IsHomogeneousList( img ) then - return PreImagesSet( map, Set( img ) ); + return PreImagesSetNC( map, Set( img ) ); fi; # preimage of the empty list @@ -297,10 +297,68 @@ end ); ############################################################################# ## -#F PreImages( ) . . . set of preimages of the range of a gen. mapping -#F PreImages(,) . set of preimages of an elm under a gen. mapping -#F PreImages(,) set of preimages of a coll. under a gen. mapping +#F PreImages() +#F PreImagesNC() . . . set of preimages of the range of a gen. mapping +#F PreImages(,) +#F PreImagesNC(,) set of preimages of an elm under a gen. mapping +#F PreImages(,) +#F PreImagesNC(,) set of preimages of a coll. under a gen. mapping ## +InstallGlobalFunction( PreImagesNC, function ( arg ) + + local map, # mapping , first argument + img; # element , second argument + + # preimage of the range under + if Length( arg ) = 1 then + + return PreImagesRange( arg[1] ); + + elif Length( arg ) = 2 then + + map := arg[1]; + img := arg[2]; + + if not IsGeneralMapping( map ) then + ErrorNoReturn( " must be a general mapping" ); + fi; + + # preimage of a single element under + if FamRangeEqFamElm( FamilyObj( map ), FamilyObj( img ) ) then + if not img in Range( map ) then + ErrorNoReturn( " must be an element of Range()" ); + fi; + return PreImagesElmNC( map, img ); + + # preimage of a collection of elements under + elif CollFamRangeEqFamElms( FamilyObj( map ), FamilyObj( img ) ) then + if not IsSubset( Range( map ), img ) then + ErrorNoReturn( "the collection must be contained in ", + "Range()" ); + fi; + + if IsDomain( img ) or IsSSortedList( img ) then + return PreImagesSetNC( map, img ); + elif IsHomogeneousList( img ) then + return PreImagesSetNC( map, Set( img ) ); + fi; + + # preimage of the empty list + elif IsList( img ) and IsEmpty( img ) then + + return []; + + else + ErrorNoReturn( "the families of the element or collection ", + "and Range() don't match, ", + "maybe is not contained in Range() or ", + "is not a homogeneous list or collection" ); + fi; + fi; + ErrorNoReturn( "usage: PreImagesNC(), PreImagesNC(,), ", + "PreImagesNC(,)" ); +end ); + InstallGlobalFunction( PreImages, function ( arg ) local map, # mapping , first argument @@ -1067,16 +1125,17 @@ InstallMethod( PreImageElm, "for inj. & surj. general mapping, and element", FamRangeEqFamElm, [ IsGeneralMapping and IsInjective and IsSurjective, IsObject ], 0, - PreImagesRepresentative ); + PreImagesRepresentativeNC ); ############################################################################# ## #M PreImagesElm( , ) . . . . . . for general mapping and element +#M PreImagesElmNC( , ) . . . . . for general mapping and element ## ## more or less delegate to `ImagesElm' ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for general mapping with finite source, and element", FamRangeEqFamElm, [ IsGeneralMapping, IsObject ], 0, @@ -1093,12 +1152,26 @@ InstallMethod( PreImagesElm, fi; end ); +InstallMethod( PreImagesElm, + "for general mapping with finite source, and element", + FamRangeEqFamElm, + [ IsGeneralMapping, IsObject ], 0, + function ( map, elm ) + + if not ( elm in Image( map ) ) then + return fail; + else + return PreImagesElmNC( map, elm ); + fi; + end ); + ############################################################################# ## -#M PreImagesElm( , ) for const. time access gen. map., and elm. +#M PreImagesElm( , ) . for const. time access gen. map., and elm. +#M PreImagesElmNC( , ) for const. time access gen. map., and elm. ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for constant time access general mapping, and element", FamRangeEqFamElm, [ IsGeneralMapping and IsConstantTimeAccessGeneralMapping, IsObject ], 0, @@ -1113,12 +1186,25 @@ InstallMethod( PreImagesElm, return preimgs; end ); +InstallMethod( PreImagesElm, + "for constant time access general mapping, and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsConstantTimeAccessGeneralMapping, IsObject ], 0, + function( map, elm ) + if not ( elm in Image( map ) ) then + return fail; + else + return PreImagesElmNC( map, elm ); + fi; + end ); + ############################################################################# ## #M PreImagesSet( , ) . for general mapping and finite collection +#M PreImagesSetNC( , ) for general mapping and finite collection ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for general mapping, and finite collection", CollFamRangeEqFamElms, [ IsGeneralMapping, IsCollection ], 0, @@ -1129,12 +1215,31 @@ InstallMethod( PreImagesSet, fi; primgs:= []; for elm in Enumerator( elms ) do - UniteSet( primgs, AsList( PreImagesElm( map, elm ) ) ); + UniteSet( primgs, AsList( PreImagesElmNC( map, elm ) ) ); od; return primgs; end ); + InstallMethod( PreImagesSet, + "for general mapping, and finite collection", + CollFamRangeEqFamElms, + [ IsGeneralMapping, IsCollection ], 0, + function( map, elms ) + local im, elm; + if not IsFinite( elms ) then + TryNextMethod(); + fi; + im:= Image( map ); + for elm in Enumerator( elms ) do + if not (elm in im ) then + return fail; + fi; + od; + return PreImagesSetNC( map, elms ); + end ); + +InstallMethod( PreImagesSetNC, "for general mapping, and empty list", true, [ IsGeneralMapping, IsList and IsEmpty ], 0, @@ -1142,6 +1247,14 @@ InstallMethod( PreImagesSet, return []; end ); +InstallMethod( PreImagesSet, + "for general mapping, and empty list", + true, + [ IsGeneralMapping, IsList and IsEmpty ], 0, + function( map, elms ) + return []; + end ); + ############################################################################# ## @@ -1151,7 +1264,7 @@ InstallMethod( PreImagesRange, "for general mapping", true, [ IsGeneralMapping ], 0, - map -> PreImagesSet( map, Range( map ) ) ); + map -> PreImagesSetNC( map, Range( map ) ) ); ############################################################################# @@ -1169,6 +1282,7 @@ InstallMethod( PreImagesRange, ############################################################################# ## #M PreImagesRepresentative( , ) . . for s.p. gen. mapping & elm +#M PreImagesRepresentativeNC( , ) . for s.p. gen. mapping & elm ## InstallMethod( PreImagesRepresentative, "for s.p. general mapping, and element", @@ -1178,12 +1292,21 @@ InstallMethod( PreImagesRepresentative, Error( "no default method for s.p. general mapping" ); end ); +InstallMethod( PreImagesRepresentativeNC, + "for s.p. general mapping, and element", + FamRangeEqFamElm, + [ IsSPGeneralMapping, IsObject ], 0, + function( map, elm ) + Error( "no default method for s.p. general mapping" ); + end ); + ############################################################################# ## #M PreImagesRepresentative( , ) +#M PreImagesRepresentativeNC( , ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for total non-s.p. general mapping, and element", FamRangeEqFamElm, [ IsNonSPGeneralMapping, IsObject ], 0, @@ -1191,17 +1314,28 @@ InstallMethod( PreImagesRepresentative, local pres; # all preimages of under # get all preimages of under - pres := PreImagesElm( map, elm ); + pres := PreImagesElmNC( map, elm ); # check that has at least one preimage under if IsEmpty( pres ) then - return fail; + return []; fi; # pick one preimage, and return it. return Representative( pres ); end ); +InstallMethod( PreImagesRepresentative, + "for total non-s.p. general mapping, and element", + FamRangeEqFamElm, + [ IsNonSPGeneralMapping, IsObject ], 0, + function( map, elm ) + if not elm in Image( map ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + ############################################################################# ## @@ -1459,7 +1593,7 @@ InstallMethod( Enumerator, return enum; elif IsFinite( R ) then for elm in Enumerator( R ) do - imgs:= PreImagesElm( map, elm ); + imgs:= PreImagesElmNC( map, elm ); if IsFinite( imgs ) then UniteSet( enum, List( imgs, im -> DirectProductElement( [ im, elm ] ) ) ); else diff --git a/lib/mapprep.gi b/lib/mapprep.gi index 96bf008e8b..8be5d05fc6 100644 --- a/lib/mapprep.gi +++ b/lib/mapprep.gi @@ -302,65 +302,90 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## +#M PreImagesElmNC( , ) . . . . . . . . . for composition mapping #M PreImagesElm( , ) . . . . . . . . . . for composition mapping ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for a composition mapping, and an element", FamRangeEqFamElm, [ IsCompositionMappingRep, IsObject ], 0, function( com, elm ) local im; - im:= PreImagesElm( com!.map2, elm ); + im:= PreImagesElmNC( com!.map2, elm ); if not IsEmpty( im ) then - return PreImagesSet( com!.map1, im ); + return PreImagesSetNC( com!.map1, im ); else return []; fi; end ); +InstallMethod( PreImagesElm, + "for a composition mapping, and an element", + FamRangeEqFamElm, + [ IsCompositionMappingRep, IsObject ], 0, + function( com, elm ) + if not ( elm in Range(com) ) then + return fail; + fi; + return PreImagesElmNC( com, elm ); + end ); + ############################################################################# ## +#M PreImagesSetNC( , ) . . . . . . . . . for composition mapping #M PreImagesSet( , ) . . . . . . . . . . for composition mapping ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for a composition mapping, and a collection", CollFamRangeEqFamElms, [ IsCompositionMappingRep, IsCollection ], 0, function( com, elms ) local im; - im:= PreImagesSet( com!.map2, elms ); + im:= PreImagesSetNC( com!.map2, elms ); if not IsEmpty( im ) then - return PreImagesSet( com!.map1, im ); + return PreImagesSetNC( com!.map1, im ); else return []; fi; end ); +InstallMethod( PreImagesSet, + "for a composition mapping, and a collection", + CollFamRangeEqFamElms, + [ IsCompositionMappingRep, IsCollection ], 0, + function( com, elms ) + if not IsSubset( Range(com), elms ) then + return []; + fi; + return PreImagesSetNC( com, elms ); + end ); + ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . for composition mapping #M PreImagesRepresentative( , ) . . . . . for composition mapping ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for a composition mapping, and an element", FamRangeEqFamElm, [ IsCompositionMappingRep, IsObject ], 0, function( com, elm ) local im, rep; - im:= PreImagesRepresentative( com!.map2, elm ); + im:= PreImagesRepresentativeNC( com!.map2, elm ); if im = fail then # 'elm' has no preimages under 'com!.map2', so it has none under 'com'. return fail; else - im:= PreImagesRepresentative( com!.map1, im ); + im:= PreImagesRepresentativeNC( com!.map1, im ); if im <> fail then return im; fi; # It may happen that only the chosen representative has no preimages. - for im in Enumerator( PreImagesElm( com!.map2, elm ) ) do - rep:= PreImagesRepresentative( com!.map1, im ); + for im in Enumerator( PreImagesElmNC( com!.map2, elm ) ) do + rep:= PreImagesRepresentativeNC( com!.map1, im ); if rep <> fail then return rep; fi; @@ -369,6 +394,17 @@ InstallMethod( PreImagesRepresentative, fi; end ); +InstallMethod( PreImagesRepresentative, + "for a composition mapping, and an element", + FamRangeEqFamElm, + [ IsCompositionMappingRep, IsObject ], 0, + function( com, elm ) + if not ( elm in Range(com) ) then + return fail; + fi; + return PreImagesRepresentativeNC( com, elm ); + end ); + ############################################################################# ## @@ -383,7 +419,7 @@ InstallMethod( KernelOfAdditiveGeneralMapping, if IsInjective( com!.map2 ) then return KernelOfAdditiveGeneralMapping( com!.map1 ); else - return PreImagesSet( com!.map1, + return PreImagesSetNC( com!.map1, KernelOfAdditiveGeneralMapping( com!.map2 ) ); fi; end ); @@ -421,7 +457,7 @@ InstallMethod( KernelOfMultiplicativeGeneralMapping, if IsInjective( com!.map2 ) then return KernelOfMultiplicativeGeneralMapping( com!.map1 ); else - return PreImagesSet( com!.map1, + return PreImagesSetNC( com!.map1, KernelOfMultiplicativeGeneralMapping( com!.map2 ) ); fi; end ); @@ -629,9 +665,10 @@ end ); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . for mapping by function #M PreImagesRepresentative( , ) . . . . . for mapping by function ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for mapping by function", FamRangeEqFamElm, [ IsMappingByFunctionRep, IsObject ], 0, @@ -643,6 +680,17 @@ InstallMethod( PreImagesRepresentative, return map!.prefun( elm ); end ); +InstallMethod( PreImagesRepresentative, + "for mapping by function", + FamRangeEqFamElm, + [ IsMappingByFunctionRep, IsObject ], 0, + function ( map, elm ) + if not ( elm in Range(map) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + ############################################################################# ## @@ -659,9 +707,10 @@ InstallMethod( PreImageElm, ############################################################################# ## -#M PreImagesElm( , ) . . . . . . . . . . for mapping by function +#M PreImagesElmNC( , ) . . . . . . . . . . for mapping by function +#M PreImagesElm( , ) . . . . . . . . . . . for mapping by function ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for mapping by function", FamRangeEqFamElm, [ IsMappingByFunctionWithInverseRep, IsObject ], 0, @@ -669,11 +718,24 @@ InstallMethod( PreImagesElm, return [ map!.invFun( elm ) ]; end ); +InstallMethod( PreImagesElm, + "for mapping by function", + FamRangeEqFamElm, + [ IsMappingByFunctionWithInverseRep, IsObject ], 0, + function ( map, elm ) + if not ( elm in Range(map) ) then + return []; + fi; + return PreImagesElmNC( map, elm ); + end ); + + ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . for mapping by function #M PreImagesRepresentative( , ) . . . . . for mapping by function ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for mapping by function with inverse", FamRangeEqFamElm, [ IsMappingByFunctionWithInverseRep, IsObject ], 0, @@ -681,6 +743,16 @@ InstallMethod( PreImagesRepresentative, return map!.invFun( elm ); end ); +InstallMethod( PreImagesRepresentative, + "for mapping by function with inverse", + FamRangeEqFamElm, + [ IsMappingByFunctionWithInverseRep, IsObject ], 0, + function ( map, elm ) + if not ( elm in Range(map) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); ############################################################################# @@ -1008,7 +1080,7 @@ InstallMethod( ImagesElm, FamSourceEqFamElm, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0, function ( inv, elm ) - return PreImagesElm( InverseGeneralMapping( inv ), elm ); + return PreImagesElmNC( InverseGeneralMapping( inv ), elm ); end ); @@ -1021,7 +1093,7 @@ InstallMethod( ImagesSet, CollFamSourceEqFamElms, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0, function ( inv, elms ) - return PreImagesSet( InverseGeneralMapping( inv ), elms ); + return PreImagesSetNC( InverseGeneralMapping( inv ), elms ); end ); @@ -1034,7 +1106,7 @@ InstallMethod( ImagesRepresentative, FamSourceEqFamElm, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0, function ( inv, elm ) - return PreImagesRepresentative( InverseGeneralMapping( inv ), elm ); + return PreImagesRepresentativeNC( InverseGeneralMapping( inv ), elm ); end ); @@ -1054,9 +1126,10 @@ InstallMethod( PreImageElm, ############################################################################# ## +#M PreImagesElmNC( , ) . . . . for inverse mapping and element #M PreImagesElm( , ) . . . . . for inverse mapping and element ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for an inverse mapping and an element", FamRangeEqFamElm, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0, @@ -1064,12 +1137,24 @@ InstallMethod( PreImagesElm, return ImagesElm( InverseGeneralMapping( inv ), elm ); end ); +InstallMethod( PreImagesElm, + "for an inverse mapping and an element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0, + function ( inv, elm ) + if not ( elm in Range(inv) ) then + return []; + fi; + return PreImagesElmNC( inv, elm ); + end ); + ############################################################################# ## -#M PreImagesSet( , ) . . for inverse mapping and collection +#M PreImagesSetNC( , ) . . for inverse mapping and collection +#M PreImagesSet( , ) . . . for inverse mapping and collection ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for an inverse mapping and a collection", CollFamRangeEqFamElms, [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0, @@ -1077,12 +1162,24 @@ InstallMethod( PreImagesSet, return ImagesSet( InverseGeneralMapping( inv ), elms ); end ); +InstallMethod( PreImagesSet, + "for an inverse mapping and a collection", + CollFamRangeEqFamElms, + [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0, + function ( inv, elms ) + if not IsSubset( Range(inv), elms ) then + return []; + fi; + return PreImagesSetNC( inv, elms ); + end ); + ############################################################################# ## -#M PreImagesRepresentative( , ) . . for inv. mapping and elm. +#M PreImagesRepresentativeNC( , ) . . for inv. mapping and elm. +#M PreImagesRepresentative( , ) . . . for inv. mapping and elm. ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for an inverse mapping and an element", FamRangeEqFamElm, [ IsInverseGeneralMappingRep, IsObject ], 0, @@ -1090,6 +1187,17 @@ InstallMethod( PreImagesRepresentative, return ImagesRepresentative( InverseGeneralMapping( inv ), elm ); end ); +InstallMethod( PreImagesRepresentative, + "for an inverse mapping and an element", + FamRangeEqFamElm, + [ IsInverseGeneralMappingRep, IsObject ], 0, + function ( inv, elm ) + if not ( elm in Range(inv) ) then + return fail; + fi; + return PreImagesRepresentativeNC( inv, elm ); + end ); + ############################################################################# ## @@ -1293,9 +1401,10 @@ InstallMethod( PreImageElm, ############################################################################# ## +#M PreImagesElmMC( , ) . . . for identity mapping and element #M PreImagesElm( , ) . . . . for identity mapping and element ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for identity mapping and object", FamRangeEqFamElm, [ IsGeneralMapping and IsOne, IsObject ], @@ -1304,12 +1413,25 @@ InstallMethod( PreImagesElm, return [ elm ]; end ); +InstallMethod( PreImagesElm, + "for identity mapping and object", + FamRangeEqFamElm, + [ IsGeneralMapping and IsOne, IsObject ], + SUM_FLAGS, # can't do better + function ( id, elm ) + if not ( elm in Range(id) ) then + return []; + fi; + return PreImagesElmNC( id, elm ); + end ); + ############################################################################# ## +#M PreImagesSetNC( , ) . . for identity mapping and collection #M PreImagesSet( , ) . . . for identity mapping and collection ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for identity mapping and collection", CollFamRangeEqFamElms, [ IsGeneralMapping and IsOne, IsCollection ], @@ -1318,12 +1440,25 @@ InstallMethod( PreImagesSet, return elms; end ); +InstallMethod( PreImagesSet, + "for identity mapping and collection", + CollFamRangeEqFamElms, + [ IsGeneralMapping and IsOne, IsCollection ], + SUM_FLAGS, # can't do better + function ( id, elms ) + if not IsSubset( Range(id), elms ) then + return []; + fi; + return PreImagesSetNC( id, elms ); + end ); + ############################################################################# ## +#M PreImagesRepresentativeNC( , ) #M PreImagesRepresentative( , ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for identity mapping and object", FamRangeEqFamElm, [ IsGeneralMapping and IsOne, IsObject ], @@ -1332,6 +1467,17 @@ InstallMethod( PreImagesRepresentative, return elm; end ); +InstallMethod( PreImagesRepresentative, + "for identity mapping and object", + FamRangeEqFamElm, + [ IsGeneralMapping and IsOne, IsObject ], + SUM_FLAGS, # can't do better + function ( id, elm ) + if not ( elm in Range(id) ) then + return fail; + fi; + return elm; + end ); ############################################################################# ## @@ -1581,9 +1727,10 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## +#M PreImagesElmNC( , ) . . . . for zero mapping and element #M PreImagesElm( , ) . . . . . for zero mapping and element ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for zero mapping and object", FamRangeEqFamElm, [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, @@ -1595,12 +1742,24 @@ InstallMethod( PreImagesElm, fi; end ); +InstallMethod( PreImagesElm, + "for zero mapping and object", + FamRangeEqFamElm, + [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, + function( zero, elm ) + if not ( elm in Range(zero) ) then + return []; + fi; + return PreImagesElmNC( zero, elm ); + end ); + ############################################################################# ## +#M PreImagesSetNC( , ) . . . for zero mapping and collection #M PreImagesSet( , ) . . . . for zero mapping and collection ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for zero mapping and collection", CollFamRangeEqFamElms, [ IsGeneralMapping and IsZero, IsCollection ], SUM_FLAGS, @@ -1612,12 +1771,24 @@ InstallMethod( PreImagesSet, fi; end ); +InstallMethod( PreImagesSet, + "for zero mapping and collection", + CollFamRangeEqFamElms, + [ IsGeneralMapping and IsZero, IsCollection ], SUM_FLAGS, + function( zero, elms ) + if not IsSubset( Range(zero), elms ) then + return []; + fi; + return PreImagesSetNC( zero, elms ); + end ); + ############################################################################# ## +#M PreImagesRepresentativeNC( , ) #M PreImagesRepresentative( , ) ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for zero mapping and object", FamRangeEqFamElm, [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, @@ -1629,6 +1800,17 @@ InstallMethod( PreImagesRepresentative, fi; end ); +InstallMethod( PreImagesRepresentative, + "for zero mapping and object", + FamRangeEqFamElm, + [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS, + function( zero, elm ) + if not ( elm in Range(zero) ) then + return fail; + fi; + return PreImagesRepresentativeNC( zero, elm ); + end ); + ############################################################################# ## @@ -1817,34 +1999,47 @@ end ); ############################################################################# ## +#M PreImagesElmNC( , ) . . . . . . . . . for restricted mapping #M PreImagesElm( , ) . . . . . . . . . . for restricted mapping ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for a restricted mapping, and an element", FamRangeEqFamElm, [ IsGeneralRestrictedMappingRep, IsObject ], 0, function( res, elm ) local preim; - preim:= PreImagesElm( res!.map, elm ); + preim:= PreImagesElmNC( res!.map, elm ); if not ( (HasIsInjective(res) and IsInjective(res)) or (HasIsInjective(res!.map) and IsInjective(res!.map)) ) then preim:=Intersection(Source(res),preim); fi; return preim; -end ); + end ); + +InstallMethod( PreImagesElm, + "for a restricted mapping, and an element", + FamRangeEqFamElm, + [ IsGeneralRestrictedMappingRep, IsObject ], 0, + function( res, elm ) + if not ( elm in Range(res) ) then + return fail; + fi; + return PreImagesElmNC( res, elm ); + end ); ############################################################################# ## +#M PreImagesSetNC( , ) . . . . . . . . . for restricted mapping #M PreImagesSet( , ) . . . . . . . . . . for restricted mapping ## -InstallMethod( PreImagesSet, +InstallMethod( PreImagesSetNC, "for a restricted mapping, and a collection", CollFamRangeEqFamElms, [ IsGeneralRestrictedMappingRep, IsCollection ], 0, function( res, elms ) local preim; - preim:= PreImagesSet( res!.map, elms ); + preim:= PreImagesSetNC( res!.map, elms ); if not ( (HasIsInjective(res) and IsInjective(res)) or (HasIsInjective(res!.map) and IsInjective(res!.map)) ) then preim:=Intersection(Source(res),preim); @@ -1852,18 +2047,30 @@ InstallMethod( PreImagesSet, return preim; end ); +InstallMethod( PreImagesSet, + "for a restricted mapping, and a collection", + CollFamRangeEqFamElms, + [ IsGeneralRestrictedMappingRep, IsCollection ], 0, + function( res, elms ) + if not IsSubset( Range(res), elms ) then + return []; + fi; + return PreImagesSetNC( res, elms ); + end ); + ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . for restricted mapping #M PreImagesRepresentative( , ) . . . . . for restricted mapping ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for a restricted mapping, and an element", FamRangeEqFamElm, [ IsGeneralRestrictedMappingRep, IsObject ], 0, function( res, elm ) local preim; - preim:= PreImagesRepresentative( res!.map, elm ); + preim:= PreImagesRepresentativeNC( res!.map, elm ); if preim = fail then # 'elm' has no preimages under 'res!.map', so it has none under 'res'. return fail; @@ -1872,11 +2079,22 @@ InstallMethod( PreImagesRepresentative, elif HasIsInjective(res!.map) and IsInjective(res!.map) then return fail; # no other choice else - preim:= PreImages( res!.map, elm ); + preim:= PreImagesNC( res!.map, elm ); return First(preim,x->x in Source(res)); fi; end ); +InstallMethod( PreImagesRepresentative, + "for a restricted mapping, and an element", + FamRangeEqFamElm, + [ IsGeneralRestrictedMappingRep, IsObject ], 0, + function( res, elm ) + if not ( elm in Range(res) ) then + return fail; + fi; + return PreImagesRepresentativeNC( res, elm ); + end ); + ############################################################################# ## diff --git a/lib/matobjnz.gi b/lib/matobjnz.gi index c2edf17d3a..e2ac12cd69 100644 --- a/lib/matobjnz.gi +++ b/lib/matobjnz.gi @@ -1315,14 +1315,6 @@ InstallMethod( InverseSameMutability, "for a zmodnz matrix", return n; end ); -InstallMethod( RankMat, "for a zmodnz matrix", [ IsZmodnZMatrixRep ], -function( m ) - m:=MutableCopyMatrix(m); - m:=SemiEchelonMatDestructive(m); - if m<>fail then m:=Length(m.vectors);fi; - return m; -end); - #InstallMethodWithRandomSource( Randomize, # "for a random source and a mutable zmodnz matrix", @@ -1451,14 +1443,6 @@ InstallMethod( CompatibleVector, "for a zmodnz matrix", return NewZeroVector(IsZmodnZVectorRep,BaseDomain(v),NumberRows(v)); end ); -InstallMethod( DeterminantMat, "for a zmodnz matrix", [ IsZmodnZMatrixRep ], -function( a ) -local m; - m:=Size(BaseDomain(a)); - a:=List(a![ROWSPOS],x->x![ELSPOS]); - return ZmodnZObj(DeterminantMat(a),m); -end ); - # Minimal/Characteristic Polynomial stuff ############################################################################# diff --git a/lib/matrix.gd b/lib/matrix.gd index 4fe2262981..31ddbf47fb 100644 --- a/lib/matrix.gd +++ b/lib/matrix.gd @@ -296,7 +296,7 @@ DeclareSynonym( "DiagonalOfMat", DiagonalOfMatrix ); ## ## <#/GAPDoc> ## -DeclareAttribute( "BaseMat", IsMatrix ); +DeclareAttribute( "BaseMat", IsMatrixOrMatrixObj ); ############################################################################# ## @@ -323,7 +323,7 @@ DeclareAttribute( "BaseMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "BaseMatDestructive", [ IsMatrix ] ); +DeclareOperation( "BaseMatDestructive", [ IsMatrixOrMatrixObj ] ); ############################################################################# ## @@ -345,7 +345,7 @@ DeclareOperation( "BaseMatDestructive", [ IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareAttribute( "BaseOrthogonalSpaceMat", IsMatrix ); +DeclareAttribute( "BaseOrthogonalSpaceMat", IsMatrixOrMatrixObj ); ############################################################################# @@ -372,7 +372,7 @@ DeclareAttribute( "BaseOrthogonalSpaceMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareAttribute( "DefaultFieldOfMatrix", IsMatrix ); +DeclareAttribute( "DefaultFieldOfMatrix", IsMatrixOrMatrixObj ); ############################################################################# @@ -396,7 +396,7 @@ DeclareAttribute( "DefaultFieldOfMatrix", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareAttribute( "DepthOfUpperTriangularMatrix", IsMatrix ); +DeclareAttribute( "DepthOfUpperTriangularMatrix", IsMatrixOrMatrixObj ); ############################################################################# @@ -503,7 +503,7 @@ DeclareSynonym( "DeterminantMatDivFree", DeterminantMatrixDivFree ); ## ## <#/GAPDoc> ## -DeclareAttribute( "DimensionsMat", IsMatrix ); +DeclareAttribute( "DimensionsMat", IsMatrixOrMatrixObj ); ############################################################################# @@ -550,7 +550,7 @@ DeclareAttribute( "DimensionsMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "ElementaryDivisorsMat", [IsRing,IsMatrix] ); +DeclareOperation( "ElementaryDivisorsMat", [IsRing, IsMatrixOrMatrixObj] ); DeclareGlobalFunction( "ElementaryDivisorsMatDestructive" ); ############################################################################# @@ -623,7 +623,7 @@ DeclareGlobalFunction( "ElementaryDivisorsMatDestructive" ); ## ## <#/GAPDoc> ## -DeclareOperation( "ElementaryDivisorsTransformationsMat", [IsRing,IsMatrix] ); +DeclareOperation( "ElementaryDivisorsTransformationsMat", [IsRing, IsMatrixOrMatrixObj] ); DeclareGlobalFunction( "ElementaryDivisorsTransformationsMatDestructive" ); ############################################################################# @@ -640,7 +640,7 @@ DeclareGlobalFunction( "ElementaryDivisorsTransformationsMatDestructive" ); ## ## ## -DeclareOperation( "TriangulizedNullspaceMatNT", [ IsMatrix ] ); +DeclareOperation( "TriangulizedNullspaceMatNT", [ IsMatrixOrMatrixObj ] ); ############################################################################# @@ -666,8 +666,8 @@ DeclareOperation( "TriangulizedNullspaceMatNT", [ IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareAttribute( "NullspaceMat", IsMatrix ); -DeclareAttribute( "TriangulizedNullspaceMat", IsMatrix ); +DeclareAttribute( "NullspaceMat", IsMatrixOrMatrixObj ); +DeclareAttribute( "TriangulizedNullspaceMat", IsMatrixOrMatrixObj ); ############################################################################# @@ -706,8 +706,8 @@ DeclareAttribute( "TriangulizedNullspaceMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "NullspaceMatDestructive", [ IsMatrix and IsMutable] ); -DeclareOperation( "TriangulizedNullspaceMatDestructive", [ IsMatrix and IsMutable] ); +DeclareOperation( "NullspaceMatDestructive", [ IsMatrixOrMatrixObj and IsMutable] ); +DeclareOperation( "TriangulizedNullspaceMatDestructive", [ IsMatrixOrMatrixObj and IsMutable] ); ############################################################################# @@ -779,7 +779,7 @@ DeclareOperation( "Eigenvalues", [ IsRing, IsMatrixOrMatrixObj ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "Eigenspaces", [ IsRing, IsMatrix ] ); +DeclareOperation( "Eigenspaces", [ IsRing, IsMatrixOrMatrixObj ] ); ############################################################################# ## @@ -795,7 +795,7 @@ DeclareOperation( "Eigenspaces", [ IsRing, IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "Eigenvectors", [ IsRing, IsMatrix ] ); +DeclareOperation( "Eigenvectors", [ IsRing, IsMatrixOrMatrixObj ] ); ############################################################################# @@ -926,7 +926,7 @@ DeclareSynonymAttr( "RankMatDestructive", RankMatrixDestructive ); ## ## <#/GAPDoc> ## -DeclareAttribute( "SemiEchelonMat", IsMatrix ); +DeclareAttribute( "SemiEchelonMat", IsMatrixOrMatrixObj ); ############################################################################# ## @@ -950,7 +950,7 @@ DeclareAttribute( "SemiEchelonMat", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "SemiEchelonMatDestructive", [ IsMatrix and IsMutable] ); +DeclareOperation( "SemiEchelonMatDestructive", [ IsMatrixOrMatrixObj and IsMutable] ); ############################################################################# @@ -987,7 +987,7 @@ DeclareOperation( "SemiEchelonMatDestructive", [ IsMatrix and IsMutable] ); ## ## <#/GAPDoc> ## -DeclareAttribute( "SemiEchelonMatTransformation", IsMatrix ); +DeclareAttribute( "SemiEchelonMatTransformation", IsMatrixOrMatrixObj ); ############################################################################# ## @@ -1003,7 +1003,7 @@ DeclareAttribute( "SemiEchelonMatTransformation", IsMatrix ); ## ## DeclareOperation( "SemiEchelonMatTransformationDestructive", [ - IsMatrix and IsMutable ] ); + IsMatrixOrMatrixObj and IsMutable ] ); ############################################################################# @@ -1135,7 +1135,7 @@ DeclareSynonym( "MutableTransposedMat", TransposedMatMutable ); # needed? ## ## ## -DeclareOperation( "MutableTransposedMatDestructive", [IsMatrix and IsMutable] ); +DeclareOperation( "MutableTransposedMatDestructive", [IsMatrixOrMatrixObj and IsMutable] ); ############################################################################# @@ -1163,7 +1163,7 @@ DeclareOperation( "MutableTransposedMatDestructive", [IsMatrix and IsMutable] ); ## ## <#/GAPDoc> ## -DeclareOperation( "TransposedMatDestructive", [ IsMatrix ] ); +DeclareOperation( "TransposedMatDestructive", [ IsMatrixOrMatrixObj ] ); @@ -1186,7 +1186,7 @@ DeclareOperation( "TransposedMatDestructive", [ IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareProperty( "IsMonomialMatrix", IsMatrix ); +DeclareProperty( "IsMonomialMatrix", IsMatrixOrMatrixObj ); ############################################################################# @@ -1211,7 +1211,7 @@ DeclareProperty( "IsMonomialMatrix", IsMatrix ); ## ## <#/GAPDoc> ## -DeclareOperation( "InverseMatMod", [ IsMatrix, IsObject ] ); +DeclareOperation( "InverseMatMod", [ IsMatrixOrMatrixObj, IsObject ] ); ############################################################################# @@ -1246,11 +1246,11 @@ DeclareOperation( "KroneckerProduct", [ IsMatrixOrMatrixObj, IsMatrixOrMatrixObj ## ## ## -## Does thework for SolutionMat and SolutionMatDestructive. +## Does the work for SolutionMat and SolutionMatDestructive. ## ## ## -DeclareOperation( "SolutionMatNoCo", [ IsMatrix, IsRowVector ] ); +DeclareOperation( "SolutionMatNoCo", [ IsMatrixOrMatrixObj, IsRowVectorOrVectorObj ] ); ############################################################################# @@ -1268,7 +1268,7 @@ DeclareOperation( "SolutionMatNoCo", [ IsMatrix, IsRowVector ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "SolutionMat", [ IsMatrix, IsRowVector ] ); +DeclareOperation( "SolutionMat", [ IsMatrixOrMatrixObj, IsRowVectorOrVectorObj ] ); ############################################################################# ## @@ -1300,7 +1300,7 @@ DeclareOperation( "SolutionMat", [ IsMatrix, IsRowVector ] ); ## <#/GAPDoc> ## DeclareOperation( "SolutionMatDestructive", - [ IsMatrix and IsMutable, IsRowVector ] ); + [ IsMatrixOrMatrixObj and IsMutable, IsRowVectorOrVectorObj ] ); ############################################################################ @@ -1326,7 +1326,7 @@ DeclareOperation( "SolutionMatDestructive", ## ## <#/GAPDoc> ## -DeclareOperation( "SumIntersectionMat", [ IsMatrix, IsMatrix ] ); +DeclareOperation( "SumIntersectionMat", [ IsMatrixOrMatrixObj, IsMatrixOrMatrixObj ] ); @@ -1349,7 +1349,7 @@ DeclareOperation( "SumIntersectionMat", [ IsMatrix, IsMatrix ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "TriangulizedMat", [ IsMatrix ] ); +DeclareOperation( "TriangulizedMat", [ IsMatrixOrMatrixObj ] ); DeclareSynonym( "RREF", TriangulizedMat); ############################################################################# @@ -1380,7 +1380,7 @@ DeclareSynonym( "RREF", TriangulizedMat); ## ## <#/GAPDoc> ## -DeclareOperation( "TriangulizeMat", [ IsMatrix and IsMutable ] ); +DeclareOperation( "TriangulizeMat", [ IsMatrixOrMatrixObj and IsMutable ] ); ############################################################################# @@ -1574,7 +1574,7 @@ DeclareGlobalFunction( "BlownUpVector" ); ## ## <#/GAPDoc> ## -DeclareOperation( "DiagonalizeMat", [IsRing,IsMatrix and IsMutable] ); +DeclareOperation( "DiagonalizeMat", [IsRing, IsMatrixOrMatrixObj and IsMutable] ); ############################################################################# @@ -2199,7 +2199,7 @@ DeclareSynonymAttr( "TraceMat", TraceMatrix ); ## ## <#/GAPDoc> ## -DeclareAttribute( "JordanDecomposition", IsMatrix ); +DeclareAttribute( "JordanDecomposition", IsMatrixOrMatrixObj ); ############################################################################# @@ -2382,7 +2382,7 @@ DeclareOperation( "CharacteristicPolynomial", ## DeclareOperation("CharacteristicPolynomialMatrixNC", #IsField is not yet known - [IsRing,IsOrdinaryMatrix,IsPosInt]); + [IsRing,IsMatrixOrMatrixObj,IsPosInt]); ############################################################################# @@ -2400,7 +2400,7 @@ DeclareOperation("CharacteristicPolynomialMatrixNC", ## DeclareOperation("MinimalPolynomialMatrixNC", #IsField is not yet known - [IsRing,IsOrdinaryMatrix,IsPosInt]); + [IsRing,IsMatrixOrMatrixObj,IsPosInt]); ############################################################################# ## diff --git a/lib/matrix.gi b/lib/matrix.gi index 569d65c5b9..11b16fb563 100644 --- a/lib/matrix.gi +++ b/lib/matrix.gi @@ -805,7 +805,7 @@ InstallMethod( CharacteristicPolynomial, "spinning over field", fi; return false; end, - [ IsField, IsField, IsOrdinaryMatrix, IsPosInt ], + [ IsField, IsField, IsMatrixOrMatrixObj, IsPosInt ], function( F, E, mat, inum ) local B; @@ -824,7 +824,7 @@ InstallMethod( CharacteristicPolynomial, "spinning over field", InstallMethod( CharacteristicPolynomialMatrixNC, "spinning over field", IsElmsCollsX, - [ IsField, IsOrdinaryMatrix, IsPosInt ], + [ IsField, IsMatrixOrMatrixObj, IsPosInt ], Matrix_CharacteristicPolynomialSameField); InstallOtherMethod( CharacteristicPolynomial, @@ -868,7 +868,7 @@ InstallOtherMethod( CharacteristicPolynomialMatrixNC, InstallMethod( MinimalPolynomial, "spinning over field", IsElmsCollsX, - [ IsField, IsOrdinaryMatrix, IsPosInt ], + [ IsField, IsMatrixOrMatrixObj, IsPosInt ], function( F, mat,inum ) local fld, B; @@ -905,7 +905,7 @@ end); InstallMethod( MinimalPolynomialMatrixNC, "spinning over field", IsElmsCollsX, - [ IsField, IsOrdinaryMatrix, IsPosInt ], + [ IsField, IsMatrixOrMatrixObj, IsPosInt ], Matrix_MinimalPolynomialSameField); InstallOtherMethod( MinimalPolynomial, @@ -1597,7 +1597,7 @@ end); ## InstallMethod( DeterminantMatDestructive, "fraction-free method", - [ IsOrdinaryMatrix and IsMutable], + [ IsMatrixOrMatrixObj and IsMutable], function ( mat ) local det, sgn, row, zero, m, i, j, k, mult, row2, piv; @@ -1668,7 +1668,7 @@ end); ## through here also. ## InstallMethod( DeterminantMatDestructive,"non fraction free", - [ IsOrdinaryMatrix and IsFFECollColl and IsMutable], + [ IsMatrixOrMatrixObj and IsFFECollColl and IsMutable], function( mat ) local m, zero, det, sgn, k, j, row, l, row2, x; @@ -1743,7 +1743,7 @@ InstallMethod( DeterminantMat, end ); InstallMethod( DeterminantMatDestructive,"nonprime residue rings", - [ IsOrdinaryMatrix and + [ IsMatrixOrMatrixObj and CategoryCollections(CategoryCollections(IsZmodnZObjNonprime)) and IsMutable], DeterminantMatDivFree); @@ -1779,7 +1779,7 @@ InstallMethod( DeterminantMatDestructive,"nonprime residue rings", ## InstallMethod( DeterminantMatDivFree, "Division-free method", - [ IsMatrix ], + [ IsMatrixOrMatrixObj ], function ( M ) local u,v,w,i, ## indices a,b,c,x,y, ## temp indices @@ -2335,7 +2335,7 @@ end ); ## InstallMethod( NullspaceMat, "generic method for ordinary matrices", - [ IsOrdinaryMatrix ], + [ IsMatrixOrMatrixObj ], mat -> SemiEchelonMatTransformation(mat).relations ); InstallOtherMethod(NullspaceMat,"matrix objects",[IsMatrixObj], @@ -2356,7 +2356,7 @@ end); InstallMethod( NullspaceMatDestructive, "generic method for ordinary matrices", - [ IsOrdinaryMatrix and IsMutable], + [ IsMatrixOrMatrixObj and IsMutable], mat -> SemiEchelonMatTransformationDestructive(mat).relations ); InstallOtherMethod( TriangulizedNullspaceMat, @@ -2381,7 +2381,7 @@ end ); InstallMethod( TriangulizedNullspaceMatNT, "generic method", - [ IsOrdinaryMatrix ], + [ IsMatrixOrMatrixObj ], function( mat ) local nullspace, n, empty, i, k, row, zero, one;# @@ -2425,7 +2425,7 @@ InstallMethod( TriangulizedNullspaceMatNT, end ); #InstallMethod(TriangulizedNullspaceMat,"generic method", -# [IsOrdinaryMatrix], +# [IsMatrixOrMatrixObj], # function ( mat ) # # triangulize the transposed of the matrix # return TriangulizedNullspaceMatNT( @@ -2433,7 +2433,7 @@ end ); #end ); #InstallMethod(TriangulizedNullspaceMatDestructive,"generic method", -# [IsOrdinaryMatrix], +# [IsMatrixOrMatrixObj], # function ( mat ) # # triangulize the transposed of the matrix # return TriangulizedNullspaceMatNT( @@ -2545,7 +2545,7 @@ InstallOtherMethod( ProjectiveOrder, ## InstallOtherMethod( RankMatDestructive, "generic method for mutable matrices", - [ IsMatrix and IsMutable ], + [ IsMatrixOrMatrixObj and IsMutable ], function( mat ) mat:= SemiEchelonMatDestructive( mat ); if mat <> fail then @@ -2556,7 +2556,7 @@ InstallOtherMethod( RankMatDestructive, InstallOtherMethod( RankMat, "generic method for matrices", - [ IsMatrix ], + [ IsMatrixOrMatrixObj ], mat -> RankMatDestructive( MutableCopyMatrix( mat ) ) ); diff --git a/lib/maxsub.gi b/lib/maxsub.gi index e04c94eaa5..c69f873028 100644 --- a/lib/maxsub.gi +++ b/lib/maxsub.gi @@ -182,7 +182,7 @@ BindGlobal("MaximalSubgroupClassesSol",function(G) sel:=Filtered([1..Length(mgi[2])],x->not IsOne(mgi[2][x])); if 4^Length(sel)>Size(Range(ff.factorhom)) then f:=SmallGeneratingSet(Image(ff.factorhom)); - mgi:=[List(f,x->PreImagesRepresentative(ff.factorhom,x)),f]; + mgi:=[List(f,x->PreImagesRepresentativeNC(ff.factorhom,x)),f]; sel:=[1..Length(mgi[1])]; fi; gensG:=mgi[1]{sel}; @@ -195,8 +195,8 @@ BindGlobal("MaximalSubgroupClassesSol",function(G) fam:=FamilyObj(One(Range(fphom))); # just in case the stored group generators differ... wordfpgens:=List(wordgens,x->ElementOfFpGroup(fam,x)); - wordpre:=List(wordfpgens,x->PreImagesRepresentative(ff.factorhom, - PreImagesRepresentative(fphom,x))); + wordpre:=List(wordfpgens,x->PreImagesRepresentativeNC(ff.factorhom, + PreImagesRepresentativeNC(fphom,x))); fphom:=ff.factorhom*fphom; # no assertion as this is not a proper homomorphism, but an inverse # multiplicative map @@ -219,10 +219,8 @@ BindGlobal("MaximalSubgroupClassesSol",function(G) # if necessary extent the fphom if homliftlevel+1PreImagesRepresentative(projG,RepresentativeAction(Image(projG),1,i))); + reps:=List([1..n],i->PreImagesRepresentativeNC(projG,RepresentativeAction(Image(projG),1,i))); reps[n+1]:= - PreImagesRepresentative(proj,RepresentativeAction(Image(proj),[1..n],[n+1..2*n],OnSets)); + PreImagesRepresentativeNC(proj,RepresentativeAction(Image(proj),[1..n],[n+1..2*n],OnSets)); for i in [2..n] do j:=reps[i]*reps[n+1]; reps[1^Image(proj,j)]:=j; @@ -665,8 +663,8 @@ local dom, o, t1, a1, t1d, proj, reps, ts, ta, tb, s1, i, fix, wnew, max, s, p1, en1:=Embedding(wnew,1); en2:=Embedding(wnew,2); emb:=List(GeneratorsOfGroup(s),i-> - Image(en1,PreImagesRepresentative(p1,RestrictedPerm(i,ts[1]))) - *Image(en2,PreImagesRepresentative(p2,RestrictedPerm(i,ts[f]))) ); + Image(en1,PreImagesRepresentativeNC(p1,RestrictedPerm(i,ts[1]))) + *Image(en2,PreImagesRepresentativeNC(p2,RestrictedPerm(i,ts[f]))) ); emb:=GroupHomomorphismByImages(s,wnew,GeneratorsOfGroup(s),emb); ma:=MaxesType3(wnew,Image(emb,s),a1,t1,2,false); for i in ma do @@ -699,7 +697,7 @@ local m, fact, fg, reps, ma, idx, nm, embs, proj, kproj, k, ag, agl, ug, # type 4c reps:=List([1..n], - i->PreImagesRepresentative(fact,RepresentativeAction(fg,1,i))); + i->PreImagesRepresentativeNC(fact,RepresentativeAction(fg,1,i))); # get the maximal subgroups of A, intersect with t to get the socle part @@ -758,8 +756,8 @@ local m, fact, fg, reps, ma, idx, nm, embs, proj, kproj, k, ag, agl, ug, #phi:=ActionHomomorphism(fg,u.orbit,OnSets); #ue:=Image(phi,fg); #reps:=List([1..nlb],i->RepresentativeAction(ue,1,i)); - #reps:=List(reps,i->PreImagesRepresentative(phi,i)); - #reps:=List(reps,i->PreImagesRepresentative(fact,i)); + #reps:=List(reps,i->PreImagesRepresentativeNC(phi,i)); + #reps:=List(reps,i->PreImagesRepresentativeNC(fact,i)); #u:=u.stabilizer; uphi:=ActionHomomorphism(Image(fact,u),b); diff --git a/lib/methsel2.g b/lib/methsel2.g index 51700574ea..a56b928f5a 100644 --- a/lib/methsel2.g +++ b/lib/methsel2.g @@ -252,8 +252,7 @@ end; context := GetCurrentLVars(), tracebackContext := ParentLVars(GetCurrentLVars()), mayReturnVoid := false, - mayReturnObj := false, - lateMessage := "type 'quit;' to quit to outer loop" + lateMessage := "you can enter 'quit;' to quit to outer loop" ), [ no_method_found ]); end; diff --git a/lib/mgmring.gi b/lib/mgmring.gi index 077f27c153..d4d0771b79 100644 --- a/lib/mgmring.gi +++ b/lib/mgmring.gi @@ -1220,7 +1220,7 @@ InstallMethod( ImagesRepresentative, end ); -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for embedding of ring into magma ring, and free magma ring element", FamRangeEqFamElm, [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], @@ -1236,7 +1236,18 @@ InstallMethod( PreImagesElm, fi; end ); -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesElm, + "for embedding of ring into magma ring, and free magma ring element", + FamRangeEqFamElm, + [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], + function ( emb, elm ) + if not ( elm in Range( emb ) ) then + return fail; + fi; + return PreImagesElm( emb, elm ); + end ); + +InstallMethod( PreImagesRepresentativeNC, "for embedding of ring into magma ring, and free magma ring element", FamRangeEqFamElm, [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], @@ -1252,6 +1263,17 @@ InstallMethod( PreImagesRepresentative, fi; end ); +InstallMethod( PreImagesRepresentative, + "for embedding of ring into magma ring, and free magma ring element", + FamRangeEqFamElm, + [ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ], + function ( emb, elm ) + if not ( elm in Range( emb ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( emb, elm ); + end ); + ############################################################################# ## @@ -1324,7 +1346,7 @@ InstallMethod( ImagesRepresentative, end ); -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "for embedding of magma into magma ring, and free magma ring element", FamRangeEqFamElm, [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], @@ -1340,7 +1362,18 @@ InstallMethod( PreImagesElm, fi; end ); -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesElm, + "for embedding of magma into magma ring, and free magma ring element", + FamRangeEqFamElm, + [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], + function ( emb, elm ) + if not ( elm in Range( emb ) ) then + return fail; + fi; + return PreImagesElmNC( emb, elm ); + end ); + +InstallMethod( PreImagesRepresentativeNC, "for embedding of magma into magma ring, and free magma ring element", FamRangeEqFamElm, [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], @@ -1356,6 +1389,16 @@ InstallMethod( PreImagesRepresentative, fi; end ); +InstallMethod( PreImagesRepresentative, + "for embedding of magma into magma ring, and free magma ring element", + FamRangeEqFamElm, + [ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ], + function ( emb, elm ) + if not ( elm in Range( emb ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( emb, elm ); + end ); ############################################################################# ## diff --git a/lib/morpheus.gi b/lib/morpheus.gi index 0e92772399..a440d864fc 100644 --- a/lib/morpheus.gi +++ b/lib/morpheus.gi @@ -748,10 +748,10 @@ local hom, gens, c, ran, r, cen, img, u, orbs, function(perm) if perm in store[1] then return ConjugatorAutomorphismNC(g, - PreImagesRepresentative(img[2],perm)); + PreImagesRepresentativeNC(img[2],perm)); fi; return GroupHomomorphismByImagesNC(g,g,GeneratorsOfGroup(g), - List(store[2],i->PreImagesRepresentative(img[2],i^perm))); + List(store[2],i->PreImagesRepresentativeNC(img[2],i^perm))); end); if bestdegPreImagesRepresentative(store[3],i^perm))); + List(store[4],i->PreImagesRepresentativeNC(store[3],i^perm))); end); if bestdegPreImagesRepresentative(gens,i)); + i->PreImagesRepresentativeNC(gens,i)); Ggc:=List(gens,i->First(Gcl,j->ForAny(j,j->ForAny(j.classes,k->i in k)))); combi:=List(Ggc,i->Concatenation(List(i,i->i.classes))); bcl:=ShallowCopy(combi); @@ -2106,7 +2116,7 @@ local d,id,H,iso,aut,auts,i,all,hom,field,dim,P,diag,mats,gens,gal; fi; aut:=GroupGeneralMappingByImages(G,G,gens, List(gens, - x->PreImagesRepresentative(iso,Image(iso,x)^(1,2)))); + x->PreImagesRepresentativeNC(iso,Image(iso,x)^(1,2)))); auts:=[aut]; all:=true; fi; @@ -2167,7 +2177,7 @@ local d,id,H,iso,aut,auts,i,all,hom,field,dim,P,diag,mats,gens,gal; fi; auts:=Concatenation(auts, List(mats,s->GroupGeneralMappingByImages(G,G,gens,List(gens,x-> - Image(hom,PreImagesRepresentative(hom,x)^s))))); + Image(hom,PreImagesRepresentativeNC(hom,x)^s))))); else gal:=Group(()); # to force trivial @@ -2179,13 +2189,13 @@ local d,id,H,iso,aut,auts,i,all,hom,field,dim,P,diag,mats,gens,gal; List(MinimalGeneratingSet(gal), s->GroupGeneralMappingByImages(G,G,gens,List(gens,x-> Image(hom, - List(PreImagesRepresentative(hom,x),r->List(r,y->Image(s,y)))))))); + List(PreImagesRepresentativeNC(hom,x),r->List(r,y->Image(s,y)))))))); fi; # graph if id.series="L" and id.parameter[1]>2 then Add(auts, GroupGeneralMappingByImages(G,G,gens,List(gens,x-> - Image(hom,Inverse(TransposedMat(PreImagesRepresentative(hom,x))))))); + Image(hom,Inverse(TransposedMat(PreImagesRepresentativeNC(hom,x))))))); all:=true; elif id.series="L" and id.parameter[1]=2 then # note no graph @@ -2350,7 +2360,7 @@ InstallGlobalFunction(AutomorphismGroupFittingFree,function(g) thom:=i[j][2]; thom:=GroupHomomorphismByImagesNC(t,t,GeneratorsOfGroup(t), List(GeneratorsOfGroup(t), - j->Image(thom,PreImagesRepresentative(thom,j)^gen))); + j->Image(thom,PreImagesRepresentativeNC(thom,j)^gen))); thom:=Image(auph,thom); Add(genimgs,thom); od; @@ -2408,7 +2418,7 @@ InstallGlobalFunction(AutomorphismGroupFittingFree,function(g) for i in gens do au:=GroupHomomorphismByImages(g,g,GeneratorsOfGroup(g), List(GeneratorsOfGroup(g), - j->PreImagesRepresentative(emb,Image(emb,j)^i))); + j->PreImagesRepresentativeNC(emb,Image(emb,j)^i))); Add(a,au); od; au:=Group(a); @@ -2449,7 +2459,7 @@ InstallGlobalFunction(AutomorphismGroupFittingFree,function(g) bi:=[]; for i in newbas do s:=List(stbs[i], - x->Image(emb,Image(autom,PreImagesRepresentative(emb,x)))); + x->Image(emb,Image(autom,PreImagesRepresentativeNC(emb,x)))); s:=First(orb[orpo[i]],x->ForAll(s,j->x^j=x)); Add(bi,s); od; diff --git a/lib/norad.gi b/lib/norad.gi index 7457f035e8..6323d1070d 100644 --- a/lib/norad.gi +++ b/lib/norad.gi @@ -173,7 +173,7 @@ local d,orb,len,S,depths,rel,stb,img,pos,i,j,k,ii,po,rep,sg,sf,sfs,fr,first, if r<>fail then Add(good,r);fi; return r<>fail; end); - good:=List(good,x->PreImagesRepresentative(pacthom,x)); + good:=List(good,x->PreImagesRepresentativeNC(pacthom,x)); good:=Filtered(good,x->not IsOne(x[2])); @@ -418,7 +418,7 @@ local sus,ser,len,factorhom,uf,n,d,up,mran,nran,mpcgs,pcgs,pcisom,nf,ng,np,sub, glact:=ActionHomomorphism(glperm,lvecs, GeneratorsOfGroup(glperm), List(GeneratorsOfGroup(glperm), - x->PreImagesRepresentative(glhom,x)), + x->PreImagesRepresentativeNC(glhom,x)), OnLines,"surjective"); stb:=Image(glact); for clu in localclust do @@ -478,7 +478,7 @@ local sus,ser,len,factorhom,uf,n,d,up,mran,nran,mpcgs,pcgs,pcisom,nf,ng,np,sub, Info(InfoFitFree,1,"Radsize= ",Size(ufr)," index ",Index(uf,ufr)); uff:=SmallGeneratingSet(uf); - ufg:=List(uff,x->PreImagesRepresentative(sus.rest,x)); + ufg:=List(uff,x->PreImagesRepresentativeNC(sus.rest,x)); n:=Normalizer(Image(factorhom),uf); @@ -503,7 +503,7 @@ local sus,ser,len,factorhom,uf,n,d,up,mran,nran,mpcgs,pcgs,pcisom,nf,ng,np,sub, nf:=SmallGeneratingSet(n); fi; - ng:=List(nf,x->PreImagesRepresentative(factorhom,x)); + ng:=List(nf,x->PreImagesRepresentativeNC(factorhom,x)); np:=pcgs; up:=sus.pcgs; diff --git a/lib/onecohom.gi b/lib/onecohom.gi index c2b6d29723..e1432730e3 100644 --- a/lib/onecohom.gi +++ b/lib/onecohom.gi @@ -128,7 +128,7 @@ local hom,fg,fpi,fpg,nt,fam; fpg:=FreeGeneratorsOfFpGroup(Range(hom)); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(hom))]; ocr.generators:=List(GeneratorsOfGroup(Range(hom)), - i->PreImagesRepresentative(hom,i)); + i->PreImagesRepresentativeNC(hom,i)); else if (Index(ocr.group,nt)>Size(nt)^3 @@ -159,9 +159,9 @@ local hom,fg,fpi,fpg,nt,fam; fpg:=FreeGeneratorsOfFpGroup(Range(fpi)); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fpi)), List(GeneratorsOfGroup(Range(fpi)), - i->PreImagesRepresentative(fpi,i))]; + i->PreImagesRepresentativeNC(fpi,i))]; if not IsBound(ocr.generators) then - ocr.generators:=List(ocr.factorpres[3],i->PreImagesRepresentative(hom,i)); + ocr.generators:=List(ocr.factorpres[3],i->PreImagesRepresentativeNC(hom,i)); fi; @@ -171,7 +171,7 @@ local hom,fg,fpi,fpg,nt,fam; # else # old code # fpi:=IsomorphismFpGroup(ocr.group:noshort:=true); # ocr.generators:=List(MappingGeneratorsImages(fpi)[2], -# i->PreImagesRepresentative(fpi,i)); +# i->PreImagesRepresentativeNC(fpi,i)); # fi; fpg:=FreeGeneratorsOfFpGroup(Range(fpi)); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fpi))]; @@ -191,7 +191,7 @@ local hom,fg,fpi,fpg,nt,fam; fpi:=IsomorphismFpGroupByChiefSeriesFactor(ocr.group,"f",nt); fam:=FamilyObj(One(Range(fpi))); fpg:=FreeGeneratorsOfFpGroup(Range(fpi)); - ocr.generators:=List(fpg,i->PreImagesRepresentative(fpi, + ocr.generators:=List(fpg,i->PreImagesRepresentativeNC(fpi, ElementOfFpGroup(fam,i))); ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fpi)),ocr.generators]; fi; diff --git a/lib/oper1.g b/lib/oper1.g index 2c25bf1cff..23550e1d7c 100644 --- a/lib/oper1.g +++ b/lib/oper1.g @@ -929,14 +929,15 @@ end); ## SylowSubgroup( s4, 6 ); ## Error, SylowSubgroup:

must be a prime +## Stack trace: ## *[1] <> ## @ GAPROOT/lib/oper1.g:964 ## [2] <> ## @ GAPROOT/lib/oper1.g:1007 ## ( ) ## called from read-eval loop at *stdin*:3 -## you can 'quit;' to quit to outer loop, or -## you can 'return;' to continue +## you can enter 'quit;' to quit to outer loop, or +## you can enter 'return;' to continue ## brk> quit; ## ]]> ##

diff --git a/lib/oprt.gd b/lib/oprt.gd index 20bae46045..e75a76cc81 100644 --- a/lib/oprt.gd +++ b/lib/oprt.gd @@ -1550,8 +1550,22 @@ OrbitsishOperation( "OrbitLengthsDomain", OrbitsishReq, false, NewAttribute ); ## ## computes the orbit and the stabilizer of pnt simultaneously in a ## single orbit-stabilizer algorithm. +## Returns an immutable record with components orbit (the orbit as +## a list) and stabilizer (the point stabilizer, a subgroup of +## G). ##

## The stabilizer will have G as its parent. +## g:=Group((1,3,2),(2,4,3));; +## gap> orbstab:=OrbitStabilizer(g,[1,2],OnSets); +## rec( +## orbit := [ [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 2, 3 ], [ 3, 4 ], +## [ 2, 4 ] ], stabilizer := Group([ (1,2)(3,4) ]) ) +## gap> orbstab.orbit; +## [ [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 2, 3 ], [ 3, 4 ], [ 2, 4 ] ] +## gap> orbstab.stabilizer; +## Group([ (1,2)(3,4) ]) +## ]]> ## ## ## <#/GAPDoc> diff --git a/lib/oprt.gi b/lib/oprt.gi index a7b758b73f..ad2e47f14a 100644 --- a/lib/oprt.gi +++ b/lib/oprt.gi @@ -1788,8 +1788,7 @@ local list, ps, p, i, gen, img, pos, imgs, hom,orb,ran,xset; imgs := List( list, PermList ); xset := ExternalSet( G, D{orb}, gens, acts, act); SetBaseOfGroup( xset, start ); - p:=RUN_IN_GGMBI; # no niceomorphism translation here - RUN_IN_GGMBI:=true; + PushOptions( rec( Run_In_GGMBI:= true ) ); # no niceomorphism translation here hom := ActionHomomorphism(xset,"surjective" ); ran:= Group( imgs, () ); # `imgs' has been created with `PermList' SetRange(hom,ran); @@ -1801,7 +1800,7 @@ local list, ps, p, i, gen, img, pos, imgs, hom,orb,ran,xset; # this to get images quickly, using a stabilizer chain in the permutation # group SetFilterObj( hom, IsActionHomomorphismByBase ); - RUN_IN_GGMBI:=p; + PopOptions(); return hom; end ); @@ -1919,8 +1918,7 @@ local dict,p,i,img,imgs,hom,permimg,orb,imgn,ran,D,xset; fi; fi; - p:=RUN_IN_GGMBI; # no niceomorphism translation here - RUN_IN_GGMBI:=true; + PushOptions( rec( Run_In_GGMBI:= true ) ); # no niceomorphism translation here hom := ActionHomomorphism( xset,"surjective" ); SetRange(hom,ran); SetImagesSource(hom,ran); @@ -1931,7 +1929,7 @@ local dict,p,i,img,imgs,hom,permimg,orb,imgn,ran,D,xset; if HasBaseOfGroup(xset) then SetFilterObj( hom, IsActionHomomorphismByBase ); fi; - RUN_IN_GGMBI:=p; + PopOptions(); return hom; end); @@ -2920,7 +2918,7 @@ local G, D, d, e, gens, acts, act, xset, hom, p, rep; rep := RepresentativeActionOp( ImagesSource( hom ), d, e, OnPoints ); if rep <> fail then - rep := PreImagesRepresentative( hom, rep ); + rep := PreImagesRepresentativeNC( hom, rep ); fi; return rep; elif IsBound( D ) then @@ -3374,9 +3372,10 @@ end ); ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . . . . . build matrix #M PreImagesRepresentative( , ) . . . . . . . . . . build matrix ## -InstallMethod( PreImagesRepresentative,"IsLinearActionHomomorphism", +InstallMethod( PreImagesRepresentativeNC,"IsLinearActionHomomorphism", FamRangeEqFamElm, [ IsLinearActionHomomorphism, IsPerm ], 0, function( hom, elm ) local V, G, Grep, filt, R, xset,lab,f; @@ -3388,7 +3387,7 @@ function( hom, elm ) TryNextMethod(); fi; - # PreImagesRepresentative does not test membership + # PreImagesRepresentativeNC does not test membership #if not elm in Image( hom ) then return fail; fi; xset:=UnderlyingExternalSet(hom); V := HomeEnumerator(xset); @@ -3418,8 +3417,18 @@ function( hom, elm ) return hom!.linActInverse*elm; end ); +InstallMethod( PreImagesRepresentative,"IsLinearActionHomomorphism", + FamRangeEqFamElm, [ IsLinearActionHomomorphism, IsPerm ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end ); + ############################################################################# ## +#M PreImagesRepresentativeNC( , ) . . . . . . . . . build matrix #M PreImagesRepresentative( , ) . . . . . . . . . . build matrix ## ## The idea is as follows. @@ -3441,7 +3450,7 @@ end ); ## matrix group contains all scalar matrices, or we know that the preimage ## has determinant $1$ and taking the root in question is unique. ## -InstallMethod( PreImagesRepresentative,"IsProjectiveActionHomomorphism", +InstallMethod( PreImagesRepresentativeNC,"IsProjectiveActionHomomorphism", FamRangeEqFamElm, [ IsProjectiveActionHomomorphism, IsPerm ], 0, function( hom, elm ) local V, G, Grep, filt, R, mat, xset,lab,dim,sol,i; @@ -3457,7 +3466,7 @@ function( hom, elm ) TryNextMethod(); fi; - # PreImagesRepresentative does not test membership + # PreImagesRepresentativeNC does not test membership #if not elm in Image( hom ) then return fail; fi; xset:=UnderlyingExternalSet(hom); V := HomeEnumerator(xset); @@ -3493,6 +3502,15 @@ function( hom, elm ) return MakeImmutable( mat ); end); +InstallMethod( PreImagesRepresentative,"IsProjectiveActionHomomorphism", + FamRangeEqFamElm, [ IsProjectiveActionHomomorphism, IsPerm ], 0, +function( hom, elm ) + if not ( elm in Range( hom ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( hom, elm ); +end); + ############################################################################# ## #A LinearActionBasis() diff --git a/lib/oprtglat.gi b/lib/oprtglat.gi index b80acc2755..43b4531805 100644 --- a/lib/oprtglat.gi +++ b/lib/oprtglat.gi @@ -224,7 +224,7 @@ local acts,gps,clusters,conj,ncl,nacts,i,j,new,q,hom,lhom,c,n,r,len, Info(InfoLattice,5,"reduced (factor) by ",Size(q)/Size(n)); Add(nacts,PreImage(lhom,n)); for k in new.clusters[j] do - r:=PreImagesRepresentative(lhom,new.conjugators[k]); + r:=PreImagesRepresentativeNC(lhom,new.conjugators[k]); conj[c[k]]:=conj[c[k]]*r; gps[c[k]]:=gps[c[k]]^r; od; diff --git a/lib/oprtperm.gi b/lib/oprtperm.gi index 0678e7eafb..a1a1616b7c 100644 --- a/lib/oprtperm.gi +++ b/lib/oprtperm.gi @@ -964,7 +964,7 @@ InstallMethod( Earns, "G, ints, gens, perms, act", true, fi; gens := [ ]; for gen in GeneratorsOfGroup( Centre( P ) ) do - pre := PreImagesRepresentative( f, gen ); + pre := PreImagesRepresentativeNC( f, gen ); ord := Order( pre ); pa := 1; while ord mod p = 0 do ord := ord / p; diff --git a/lib/package.gi b/lib/package.gi index 1930c9d6fd..b23272e685 100644 --- a/lib/package.gi +++ b/lib/package.gi @@ -1396,15 +1396,8 @@ InstallGlobalFunction( RereadPackage, function( arg ) ## #F LoadPackageDocumentation( ) ## -## In versions before 4.5, a second argument was required. -## For the sake of backwards compatibility, we do not forbid a second -## argument, but we ignore it. -## (In later versions, we may forbid the second argument.) -## -InstallGlobalFunction( LoadPackageDocumentation, function( arg ) - local info, short, pkgdoc, long, sixfile; - - info:= arg[1]; +InstallGlobalFunction( LoadPackageDocumentation, function( info ) + local short, pkgdoc, long, sixfile; # Load all books for the package. for pkgdoc in info.PackageDoc do @@ -3348,12 +3341,13 @@ InstallGlobalFunction( PackageVariablesInfo, function( pkgname, version ) fi; num:= NumberArgumentsFunction( func ); nam:= NamesLocalVariablesFunction( func ); - if num = -1 then - str:= "arg"; - elif nam = fail then + if nam = fail then str:= "..."; else - str:= JoinStringsWithSeparator( nam{ [ 1 .. num ] }, ", " ); + str:= JoinStringsWithSeparator( nam{ [ 1 .. AbsInt(num) ] }, ", " ); + if num < 0 then + Append( str, "..." ); + fi; fi; return Concatenation( "( ", str, " )" ); end; diff --git a/lib/pcgs.gd b/lib/pcgs.gd index cf2c0a8338..e1cf7172d8 100644 --- a/lib/pcgs.gd +++ b/lib/pcgs.gd @@ -782,7 +782,7 @@ DeclareAttribute( "RefinedPcGroup", IsPcGroup ); ## ## ## isomorphic -## returns an isomorphism from G onto an isomorphic pc group +## returns an isomorphism from a pc group G onto an isomorphic pc group ## whose family pcgs is a prime order pcgs. ## ## diff --git a/lib/pcgsnice.gi b/lib/pcgsnice.gi index 0496a0c212..caa90d90ec 100644 --- a/lib/pcgsnice.gi +++ b/lib/pcgsnice.gi @@ -23,7 +23,7 @@ AttributeMethodByNiceMonomorphism( Pcgs, if npcgs = fail then return fail; fi; - pcgs := List( npcgs, gen -> PreImagesRepresentative( nice, gen ) ); + pcgs := List( npcgs, gen -> PreImagesRepresentativeNC( nice, gen ) ); pcgs := PcgsByPcSequenceNC( ElementsFamily( FamilyObj( G ) ), pcgs ); if HasIsPrimeOrdersPcgs( npcgs ) and IsPrimeOrdersPcgs( npcgs ) then SetIsPrimeOrdersPcgs( pcgs, true ); diff --git a/lib/pcgsspec.gi b/lib/pcgsspec.gi index e8ff00d776..01cc3fdc62 100644 --- a/lib/pcgsspec.gi +++ b/lib/pcgsspec.gi @@ -752,6 +752,9 @@ InstallMethod( IsomorphismSpecialPcGroup, "generic method for groups", function(G) local iso; iso:=IsomorphismPcGroup(G); + if iso = fail then + return fail; + fi; return iso*IsomorphismSpecialPcGroup(Range(iso)); end); diff --git a/lib/permdeco.gi b/lib/permdeco.gi index f57059f634..e605798c0f 100644 --- a/lib/permdeco.gi +++ b/lib/permdeco.gi @@ -314,7 +314,7 @@ local tryrep,sel,selin,a,s,dom,iso,stabs,outs,map,i,j,p,found,seln, for i in GeneratorsOfGroup(G) do a:=One(d); for j in [1..Length(stabs)] do - a:=a*Image(Embedding(d,j),PreImagesRepresentative(outs[j],i)); + a:=a*Image(Embedding(d,j),PreImagesRepresentativeNC(outs[j],i)); od; Add(p,a); od; @@ -360,7 +360,7 @@ local G,H,tg,th,hom, tga, Gemb, C, outs, auts, ar, Hemb; i->GroupHomomorphismByImagesNC(tg,tg, GeneratorsOfGroup(tg), List(GeneratorsOfGroup(tg), - j->Image(hom,PreImagesRepresentative(hom,j)^i)))); + j->Image(hom,PreImagesRepresentativeNC(hom,j)^i)))); Gemb:=fail; if ForAll(tga,IsConjugatorAutomorphism) then @@ -442,7 +442,7 @@ local cs,i,k,u,o,norm,T,Thom,autos,ng,a,Qhom,Q,Ehom,genimages, autos:=List(ng,i->GroupHomomorphismByImagesNC(T,T, GeneratorsOfGroup(T), List(GeneratorsOfGroup(T), - j->Image(Thom,PreImagesRepresentative(Thom,j)^i)))); + j->Image(Thom,PreImagesRepresentativeNC(Thom,j)^i)))); a:=AutomorphismRepresentingGroup(T,autos); Thom:=GroupHomomorphismByImagesNC(norm,a[1],ng,a[3]); a:=a[1]; @@ -455,7 +455,7 @@ local cs,i,k,u,o,norm,T,Thom,autos,ng,a,Qhom,Q,Ehom,genimages, # define isomorphisms between the components reps:=List([1..n],i-> - PreImagesRepresentative(Qhom,RepresentativeAction(Q,1,i))); + PreImagesRepresentativeNC(Qhom,RepresentativeAction(Q,1,i))); genimages:=[]; for i in GeneratorsOfGroup(G) do @@ -539,7 +539,7 @@ local limit, r, pcgs, ser, ind, m, p, l, l2, good, i, j,nser,hom; ser:=InvariantElementaryAbelianSeries(p, List( GeneratorsOfGroup( G ), i -> GroupHomomorphismByImagesNC(p,p,GeneratorsOfGroup(p), List(GeneratorsOfGroup(p), - j->Image(m,PreImagesRepresentative(m,j)^i)))), + j->Image(m,PreImagesRepresentativeNC(m,j)^i)))), TrivialSubgroup(p),true); ser:=List(ser,i->PreImage(m,i)); else diff --git a/lib/randiso.gd b/lib/randiso.gd index 2a33d8b415..5f66f30e93 100644 --- a/lib/randiso.gd +++ b/lib/randiso.gd @@ -21,13 +21,63 @@ DeclareAttribute( "OmegaAndLowerPCentralSeries", IsGroup ); ## ## ## -## returns the code corresponding to pcgs. +## returns the non-negative integer code corresponding to the finite pcgs +## pcgs, which must be in . +## The code stores the relative orders of pcgs and +## the right hand sides of the nontrivial power and commutator relations +## of the pc presentation defined by pcgs. This integer encoding of +## pc groups underlies the group construction method described in +## . +##

+## More precisely, let +## g_1,\ldots,g_l be the entries of pcgs, and let +## r_1,\ldots,r_l be their relative orders. If l=0, +## the code is 0. Otherwise put +## m = \max_i r_i - 1. If the relative orders are not all equal, +## the first l base m digits are +## r_1-2,\ldots,r_l-2, so the relative order part is +## \sum_{i=1}^l (r_i-2)m^{l-i}. If the relative orders are all +## equal, this part is omitted; on decoding the relative orders are then +## read from the factorisation of the supplied group order. +##

+## After the relative order part comes a bit mask of length +## l(l+1)/2-1. The bits, from least significant to most +## significant, correspond first to the power relations +## g_1^{r_1},\ldots,g_{l-1}^{r_{l-1}}, and then to the +## commutators [g_j,g_i] for +## 1 \leq i < j \leq l, ordered by increasing i and, for +## fixed i, increasing j. A bit is 1 exactly when +## the corresponding right hand side is nontrivial. The final power +## relation g_l^{r_l}=1 is not stored separately. +##

+## The nontrivial right hand sides, in the same order as their set bits, +## are stored as base |G| digits, where G is the group +## generated by pcgs. If +## x = g_1^{e_1} \cdots g_l^{e_l}, with +## 0 \leq e_i < r_i, then the digit for x is +## \sum_{i=1}^l e_i\prod_{k=i+1}^l r_k. Equivalently, this is +## the zero-based position of x in the canonical list +## g_1^{e_1}\cdots g_l^{e_l}, ordered according to the +## lexicographic order of the tuples e_1,\dots,e_l. +##

+## Thus if b is m^l when the relative order part is present +## and 1 otherwise, if u is the bit mask, and if +## a_1,\ldots,a_t are the digits for the nontrivial right hand +## sides, then the complete code is +## A + b(u + 2^{l(l+1)/2-1}(a_1 + |G|a_2 + \cdots + +## |G|^{t-1}a_t)), where A is the relative order part, or +## 0 if that part is omitted. ## G := CyclicGroup(512);; +## gap> G := CyclicGroup(8);; ## gap> p := Pcgs( G );; ## gap> CodePcgs( p ); -## 162895587718739690298008513020159 +## 323 ## ]]> +## In this example the relative orders are [2,2,2], so there is +## no relative order part. The nontrivial power tails are g_2 +## and g_3, with digits 2 and 1 in the canonical +## list. Hence the code is +## 1 + 2 + 2^5(2 + 8\cdot 1) = 323. ## ## ## <#/GAPDoc> @@ -43,11 +93,15 @@ DeclareGlobalFunction( "CodePcgs" ); ## ## ## -## returns the code for a pcgs of G. +## returns the code for the pcgs returned by Pcgs for G. +## The encoding is the one described for . ## G := DihedralGroup(512);; -## gap> CodePcGroup( G ); -## 2940208627577393070560341803949986912431725641726 +## gap> G := CyclicGroup(8);; +## gap> code := CodePcGroup( G ); +## 323 +## gap> H := PcGroupCode( code, Size( G ) );; +## gap> IsCyclic( H ) and Size( H ) = Size( G ); +## true ## ]]> ## ## @@ -69,6 +123,15 @@ DeclareGlobalFunction( "CodePcGroup" ); ## otherwise anything may happen. ## Valid codes are usually obtained by one of the functions ## or . +## The inverse construction uses the integer format described for +## . The length of the pcgs, and in the case where +## all relative orders are equal also the relative orders themselves, are +## recovered from the prime factorisation of size. +##

+## The same integer format is also used by Magma's +## SmallGroupEncoding and SmallGroupDecoding, and by +## OSCAR's encode for pc groups and +## pc_group( order, code ). ## G := SmallGroup( 24, 12 );; ## gap> p := Pcgs( G );; diff --git a/lib/randiso.gi b/lib/randiso.gi index 5331eb51c3..15b1d8c520 100644 --- a/lib/randiso.gi +++ b/lib/randiso.gi @@ -240,6 +240,11 @@ end ); InstallGlobalFunction( CodePcgs, function( pcgs ) local code, indices, l, mi, i, base, nt, r, j, size; + # Check the argument. + if not ( IsPcgs( pcgs ) and IsPrimeOrdersPcgs( pcgs ) ) then + Error( " must be a pcgs in 'IsPrimeOrdersPcgs'" ); + fi; + # basic structures l := Length( pcgs ); if l = 0 then diff --git a/lib/relation.gi b/lib/relation.gi index e5208df4b7..db6005a732 100644 --- a/lib/relation.gi +++ b/lib/relation.gi @@ -71,7 +71,7 @@ ## ## I. Operations and methods for binary relations on points ## 1. ImagesElm (compatibility with GeneralMapping) -## 2. PreImagesElm (compatibility with GeneralMapping) +## 2. PreImagesElmNC (compatibility with GeneralMapping) ## 3. \=, \in, \< ## 4. \* for relations, transformations, and permutation ## 5. Set operations \+, \- (union, difference) @@ -92,7 +92,7 @@ ## 4. MeetEquivalenceRelations ## 5. \= ## 6. ImagesElm (compatibility with GeneralMapping) -## 7. PreImagesElm (compatibility with GeneralMapping) +## 7. PreImagesElmNC (compatibility with GeneralMapping) ## 8. PrintObj ## ## L. Constructors of equivalence classes @@ -104,7 +104,7 @@ ## 2. PrintObj, Enumerator ## 3. \< ## 4. ImagesRepresentative -## 6. PreImagesRepresentative +## 6. PreImagesRepresentativeNC ## ############################################################################ ############################################################################ @@ -230,7 +230,7 @@ InstallMethod(IsReflexiveBinaryRelation, ## #P IsSymmetricBinaryRelation() ## -## Depends on Images and Preimages returning SSorted lists. +## Depends on Images and PreimagesNC returning SSorted lists. ## InstallMethod(IsSymmetricBinaryRelation, @@ -250,7 +250,7 @@ InstallMethod(IsSymmetricBinaryRelation, List(Enumerator(UnderlyingRelation(m)),x->[x[1],x[2]]))); for e in el do - if not PreImages(m,e)=Images(m,e) then + if not PreImagesNC(m,e)=Images(m,e) then return false; fi; od; @@ -312,7 +312,7 @@ InstallMethod(IsAntisymmetricBinaryRelation, List(Enumerator(UnderlyingRelation(rel)),x->[x[1],x[2]]))); for e in el do - i := IntersectionSet(PreImages(rel,e),Images(rel,e)); + i := IntersectionSet(PreImagesNC(rel,e),Images(rel,e)); if not IsEmpty(i) and not i=[e] then return false; fi; @@ -376,7 +376,7 @@ function(rel) for a in Source(rel) do for b in Source(rel) do # intersecting downsets - intersection := Intersection(PreImages(rel,b),PreImages(rel,a)); + intersection := Intersection(PreImagesNC(rel,b),PreImagesNC(rel,a)); # new relation on the intersection induced by the original relation nrel := PartialOrderByOrderingFunction( Domain(intersection), @@ -607,11 +607,11 @@ InstallMethod(HasseDiagramBinaryRelation, HDBRMinElts := function(list, rel) ## x minimal if - ## {y in list | y<>x and y in PreImagesElm( rel,x)} is empty + ## {y in list | y<>x and y in PreImagesElmNC( rel,x)} is empty ## return Filtered(list, x->IsEmpty(Filtered(list, y-> (y <> x) and - (y in PreImagesElm(rel,x))))); + (y in PreImagesElmNC(rel,x))))); end; ## return the elements which cover x in rel @@ -983,11 +983,12 @@ InstallMethod(ImagesElm, ############################################################################# ## +#M PreImagesElmNC( , ) #M PreImagesElm( , ) ## ## For binary relations over [1..n] represented as a list of images ## -InstallMethod(PreImagesElm, +InstallMethod(PreImagesElmNC, "for binary rels over [1..n] with images list", true, [IsBinaryRelation and IsBinaryRelationOnPointsRep, IsPosInt], 0, function( rel, n ) @@ -995,6 +996,16 @@ InstallMethod(PreImagesElm, i->n in Successors(rel)[i]); end); +InstallMethod(PreImagesElm, + "for binary rels over [1..n] with images list", + true, [IsBinaryRelation and IsBinaryRelationOnPointsRep, IsPosInt], 0, + function( rel, n ) + if not ( n in Range(rel) ) then + return fail; + fi; + return PreImagesElm( rel, n ); + end ); + ############################################################################# ## #A Successors( ) @@ -1781,11 +1792,21 @@ InstallMethod( ImagesRepresentative, "equivalence relations", ############################################################################# ## -#M PreImagesRepresentative( , ) . . . for equivalence relations +#M PreImagesRepresentativeNC( , ) . . . for equivalence relations +#M PreImagesRepresentative( , ) . . . . for equivalence relations ## +InstallMethod( PreImagesRepresentativeNC, "equivalence relations", + FamRangeEqFamElm, [IsEquivalenceRelation, IsObject], 0, + function( map, elm ) + return elm; + end); + InstallMethod( PreImagesRepresentative, "equivalence relations", FamRangeEqFamElm, [IsEquivalenceRelation, IsObject], 0, function( map, elm ) + if not ( elm in Range(map) ) then + return fail; + fi; return elm; end); @@ -1813,9 +1834,10 @@ InstallMethod( ImagesElm, ############################################################################# ## -#M PreImagesElm( , ) for equivalence relations with partition +#M PreImagesElmNC( , ) . for equivalence relations with partition +#M PreImagesElm( , ) . . for equivalence relations with partition ## -InstallMethod( PreImagesElm, +InstallMethod( PreImagesElmNC, "equivalence relations with partition and element", FamRangeEqFamElm, [IsEquivalenceRelation and HasEquivalenceRelationPartition, @@ -1826,6 +1848,18 @@ InstallMethod( PreImagesElm, return ImagesElm(rel, elm); end); +InstallMethod( PreImagesElm, + "equivalence relations with partition and element", + FamRangeEqFamElm, + [IsEquivalenceRelation and HasEquivalenceRelationPartition, + IsObject],0, + function( rel, elm ) + if not ( elm in Range( rel ) ) then ##?? is there a Range(rel)? + return fail; + fi; + return PreImagesElmNC( rel, elm ); + end); + ############################################################################# ## #M PrintObj( ) for equivalence relation diff --git a/lib/ringhom.gi b/lib/ringhom.gi index 21791f48a8..887a991704 100644 --- a/lib/ringhom.gi +++ b/lib/ringhom.gi @@ -52,12 +52,7 @@ function( S, R, gens, imgs ) fi; # Make the general mapping. - map:= Objectify( TypeOfDefaultGeneralMapping( S, R, - IsSPGeneralMapping - and IsRingGeneralMapping - and IsSCRingGeneralMappingByImagesDefaultRep ), - rec( - ) ); + map:= Objectify( TypeOfDefaultGeneralMapping( S, R, filter ), rec( ) ); SetMappingGeneratorsImages(map,[Immutable(gens),Immutable(imgs)]); # return the general mapping @@ -444,9 +439,10 @@ end ); ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . . for ring g.m.b.i. +#M PreImagesRepresentativeNC( , ) . . . . . . for ring g.m.b.i. +#M PreImagesRepresentative( , ) . . . . . . . for ring g.m.b.i. ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for ring g.m.b.i., and element", FamRangeEqFamElm, [ IsRingGeneralMapping and IsRingGeneralMappingByImagesDefaultRep, @@ -455,6 +451,18 @@ function( map, elm ) return ImagesRepresentative(InverseGeneralMapping(map),elm); end ); +InstallMethod( PreImagesRepresentative, + "for ring g.m.b.i., and element", + FamRangeEqFamElm, + [ IsRingGeneralMapping and IsRingGeneralMappingByImagesDefaultRep, + IsObject ], +function( map, elm ) + if not ( elm in Range( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); +end ); + BindGlobal("IsomorphismSCRing",function(R) local e, z, one, o, sel, g, go, elms, dec, p, cands, m, a, b, nr, hom, i, j; if Size(R)>100000 then diff --git a/lib/ringsc.gd b/lib/ringsc.gd index bd2116bcd7..9871317d71 100644 --- a/lib/ringsc.gd +++ b/lib/ringsc.gd @@ -47,6 +47,14 @@ DeclareSynonym("IsSubringSCRing",IsRing and IsSCRingObjCollection); ## it can be either a string name ## (then name1, name2 etc. are chosen) ## or a list of strings which are then chosen. +## T:=EmptySCTable( 1, 0 );; +## gap> SetEntrySCTable( T, 1, 1, [ 1, 1 ] ); +## gap> R:=RingByStructureConstants([9], T); # Z/9Z +## +## gap> Elements(R); +## [ 0*r.1, r.1, 2*r.1, 3*r.1, 4*r.1, 5*r.1, 6*r.1, 7*r.1, -r.1 ] +## ]]> ## ## ## <#/GAPDoc> diff --git a/lib/rwspcsng.gi b/lib/rwspcsng.gi index 19cd81bcec..81bfcdb7a3 100644 --- a/lib/rwspcsng.gi +++ b/lib/rwspcsng.gi @@ -71,8 +71,6 @@ DeclareFilter( "IsDefaultRhsTypeSingleCollector" ); ## describing the polycyclic presentation, an exponent vector and a word ## in the corresponding free group. It collects into . ## -SingleCollector_CollectWordRunning := false; - BindGlobal( "SingleCollector_CollectWord", function( sc, v, w ) local cnj, # [g][h] contains g^h for g > h @@ -92,13 +90,7 @@ BindGlobal( "SingleCollector_CollectWord", function( sc, v, w ) tmp, # temporary avc; # g_i .. g_n commutes with g_avc[i]+1 .. g_n - # the collector is not reentrant - if SingleCollector_CollectWordRunning then - SingleCollector_CollectWordRunning := false; - Error( "collector is not reentrant" ); - fi; #Print( "#I using the GAP level single collector\n" ); - SingleCollector_CollectWordRunning := true; # contains the stack of words to insert nw := []; nw[1] := w; @@ -108,7 +100,6 @@ BindGlobal( "SingleCollector_CollectWord", function( sc, v, w ) # if we got the identity return if lw[1] = 0 then - SingleCollector_CollectWordRunning := false; return true; fi; @@ -238,7 +229,6 @@ BindGlobal( "SingleCollector_CollectWord", function( sc, v, w ) fi; fi; od; - SingleCollector_CollectWordRunning := false; return true; end ); diff --git a/lib/schur.gi b/lib/schur.gi index f53b66dbdd..b34a4608c9 100644 --- a/lib/schur.gi +++ b/lib/schur.gi @@ -130,7 +130,7 @@ InstallMethod(EpimorphismSchurCover,"generic, via fp group",true,[IsGroup],1, j->One(F))))); hom:=GroupHomomorphismByImagesNC(D,G,GeneratorsOfGroup(D), - List(Dgens,i->PreImagesRepresentative(iso,i))); + List(Dgens,i->PreImagesRepresentativeNC(iso,i))); Dgens:=TzImagesOldGens(p); Dgens:=List(Dgens{[Length(Fgens)+1..Length(Dgens)]}, i->MappedWord(i,p!.generators,GeneratorsOfGroup(D))); @@ -201,7 +201,7 @@ local s,pcgs,n,l,cov,pco,ng,gens,imgs,ran,zer,i,j,e,a, fi; # get a decent pcgs for the cover - pco:=List(pcgs,i->Image(epi,PreImagesRepresentative(de,i))); + pco:=List(pcgs,i->Image(epi,PreImagesRepresentativeNC(de,i))); Append(pco,Pcgs(mul)); pco:=PcgsByPcSequenceNC(FamilyObj(One(cov)),pco); @@ -261,7 +261,7 @@ local s,pcgs,n,l,cov,pco,ng,gens,imgs,ran,zer,i,j,e,a, # factor generators gens:=GeneratorsOfGroup(qs); # their conjugates - imgs:=List(gens,j->PreImagesRepresentative(epi,Image(epi,j)^dc[i])); + imgs:=List(gens,j->PreImagesRepresentativeNC(epi,Image(epi,j)^dc[i])); rels:=ClosureGroup(rels,CommutGenImgs(pco,gens,imgs, Intersection(mul,DerivedSubgroup(qs)))); fi; @@ -306,7 +306,7 @@ BindGlobal("PositiveExponentsPresentationFpHom",function(hom) local G,F,geni,ro,fam,r,i,j,rel,n,e; G:=Image(hom); F:=FreeGeneratorsOfFpGroup(G); - geni:=List(GeneratorsOfGroup(G),i->PreImagesRepresentative(hom,i)); + geni:=List(GeneratorsOfGroup(G),i->PreImagesRepresentativeNC(hom,i)); ro:=List(geni,Order); fam:=FamilyObj(F[1]); r:=[]; @@ -351,7 +351,7 @@ local G,H,D,T,i,j,k,l,a,h,nk,evals,rels,gens,r,np,g,invlist,el,elp,TL,rp,pos; # this will guarantee we always take the same preimages el:=AsSSortedListNonstored(H); - elp:=List(el,i->PreImagesRepresentative(s,i)); + elp:=List(el,i->PreImagesRepresentativeNC(s,i)); #ensure the preimage of identity is one if IsOne(el[1]) then pos:=1; @@ -401,13 +401,13 @@ local G,H,D,T,i,j,k,l,a,h,nk,evals,rels,gens,r,np,g,invlist,el,elp,TL,rp,pos; fi; np:=k*g; nk:=TL[PositionCanonical(T,np)]; - #h:=h*PreImagesRepresentative(s,np/nk); + #h:=h*PreImagesRepresentativeNC(s,np/nk); h:=h*elp[Position(el,np/nk)]; k:=nk; od; - #Print(PreImagesRepresentative(s,Image(s,h))*h,"\n"); - #a:=a/PreImagesRepresentative(s,Image(s,h))*h; + #Print(PreImagesRepresentativeNC(s,Image(s,h))*h,"\n"); + #a:=a/PreImagesRepresentativeNC(s,Image(s,h))*h; a:=a/h*elp[Position(el,Image(s,h))]; od; @@ -485,7 +485,7 @@ local G,B,P,s,D,i,j,v,ri,rank,bas,basr,row,rel,sol,snf,mat; j:=NaturalHomomorphismByNormalSubgroupNC(D,v); i:=GeneratorsOfGroup(Image(j)); i:=GroupHomomorphismByImagesNC(Image(j),P,i, - List(i,k->ImageElm(s,PreImagesRepresentative(j,k)))); + List(i,k->ImageElm(s,PreImagesRepresentativeNC(j,k)))); SetKernelOfMultiplicativeGeneralMapping(i, Image(j,KernelOfMultiplicativeGeneralMapping(s))); return i; @@ -558,7 +558,7 @@ local hom, #isomorphism fp s:=sl[pp]; mg:=IsomorphismPermGroup(KernelOfMultiplicativeGeneralMapping(s)); mg:=List(IndependentGeneratorsOfAbelianGroup(Image(mg)), - i->PreImagesRepresentative(mg,i)); + i->PreImagesRepresentativeNC(mg,i)); sdc:=ListWithIdenticalEntries(Last(ngl),One(Source(s))); sdc{[ngl[pp]+1..ngl[pp+1]]}:=mg; @@ -579,7 +579,7 @@ local hom, #isomorphism fp q:=[]; for i in ce do - Add(q,PreImagesRepresentative(sdc,i[2])); + Add(q,PreImagesRepresentativeNC(sdc,i[2])); od; rel2[pp]:=q; od; diff --git a/lib/schursym.gi b/lib/schursym.gi index 59eb8bb64d..1f770f27dc 100644 --- a/lib/schursym.gi +++ b/lib/schursym.gi @@ -654,9 +654,8 @@ function( sym ) hom := GroupHomomorphismByImages( grp, sym, GeneratorsOfGroup( grp ), img ); Assert( 3, KernelOfMultiplicativeGeneralMapping( hom ) = Center( grp ) ); else - dom := RUN_IN_GGMBI; RUN_IN_GGMBI := true; - hom := GroupHomomorphismByImagesNC( grp, sym, GeneratorsOfGroup( grp ), img ); - RUN_IN_GGMBI := dom; + hom := GroupHomomorphismByImagesNC( grp, sym, GeneratorsOfGroup( grp ), img + : Run_In_GGMBI:= true ); SetKernelOfMultiplicativeGeneralMapping( hom, Center( grp ) ); fi; return hom; @@ -680,9 +679,8 @@ function( alt ) hom := GroupHomomorphismByImages( grp, alt, GeneratorsOfGroup( grp ), img ); Assert( 3, KernelOfMultiplicativeGeneralMapping( hom ) = Center( grp ) ); else - dom := RUN_IN_GGMBI; RUN_IN_GGMBI := true; - hom := GroupHomomorphismByImagesNC( grp, alt, GeneratorsOfGroup( grp ), img ); - RUN_IN_GGMBI := dom; + hom := GroupHomomorphismByImagesNC( grp, alt, GeneratorsOfGroup( grp ), img + : Run_In_GGMBI:= true ); SetKernelOfMultiplicativeGeneralMapping( hom, Center( grp ) ); fi; return hom; diff --git a/lib/semirel.gi b/lib/semirel.gi index dd0fad38fa..f3bb8188cc 100644 --- a/lib/semirel.gi +++ b/lib/semirel.gi @@ -1299,7 +1299,7 @@ end); ######## ######## -InstallMethod(PreImagesRepresentative, "for semigroup homomorphism by images", +InstallMethod(PreImagesRepresentativeNC, "for semigroup homomorphism by images", FamRangeEqFamElm, [IsSemigroupHomomorphism and IsSemigroupHomomorphismByImagesRep, IsMultiplicativeElement], function(hom, x) diff --git a/lib/stbcbckt.gi b/lib/stbcbckt.gi index f0b4eb0046..1d9ccd727f 100644 --- a/lib/stbcbckt.gi +++ b/lib/stbcbckt.gi @@ -2602,7 +2602,7 @@ dom, et, ft, Pr, rbase, BF, Q, data,lc; found:=PartitionBacktrack( G, Pr, true, rbase, data, L, R ); if IsPerm(found) and map<>false then - found:=PreImagesRepresentative(map,found); + found:=PreImagesRepresentativeNC(map,found); fi; return found; end ); diff --git a/lib/streams.gi b/lib/streams.gi index 5f0f44aa73..f105a1c635 100644 --- a/lib/streams.gi +++ b/lib/streams.gi @@ -1367,6 +1367,9 @@ InstallGlobalFunction( InputOutputLocalProcess, Error("Can't handle new rep for directories"); fi; dirname := cdir![1]; + if not IsPlistRep(argts) then + argts := PlainListCopy(argts); + fi; ptynum := CREATE_PTY_IOSTREAM( dirname, exec, argts); if ptynum = fail then return fail; diff --git a/lib/twocohom.gi b/lib/twocohom.gi index 179e1f453a..7af0728b1e 100644 --- a/lib/twocohom.gi +++ b/lib/twocohom.gi @@ -813,7 +813,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, od; gens:=List(GeneratorsOfGroup(FamilyObj(fpg)!.wholeGroup), - x->PreImagesRepresentative(fp,x)); + x->PreImagesRepresentativeNC(fp,x)); hom:=GroupHomomorphismByImagesNC(G,Group(mo.generators), GeneratorsOfGroup(G),mo.generators); @@ -845,7 +845,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, else # Length of r[1] is 1. That is, this generator is not used! m:=First(RelationsOfFpMonoid(mon),x->List(x,LetterRepAssocWord)=r); - m:=List(m,x->PreImagesRepresentative(fm,ElementOfFpMonoid(FamilyObj(One(mon)),x))); + m:=List(m,x->PreImagesRepresentativeNC(fm,ElementOfFpMonoid(FamilyObj(One(mon)),x))); m:=List(m,UnderlyingElement); # free group elements/words if not IsOne(m[1]*Subword(m[2],1,1)) then @@ -866,7 +866,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, model:=ValueOption("model"); if model<>fail then q:=GQuotients(model,G)[1]; - pre:=List(gens,x->PreImagesRepresentative(q,x)); + pre:=List(gens,x->PreImagesRepresentativeNC(q,x)); ker:=KernelOfMultiplicativeGeneralMapping(q); pcgs:=Pcgs(ker); l1:=GModuleByMats(LinearActionLayer(Group(pre),pcgs),mo.field); @@ -880,7 +880,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, m:=GroupGeneralMappingByImagesNC(fpg,model,GeneratorsOfGroup(fpg),pre); mats:=List(GeneratorsOfMonoid(mon), x->ImagesRepresentative(m, - PreImagesRepresentative(fm,x))); #Elements for monoid generators + PreImagesRepresentativeNC(fm,x))); #Elements for monoid generators nonone:=[1..Length(mats)]; pre:=mats; onemat:=One(G); @@ -896,8 +896,8 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, zerovec:=Zero(onemat[1]); mats:=List(GeneratorsOfMonoid(mon), - x->ImagesRepresentative(hom,PreImagesRepresentative(fp, - PreImagesRepresentative(fm,x)))); # matrices for monoid generators + x->ImagesRepresentative(hom,PreImagesRepresentativeNC(fp, + PreImagesRepresentativeNC(fm,x)))); # matrices for monoid generators one:=One(mats[1]); nonone:=Filtered([1..Length(mats)],x->not IsOne(mats[x])); zero:=zerovec; @@ -1046,7 +1046,7 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, one:=One(FreeGroupOfFpGroup(fpg)); k:=List(GeneratorsOfMonoid(mon), - x->UnderlyingElement(PreImagesRepresentative(fm,x))); + x->UnderlyingElement(PreImagesRepresentativeNC(fm,x))); # matrix corresponding to monoid word mapped2:=function(list) local a,i; @@ -1124,8 +1124,8 @@ local field,fp,fpg,gens,hom,mats,fm,mon,tzrules,dim,rules,eqs,i,j,k,l,o,l1, local a; if not IsBound(imagemonwords[nr]) then # apply automorphism - a:=PreImagesRepresentative(fm,GeneratorsOfMonoid(mon)[nr]); - a:=PreImagesRepresentative(fp,a); + a:=PreImagesRepresentativeNC(fm,GeneratorsOfMonoid(mon)[nr]); + a:=PreImagesRepresentativeNC(fp,a); a:=ImagesRepresentative(autom,a); a:=ImagesRepresentative(fp,a); a:=ImagesRepresentative(fm,a); diff --git a/lib/vspchom.gi b/lib/vspchom.gi index 4b6aee7a75..7fe397f6bd 100644 --- a/lib/vspchom.gi +++ b/lib/vspchom.gi @@ -486,8 +486,9 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## #M PreImagesRepresentative( , ) . . . . for left module g.m.b.i. +#M PreImagesRepresentativeNC( , ) . . . for left module g.m.b.i. ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for left module g.m.b.i., and element", FamRangeEqFamElm, [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, @@ -503,6 +504,17 @@ InstallMethod( PreImagesRepresentative, return LinearCombination( map!.preimagesbasisimage, elm ); end ); +InstallMethod( PreImagesRepresentative, + "for left module g.m.b.i., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + if not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); ############################################################################# ## @@ -1221,9 +1233,9 @@ InstallMethod( ImagesRepresentative, ############################################################################# ## -#M PreImagesRepresentative( , ) . . . . . for left module m.b.m. +#M PreImagesRepresentativeNC( , ) . . . . for left module m.b.m. ## -InstallMethod( PreImagesRepresentative, +InstallMethod( PreImagesRepresentativeNC, "for left module m.b.m., and element", FamRangeEqFamElm, [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, @@ -1239,6 +1251,18 @@ InstallMethod( PreImagesRepresentative, return LinearCombination( map!.preimagesbasisimage, elm ); end ); +InstallMethod( PreImagesRepresentative, + "for left module m.b.m., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, + IsObject ], + function( map, elm ) + if not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + ############################################################################# ## diff --git a/lib/vspchom.gi.changed b/lib/vspchom.gi.changed new file mode 100644 index 0000000000..7fe397f6bd --- /dev/null +++ b/lib/vspchom.gi.changed @@ -0,0 +1,2256 @@ +############################################################################# +## +## This file is part of GAP, a system for computational discrete algebra. +## This file's authors include Thomas Breuer. +## +## Copyright of GAP belongs to its developers, whose names are too numerous +## to list here. Please refer to the COPYRIGHT file for details. +## +## SPDX-License-Identifier: GPL-2.0-or-later +## +## This file contains methods for general linear mappings of finite +## dimensional free left modules. +## +## There are two default representations of such general mappings, +## one by generators and images, the other by two bases and a matrix. +## +## Note that a matrix is not the appropriate object to represent a general +## linear mapping if it is not total or not single-valued; +## moreover, if one does not prescribe images of a basis but of an +## arbitrary generating system, one does not want to compute a basis at the +## time the general mapping is formed; +## finally, the matrix is not appropriate to compute preimages, whereas +## the general mapping by images behaves symmetrically in this respect. +## +## (The matrix is best for linear mappings used as arithmetic elements, +## for mapping elements of the source to the range and back; storing +## images and preimages avoids the matrix multiplication.) +## +## 1. methods for linear general mappings given by images +## 2. methods for linear mappings given by matrices +## 3. methods for vector spaces of linear mappings +## 4. methods for algebras of linear mappings +## 5. methods for full hom spaces +## + +#T TODO: +#T +#T specific representation for nat. hom. +#T (choice of coefficients instead of silly matrix) +#T AsLeftModuleGeneralMappingByImages, to allow id + id, c * id, -id, +#T Zero( id ), id + zero, - zero, c * zero, ... +#T \= methods for m.b.m. and g.m.b.i. (if bases coincide, compare data) +#T parent dependencies for nat. hom. + +#T put bases into mappings; +#T check that they are really bases of source/range! + + +############################################################################# +## +## 1. methods for linear general mappings given by images +## + +############################################################################# +## +#R IsLinearGeneralMappingByImagesDefaultRep +## +## is a default representation of $F$-linear general mappings between two +## free left modules $V$ and $W$ where $F$ is equal to the left acting +## domain of $V$ and of $W$. +## +#T (It would be possible to allow situations where $F$ is only contained +#T in the left acting domain of $W$; +#T this would lead to asymmetry w.r.t. taking the inverse general mapping.) +## +## Defining components are +## +## `generators' \: \\ +## list of vectors in $V$, +## +## `genimages' \: \\ +## list of vectors in $W$. +## +## The general mapping is defined as the linear closure of the relation +## that joins the $i$-th entry in `generators' and the $i$-th entry in +## `genimages'. +## +## If one wants to compute images, one needs the components +## `basispreimage' \: \\ +## a basis of the $F$-module generated by `generators', +## +## `imagesbasispreimage' \: \\ +## images of the basis vectors of `basispreimage', +## +## `corelations' \: \\ +## linearly independent generators for the corelation space, +## i.e., of the space of all row vectors such that +## `LinearCombination( , generators )' is zero in $V$. +## (The corresponding linear combinations of `genimages' +## generate the cokernel.) +## +## If these components are not yet bound, they are computed by +## `MakeImagesInfoLinearGeneralMappingByImages' when they are needed. +## If `generators' is a *basis* of a free left module then these +## components can be entered without extra work. +## +## If one wants to compute preimages, one needs the components +## `basisimage' \: \\ +## a basis of the $F$-module generated by `genimages', +## +## `preimagesbasisimage' \: \\ +## preimages of the basis vectors of `basisimage', +## +## `relations' \: \\ +## linearly independent generators for the relation space, +## i.e., of the space of all row vectors such that +## `LinearCombination( , genimages )' is zero in $W$. +## (The corresponding linear combinations of `generators' +## generate the kernel.) +## +## If these components are not yet bound, they are computed by +## `MakePreImagesInfoLinearGeneralMappingByImages' when they are needed. +## If `genimages' is a *basis* of a free left module then these +## components can be entered without extra work. +## +## Computed images and preimages of free left modules under linear mappings +## are always free left modules. +## If one needs more structure (e.g., that of an algebra) for an image or +## preimage then the linear mapping must have a special representation. +## +## Note that the inverse general mapping of a linear mapping defined by +## images is best handled if it uses the default method, +## since such an inverse general mapping delegates the tasks of computing +## (pre)images to the original general mapping. +## So the (pre)images info is computed only once. +#T but what about sums of such mappings? +#T better try to share info also in this case? +#T (share a list that is filled with the info later?) +## +DeclareRepresentation( "IsLinearGeneralMappingByImagesDefaultRep", + IsAttributeStoringRep, + [ "basisimage", "preimagesbasisimage", "corelations", + "basispreimage", "imagesbasispreimage", "relations", + "generators", "genimages" ] ); + +InstallTrueMethod( IsAdditiveElementWithInverse, + IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ); +InstallTrueMethod( IsLeftModuleGeneralMapping, + IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ); + + +############################################################################# +## +#M LeftModuleGeneralMappingByImages( , , , ) +## +InstallMethod( LeftModuleGeneralMappingByImages, + "for two free left modules and two homogeneous lists", + [ IsFreeLeftModule, IsFreeLeftModule, + IsHomogeneousList, IsHomogeneousList ], + function( S, R, gens, imgs ) + + local map; # general mapping from to , result + + # Check the arguments. + if Length( gens ) <> Length( imgs ) then + Error( " and must have the same length" ); + elif not IsSubset( S, gens ) then + Error( " must lie in " ); + elif not IsSubset( R, imgs ) then + Error( " must lie in " ); + elif LeftActingDomain( S ) <> LeftActingDomain( R ) then + Error( " and must have same left acting domain" ); + fi; + + # Make the general mapping. + map:= Objectify( TypeOfDefaultGeneralMapping( S, R, + IsSPGeneralMapping + and IsLeftModuleGeneralMapping + and IsLinearGeneralMappingByImagesDefaultRep ), + rec() ); + + SetMappingGeneratorsImages(map,[gens,imgs]); + # Handle the case that `gens' is a basis. + if IsBasis( gens ) then + map!.basispreimage := gens; + map!.imagesbasispreimage := imgs; + map!.corelations := Immutable( [] ); + fi; + + # Handle the case that `imgs' is a basis. + if IsBasis( imgs ) then + map!.basisimage := imgs; + map!.preimagesbasisimage := gens; + map!.relations := Immutable( [] ); + fi; + + # return the general mapping + return map; + end ); + + +############################################################################# +## +#M LeftModuleHomomorphismByImagesNC( , , , ) +## +InstallMethod( LeftModuleHomomorphismByImagesNC, + "for two left modules and two lists", + [ IsFreeLeftModule, IsFreeLeftModule, IsList, IsList ], + function( S, R, gens, imgs ) + local map; # homomorphism from to , result + map:= LeftModuleGeneralMappingByImages( S, R, gens, imgs ); + SetIsSingleValued( map, true ); + SetIsTotal( map, true ); + return map; + end ); + + +############################################################################# +## +#F LeftModuleHomomorphismByImages( , , , ) +## +InstallGlobalFunction( LeftModuleHomomorphismByImages, + function( S, R, gens, imgs ) + local hom; + hom:= LeftModuleGeneralMappingByImages( S, R, gens, imgs ); + if IsMapping( hom ) then + return LeftModuleHomomorphismByImagesNC( S, R, gens, imgs ); + else + return fail; + fi; +end ); + + +############################################################################# +## +#M AsLeftModuleGeneralMappingByImages( ) . for a lin. gen. mapping +## +InstallMethod( AsLeftModuleGeneralMappingByImages, + "for a linear g.m.b.i.", + [ IsLeftModuleGeneralMapping + and IsLinearGeneralMappingByImagesDefaultRep ], + IdFunc ); + + +############################################################################# +## +#M ImagesSource( ) . . . . . . . . . . . . . . . . for linear g.m.b.i. +## +InstallMethod( ImagesSource, + "for a linear g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + if IsBound( map!.basisimage ) then + return UnderlyingLeftModule( map!.basisimage ); + else + return SubmoduleNC( Range( map ), MappingGeneratorsImages(map)[2] ); +#T is it used that the second argument may be a basis object? + fi; + end ); + + +############################################################################# +## +#M PreImagesRange( ) . . . . . . . . . . . . . . . for linear g.m.b.i. +## +InstallMethod( PreImagesRange, + "for a linear g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + if IsBound( map!.basispreimage ) then + return UnderlyingLeftModule( map!.basispreimage ); + else + return SubmoduleNC( Source( map ), MappingGeneratorsImages(map)[1] ); +#T is it used that the second argument may be a basis object? + fi; + end ); + + +############################################################################# +## +#F MakeImagesInfoLinearGeneralMappingByImages( ) +## +## Provide the information for computing images, that is, set up +## the components `basispreimage', `imagesbasispreimage', `corelations'. +## +BindGlobal( "MakeImagesInfoLinearGeneralMappingByImages", function( map ) + local preimage, + ech, + mapi, + B; + + preimage:= PreImagesRange( map ); + mapi:= MappingGeneratorsImages( map ); + + if Dimension( preimage ) = 0 then + + # Set the entries explicitly. + map!.basispreimage := Basis( preimage ); + map!.corelations := IdentityMat( Length( mapi[2] ), + LeftActingDomain( preimage ) ); + map!.imagesbasispreimage := Immutable( [] ); + + elif IsGaussianRowSpace( Source( map ) ) then +#T operation MakeImagesInfo( map, source ) +#T to leave this to the method selection ? +#T or flag `IsFromGaussianSpace' ? + + # The images of the basis vectors are obtained on + # forming the linear combinations of images of generators + # given by `ech.coeffs'. + + ech:= SemiEchelonMatTransformation( mapi[1] ); + map!.basispreimage := SemiEchelonBasisNC( + preimage, ech.vectors ); + map!.corelations := Immutable( ech.relations ); + map!.imagesbasispreimage := Immutable( ech.coeffs * mapi[2] ); +#T problem if mapi[2] is a basis and if this does not store that it is a small list! + + else + + # Delegate the work to the associated row space. + B:= Basis( preimage ); + ech:= SemiEchelonMatTransformation( List( mapi[1], + x -> Coefficients( B, x ) ) ); + map!.basispreimage := BasisNC( preimage, + List( ech.vectors, + x -> LinearCombination( B, x ) ) ); + map!.corelations := Immutable( ech.relations ); + map!.imagesbasispreimage := Immutable( List( ech.coeffs, + x -> LinearCombination( mapi[2], x ) ) ); + + fi; +end ); + + +############################################################################# +## +#F MakePreImagesInfoLinearGeneralMappingByImages( ) +## +## Provide the information for computing preimages, that is, set up +## the components `basisimage', `preimagesbasisimage', `relations'. +## +BindGlobal( "MakePreImagesInfoLinearGeneralMappingByImages", function( map ) + local image, + ech, + mapi, + B; + + mapi:= MappingGeneratorsImages( map ); + image:= ImagesSource( map ); + + if Dimension( image ) = 0 then + + # Set the entries explicitly. + map!.basisimage := Basis( image ); + map!.relations := IdentityMat( Length( mapi[1] ), + LeftActingDomain( image ) ); + map!.preimagesbasisimage := Immutable( [] ); + + elif IsGaussianRowSpace( Range( map ) ) then + + # The preimages of the basis vectors are obtained on + # forming the linear combinations of preimages of genimages + # given by `ech.coeffs'. + ech:= SemiEchelonMatTransformation( mapi[2] ); + map!.basisimage := SemiEchelonBasisNC( image, ech.vectors ); + map!.relations := Immutable( ech.relations ); + map!.preimagesbasisimage := Immutable( ech.coeffs * mapi[1]); +#T problem if mapi[1] is a basis and if this does not store that it is a small list! + + else + + # Delegate the work to the associated row space. + B:= Basis( image ); + ech:= SemiEchelonMatTransformation( List( mapi[2], + x -> Coefficients( B, x ) ) ); + map!.basisimage := BasisNC( image, + List( ech.vectors, + x -> LinearCombination( B, x ) ) ); + map!.relations := Immutable( ech.relations ); + map!.preimagesbasisimage := Immutable( List( ech.coeffs, + row -> LinearCombination( + row, mapi[1] ) ) ); + + fi; +end ); + + +############################################################################# +## +#M CoKernelOfAdditiveGeneralMapping( ) . . . for left module g.m.b.i. +## +InstallMethod( CoKernelOfAdditiveGeneralMapping, + "for left module g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local genimages; + + # Form the linear combinations of the basis vectors for the + # corelation space with the `genimages' of `map'. + + if not IsBound( map!.corelations ) then + MakeImagesInfoLinearGeneralMappingByImages( map ); + fi; + genimages:= MappingGeneratorsImages(map)[2]; + return SubmoduleNC( Range( map ), + List( map!.corelations, + r -> LinearCombination( genimages, r ) ) ); + end ); + + +############################################################################# +## +#M IsSingleValued( ) . . . . . . . . . . . . for left module g.m.b.i. +## +InstallMethod( IsSingleValued, + "for left module g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local genimages; + + if not IsBound( map!.corelations ) then + MakeImagesInfoLinearGeneralMappingByImages( map ); + fi; + genimages:= MappingGeneratorsImages(map)[2]; + return ForAll( map!.corelations, + r -> IsZero( LinearCombination( genimages, r ) ) ); + end ); + + +############################################################################# +## +#M KernelOfAdditiveGeneralMapping( ) . . . . for left module g.m.b.i. +## +InstallMethod( KernelOfAdditiveGeneralMapping, + "for left module g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local generators; + + # Form the linear combinations of the basis vectors for the + # relation space with the `generators' of `map'. + + if not IsBound( map!.relations ) then + MakePreImagesInfoLinearGeneralMappingByImages( map ); + fi; + generators:= MappingGeneratorsImages(map)[1]; + return SubmoduleNC( Source( map ), + List( map!.relations, + r -> LinearCombination( generators, r ) ) ); + end ); + + +############################################################################# +## +#M IsInjective( ) . . . . . . . . . . . . . for left module g.m.b.i. +## +InstallMethod( IsInjective, + "for left module g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local generators; + + if not IsBound( map!.relations ) then + MakePreImagesInfoLinearGeneralMappingByImages( map ); + fi; + generators:= MappingGeneratorsImages(map)[1]; + return ForAll( map!.relations, + r -> IsZero( LinearCombination( generators, r ) ) ); + end ); + + +############################################################################# +## +#M ImagesRepresentative( , ) . . . . . for left module g.m.b.i. +## +InstallMethod( ImagesRepresentative, + "for left module g.m.b.i., and element", + FamSourceEqFamElm, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + if not IsBound( map!.basispreimage ) then + MakeImagesInfoLinearGeneralMappingByImages( map ); + fi; + elm:= Coefficients( map!.basispreimage, elm ); + if elm = fail then + return fail; + elif IsEmpty( elm ) then + return Zero( Range( map ) ); + fi; + return LinearCombination( map!.imagesbasispreimage, elm ); + end ); + + +############################################################################# +## +#M PreImagesRepresentative( , ) . . . . for left module g.m.b.i. +#M PreImagesRepresentativeNC( , ) . . . for left module g.m.b.i. +## +InstallMethod( PreImagesRepresentativeNC, + "for left module g.m.b.i., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + if not IsBound( map!.basisimage ) then + MakePreImagesInfoLinearGeneralMappingByImages( map ); + fi; + elm:= Coefficients( map!.basisimage, elm ); + if elm = fail then + return fail; + fi; + return LinearCombination( map!.preimagesbasisimage, elm ); + end ); + +InstallMethod( PreImagesRepresentative, + "for left module g.m.b.i., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsObject ], + function( map, elm ) + if not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + +############################################################################# +## +#M ViewObj( ) . . . . . . . . . . . . . . . for left module g.m.b.i. +## +InstallMethod( ViewObj, + "for a left module g.m.b.i", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local mapi; + + mapi:= MappingGeneratorsImages( map ); + View( mapi[1] ); + Print( " -> " ); + View( mapi[2] ); + end ); + + +############################################################################# +## +#M PrintObj( ) . . . . . . . . . . . . . . . for left module g.m.b.i. +## +InstallMethod( PrintObj, + "for a left module g.m.b.i", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local mapi; + + mapi:= MappingGeneratorsImages( map ); + Print( "LeftModuleGeneralMappingByImages( ", + Source( map ), ", ", Range( map ), ", ", + mapi[1], ", ", mapi[2], " )" ); + end ); + +InstallMethod( PrintObj, + "for a left module hom. b.i", + [ IsMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local mapi; + + mapi:= MappingGeneratorsImages( map ); + Print( "LeftModuleHomomorphismByImages( ", + Source( map ), ", ", Range( map ), ", ", + mapi[1], ", ", mapi[2], " )" ); + end ); + + +############################################################################# +## +#M \*( , ) . . . . . . . . . . . . for scalar and linear g.m.b.i. +## +InstallMethod( \*, + "for scalar and linear g.m.b.i.", + [ IsMultiplicativeElement, + IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( scalar, map ) + local mult, # the multiple of `map', result + mapi, # generators and images + F; # left acting domain + + # Check the scalar. + # (Maybe it is in fact another mapping, and we want to compose.) + if not IsInt( scalar ) + and not IsElmsColls( FamilyObj( scalar ), + FamilyObj( LeftActingDomain( Range( map ) ) ) ) then + TryNextMethod(); + fi; + + mapi:=MappingGeneratorsImages(map); + # Construct the linear general mapping (if possible). + mult:= LeftModuleGeneralMappingByImages( + Source( map ), Range( map ), mapi[1], + List( mapi[2], v -> scalar * v ) ); + + # Maintain info on the preimage side of the general mapping. + if IsBound( map!.basispreimage ) then + mult!.basispreimage := map!.basispreimage; + mult!.imagesbasispreimage := Immutable( + List( map!.imagesbasispreimage, v -> scalar * v ) ); + mult!.corelations := map!.corelations; + fi; + + # Being a mapping is preserved by scalar multiplication. + if HasIsSingleValued( map ) then + SetIsSingleValued( mult, IsSingleValued( map ) ); + fi; + if HasIsTotal( map ) then + SetIsTotal( mult, IsTotal( map ) ); + fi; + + # If the scalar is invertible in the left acting domain of the source + # then surjectivity and injectivity are maintained as well as the image. + F:= LeftActingDomain( Source( map ) ); + if scalar in F and IsUnit( F, scalar ) then + + if HasIsInjective( map ) then + SetIsInjective( mult, IsInjective( map ) ); + fi; + if HasIsSurjective( map ) then + SetIsSurjective( mult, IsSurjective( map ) ); + fi; + + if IsBound( map!.basisimage ) then + scalar:= Inverse( scalar ); + mult!.basisimage := map!.basisimage; + mult!.preimagesbasisimage := Immutable( + List( map!.preimagesbasisimage, v -> scalar * v ) ); + mult!.relations := map!.relations; + fi; + + fi; + + return mult; + end ); + + +############################################################################# +## +#M AdditiveInverseOp( ) . . . . . . . . . . . . . for linear g.m.b.i. +## +InstallMethod( AdditiveInverseOp, + "for linear g.m.b.i.", + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map ) + local ainv, # the additive inverse of `map', result + mapi; + + mapi:=MappingGeneratorsImages(map); + # Construct the linear general mapping (if possible). + ainv:= LeftModuleGeneralMappingByImages( + Source( map ), Range( map ), mapi[1], + List( mapi[2], AdditiveInverse ) ); + + # Maintain images and preimages info. + if IsBound( map!.basispreimage ) then + ainv!.basispreimage := map!.basispreimage; + ainv!.imagesbasispreimage := Immutable( + List( map!.imagesbasispreimage, AdditiveInverse ) ); + ainv!.corelations := map!.corelations; + fi; + if IsBound( map!.basisimage ) then + ainv!.basisimage := map!.basisimage; + ainv!.preimagesbasisimage := Immutable( + List( map!.preimagesbasisimage, AdditiveInverse ) ); + ainv!.relations := map!.relations; + fi; + + # Being a mapping is preserved by scalar multiplication. + if HasIsSingleValued( map ) then + SetIsSingleValued( ainv, IsSingleValued( map ) ); + fi; + if HasIsTotal( map ) then + SetIsTotal( ainv, IsTotal( map ) ); + fi; + + # Surjectivity and injectivity are maintained. + if HasIsInjective( map ) then + SetIsInjective( ainv, IsInjective( map ) ); + fi; + if HasIsSurjective( map ) then + SetIsSurjective( ainv, IsSurjective( map ) ); + fi; + + return ainv; + end ); + + +############################################################################# +## +#T \<( , ) +## +## method for two linear mappings from Gaussian spaces, use canonical bases? +## + + +############################################################################# +## +#M CompositionMapping2( , map1> ) for left mod. hom. & lin. g.m.b.i. +## +InstallMethod( CompositionMapping2, + "for left module hom. and linear g.m.b.i.", + FamSource1EqFamRange2, + [ IsLeftModuleHomomorphism, + IsLeftModuleGeneralMapping + and IsLinearGeneralMappingByImagesDefaultRep ], + function( map2, map1 ) + local comp, # composition of and , result + mapi1, + gens, + genimages; + + # Check that the linear mappings can be composed. + + mapi1:=MappingGeneratorsImages(map1); + # Compute images for the generators of `map1'. + if IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and mapi1[2] = MappingGeneratorsImages(map2)[1] then + + gens := mapi1[1]; + genimages := MappingGeneratorsImages(map2)[2]; + + else + + gens:= mapi1[1]; + genimages:= List( mapi1[2], + v -> ImagesRepresentative( map2, v ) ); + + fi; + + # Construct the linear general mapping. + comp:= LeftModuleGeneralMappingByImages( + Source( map1 ), Range( map2 ), gens, genimages ); + + # Maintain images info (only if `gens' is not a basis). + if IsLinearGeneralMappingByImagesDefaultRep( comp ) + and not IsBound( comp!.basispreimage ) + and IsBound( map1!.basispreimage ) then + comp!.basispreimage := map1!.basispreimage; + comp!.corelations := map1!.corelations; + comp!.imagesbasispreimage := Immutable( + List( map1!.imagesbasispreimage, + v -> ImagesRepresentative( map2, v ) ) ); + fi; + + # Return the composition. + return comp; + end ); + + +############################################################################# +## +#M \+( , map2> ) . . . . . . . . . . . . . . . for two linear g.m.b.i. +## +## If both general mappings respect zero, additive inverses, scalar +## multiplication then the sum also does. +## +InstallOtherMethod( \+, + "for linear g.m.b.i. and general mapping", + IsIdenticalObj, + [ IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsGeneralMapping ], + function( map1, map2 ) + local gens, + genimages, + mapi1, + sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then + Error( " and must have same preimage" ); + fi; + + mapi1:=MappingGeneratorsImages(map1); + + if IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and mapi1[1] = MappingGeneratorsImages(map2)[1] then + + # If the generators in both general mappings are the same, + # it suffices to add the images. + gens := mapi1[1]; + genimages := mapi1[2] + MappingGeneratorsImages(map2)[2]; + + else + + # Compute images of the generators of `map1' under `map2'. + # (Note that both general mappings must be described in terms of + # `generators' in order to keep the meaning of `corelations'.) + gens:= mapi1[1]; + genimages:= mapi1[2] + + List( mapi1[1], + v -> ImagesRepresentative( map2, v ) ); + + fi; + + # Construct the linear general mapping. + sum:= LeftModuleGeneralMappingByImages( + Source( map1 ), Range( map1 ), gens, genimages ); + + # Maintain images info (only if `gens' is not a basis). + if IsLinearGeneralMappingByImagesDefaultRep( sum ) + and IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and not IsBound( sum!.basispreimage ) + and IsBound( map1!.basispreimage ) + and IsBound( map2!.basispreimage ) + and map1!.basispreimage = map2!.basispreimage then + sum!.basispreimage := map1!.basispreimage; + sum!.corelations := map1!.corelations; + sum!.imagesbasispreimage := + map1!.imagesbasispreimage + map2!.imagesbasispreimage; + fi; + + # Return the sum. + return sum; +end ); + +InstallOtherMethod( \+, + "for general mapping and linear g.m.b.i.", + IsIdenticalObj, + [ IsGeneralMapping, + IsGeneralMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map1, map2 ) + local gens, + genimages, + mapi2, + sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then + Error( " and must have same preimage" ); + fi; + + mapi2:=MappingGeneratorsImages(map2); + + if IsLinearGeneralMappingByImagesDefaultRep( map1 ) + and MappingGeneratorsImages(map1)[1]= mapi2[1] then + + # If the generators in both general mappings are the same, + # it suffices to add the images. + gens := mapi2[1]; + genimages := MappingGeneratorsImages(map1)[2] + mapi2[2]; + + else + + # Compute images of the generators of `map1' under `map2'. + # (Note that both general mappings must be described in terms of + # `generators' in order to keep the meaning of `corelations'.) + gens:= mapi2[1]; + genimages:= List( mapi2[1], + v -> ImagesRepresentative( map1, v ) ) + + mapi2[2]; + + fi; + + # Construct the linear general mapping. + sum:= LeftModuleGeneralMappingByImages( + Source( map1 ), Range( map1 ), gens, genimages ); + + # Maintain images info (only if `gens' is not a basis). + if IsLinearGeneralMappingByImagesDefaultRep( sum ) + and IsLinearGeneralMappingByImagesDefaultRep( map1 ) + and not IsBound( sum!.basispreimage ) + and IsBound( map1!.basispreimage ) + and IsBound( map2!.basispreimage ) + and map1!.basispreimage = map2!.basispreimage then + sum!.basispreimage := map1!.basispreimage; + sum!.corelations := map1!.corelations; + sum!.imagesbasispreimage := + map1!.imagesbasispreimage + map2!.imagesbasispreimage; + fi; + + # Return the sum. + return sum; +end ); + + +############################################################################# +## +#M \+( , ) . . . . . . . . . for two linear mappings by images +## +## The method for (total and single-valued general) mappings takes +## advantage from the fact that `generators' and `basispreimage' components +## need not be distinguished since the `corelations' component is empty. +## +InstallOtherMethod( \+, + "for linear m.b.i. and mapping", + IsIdenticalObj, + [ IsMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsMapping ], + function( map1, map2 ) + local gens, + genimages, + mapi1, + sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then + Error( " and must have same preimage" ); + fi; + + if IsBound( map1!.basispreimage ) then + + # Use the basis in the construction. + gens:= map1!.basispreimage; + + if IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and IsBound( map2!.basispreimage ) + and map1!.basispreimage = map2!.basispreimage then + + genimages := map1!.imagesbasispreimage + map2!.imagesbasispreimage; + + else + + genimages:= map1!.imagesbasispreimage + + List( gens, + v -> ImagesRepresentative( map2, v ) ); + + fi; + + else + + mapi1:=MappingGeneratorsImages(map1); + + if IsLinearGeneralMappingByImagesDefaultRep( map2 ) + and mapi1[1] = MappingGeneratorsImages(map2)[1] then + + # If the generators in both general mappings are the same, + # it suffices to add the images. + gens := mapi1[1]; + genimages := mapi1[2] + MappingGeneratorsImages(map2)[2]; + + else + + # Compute images of the generators of `map1' under `map2'. + # (Note that both general mappings must be described in terms of + # `generators' in order to keep the meaning of `corelations'.) + gens:= mapi1[1]; + genimages:= mapi1[2] + + List( mapi1[1], + v -> ImagesRepresentative( map2, v ) ); + + fi; + fi; + + # Construct the linear mapping. + sum:= LeftModuleHomomorphismByImagesNC( + Source( map1 ), Range( map1 ), gens, genimages ); + + # Return the sum. + return sum; + end ); + +InstallOtherMethod( \+, + "for mapping and linear m.b.i.", + IsIdenticalObj, + [ IsMapping, + IsMapping and IsLinearGeneralMappingByImagesDefaultRep ], + function( map1, map2 ) + local gens, + genimages, + mapi2, + sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + elif PreImagesRange( map1 ) <> PreImagesRange( map2 ) then + Error( " and must have same preimage" ); + fi; + + if IsBound( map2!.basispreimage ) then + + # Use the basis in the construction. + gens:= map2!.basispreimage; + + if IsLinearGeneralMappingByImagesDefaultRep( map1 ) + and IsBound( map1!.basispreimage ) + and map1!.basispreimage = map2!.basispreimage then + + genimages := map1!.imagesbasispreimage + map2!.imagesbasispreimage; + + else + + genimages:= List( gens, v -> ImagesRepresentative( map1, v ) ) + + map2!.imagesbasispreimage; + + fi; + + else + + mapi2:=MappingGeneratorsImages(map2); + + if IsLinearGeneralMappingByImagesDefaultRep( map1 ) + and MappingGeneratorsImages(map1)[1] = mapi2[1] then + + # If the generators in both general mappings are the same, + # it suffices to add the images. + gens := mapi2[1]; + genimages := MappingGeneratorsImages(map1)[2] + mapi2[2]; + + else + + # Compute images of the generators of `map2' under `map1'. + # (Note that both general mappings must be described in terms of + # `generators' in order to keep the meaning of `corelations'.) + gens:= mapi2[1]; + genimages:= List( mapi2[1], + v -> ImagesRepresentative( map1, v ) ) + + mapi2[2]; + + fi; + + fi; + + # Construct the linear mapping. + sum:= LeftModuleHomomorphismByImagesNC( + Source( map1 ), Range( map1 ), gens, genimages ); + + # Return the sum. + return sum; + end ); + + +############################################################################# +## +## 2. methods for linear mappings given by matrices +## + + +############################################################################# +## +#R IsLinearMappingByMatrixDefaultRep +## +## is another default representation of $F$-linear mappings between +## two free left modules $V$ and $W$ where $F$ is equal to the left acting +## domain of $V$ and of $W$. +## +## Defining components are +## +## `basissource' \: \\ +## basis of $V$, +## +## `basisrange' \: \\ +## basis of $W$, +## +## `matrix' \: \\ +## matrix over $F$, of dimensions $\dim(V)$ times $\dim(W)$. +## +## The mapping is defined as follows. +## The image of a vector in $V$ has coefficients +## `Coefficients( !.basissource ) * !.matrix' +## w.r.t. `!.basisrange'. +## +## If one wants to compute preimages, one needs the components +## `basisimage' \: \\ +## basis of the image of , +## +## `preimagesbasisimage' \: \\ +## preimages of the basis vectors of `basisimage', +## +## `relations' \: \\ +## linearly independent generators for the relation space, +## i.e., of the left null space of `!.matrix'. +## (The corresponding linear combinations of `basissource' +## generate the kernel.) +## +## If these components are not yet bound, they are computed by +## `MakePreImagesInfoLinearMappingByMatrix'. +## +## Computed images and preimages of free left modules under linear mappings +## are always free left modules. +## If one needs more structure (e.g., that of an algebra) for an image or +## preimage then the linear mapping must have a special representation. +## +## Note that the inverse general mapping of a linear mapping defined by +## a matrix is best handled if it uses the default method, +## since such an inverse general mapping delegates the tasks of computing +## (pre)images to the original general mapping. +## So the (pre)images info is computed only once. +#T but what about sums of such mappings? +#T better try to share info also in this case? +#T (share a list that is filled with the info later?) +## +DeclareRepresentation( + "IsLinearMappingByMatrixDefaultRep", + IsAttributeStoringRep, + [ "basissource", "basisrange", "matrix", + "basisimage", "preimagesbasisimage", "relations" ] ); + +InstallTrueMethod( IsAdditiveElementWithInverse, + IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ); +InstallTrueMethod( IsLeftModuleGeneralMapping, + IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ); + + +############################################################################# +## +#M LeftModuleHomomorphismByMatrix( , ,
) +## +## is the total and single-valued linear general mapping with a basis +## of the source and
a basis of the range, and the rows of the matrix +## being the coefficients vectors of the images of w.r.t. +##
. +## +InstallMethod( LeftModuleHomomorphismByMatrix, + "for two bases of free left modules and a matrix", + [ IsBasis, IsMatrix, IsBasis ], + function( BS, matrix, BR ) + local S, R, map; + + S:= UnderlyingLeftModule( BS ); + R:= UnderlyingLeftModule( BR ); + + # Check the arguments. + if Length( BS ) <> Length( matrix ) then + Error( " and must have the same length" ); + elif Length( BR ) <> Length( matrix[1] ) then + Error( "
and [1] must have the same length" ); + elif LeftActingDomain( S ) <> LeftActingDomain( R ) then + Error( " and must have same left acting domain" ); + fi; +#T check entries of the matrix? + + # Make the mapping. + map:= Objectify( TypeOfDefaultGeneralMapping( S, R, + IsSPGeneralMapping + and IsSingleValued + and IsTotal + and IsLeftModuleGeneralMapping + and IsLinearMappingByMatrixDefaultRep ), + rec( + basissource := BS, + matrix := Immutable( matrix ), + basisrange := BR + ) ); + + # return the mapping + return map; + end ); + + +############################################################################# +## +#F MakePreImagesInfoLinearMappingByMatrix( ) +## +## Provide the information for computing preimages, that is, set up +## the components `basisimage', `preimagesbasisimage', `relations'. +## +BindGlobal( "MakePreImagesInfoLinearMappingByMatrix", function( map ) + local ech, + B; + + ech:= SemiEchelonMatTransformation( map!.matrix ); + B:= Basis( Range( map ) ); + map!.basisimage := BasisNC( ImagesSource( map ), + List( ech.vectors, + x -> LinearCombination( B, x ) ) ); + map!.relations := Immutable( ech.relations ); + + map!.preimagesbasisimage := Immutable( List( ech.coeffs, + row -> LinearCombination( + map!.basissource, row ) ) ); +end ); + + +############################################################################# +## +#M KernelOfAdditiveGeneralMapping( ) . . . . . for left module m.b.m. +## +InstallMethod( KernelOfAdditiveGeneralMapping, + "for left module m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + local generators, S; + + # Form the linear combinations of the basis vectors for the + # relation space with the `basissource' of `map'. + + if not IsBound( map!.relations ) then + MakePreImagesInfoLinearMappingByMatrix( map ); + fi; + generators:= BasisVectors( map!.basissource ); + S:= Source( map ); + return LeftModuleByGenerators( LeftActingDomain( S ), + List( map!.relations, + r -> LinearCombination( generators, r ) ), + Zero( S ) ); + end ); + + +############################################################################# +## +#M IsInjective( ) . . . . . . . . . . . . . . for left module m.b.m. +## +InstallMethod( IsInjective, + "for left module m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + local generators; + + if not IsBound( map!.relations ) then + MakePreImagesInfoLinearMappingByMatrix( map ); + fi; + generators:= BasisVectors( map!.basissource ); + return ForAll( map!.relations, + r -> IsZero( LinearCombination( generators, r ) ) ); + end ); + + +############################################################################# +## +#M ImagesRepresentative( , ) . . . . . . for left module m.b.m. +## +InstallMethod( ImagesRepresentative, + "for left module m.b.m., and element", + FamSourceEqFamElm, + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, + IsObject ], + function( map, elm ) + elm:= Coefficients( map!.basissource, elm ); + if elm <> fail then + elm:= LinearCombination( map!.basisrange, elm * map!.matrix ); + fi; + return elm; + end ); + + +############################################################################# +## +#M PreImagesRepresentativeNC( , ) . . . . for left module m.b.m. +## +InstallMethod( PreImagesRepresentativeNC, + "for left module m.b.m., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, + IsObject ], + function( map, elm ) + if not IsBound( map!.basisimage ) then + MakePreImagesInfoLinearMappingByMatrix( map ); + fi; + elm:= Coefficients( map!.basisimage, elm ); + if elm = fail then + return fail; + fi; + return LinearCombination( map!.preimagesbasisimage, elm ); + end ); + +InstallMethod( PreImagesRepresentative, + "for left module m.b.m., and element", + FamRangeEqFamElm, + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep, + IsObject ], + function( map, elm ) + if not ( elm in Image( map ) ) then + return fail; + fi; + return PreImagesRepresentativeNC( map, elm ); + end ); + + +############################################################################# +## +#M ViewObj( ) . . . . . . . . . . . . . . . . for left module m.b.m. +## +InstallMethod( ViewObj, + "for a left module m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + Print( " " ); + View( UnderlyingLeftModule( map!.basisrange ) ); + Print( ">" ); + end ); + + +############################################################################# +## +#M PrintObj( ) . . . . . . . . . . . . . . . . for left module m.b.m. +## +InstallMethod( PrintObj, + "for a left module m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + Print( "LeftModuleHomomorphismByMatrix( ", + map!.basissource, ", ", map!.matrix, ", ", + map!.basisrange, " )" ); + end ); + + +############################################################################# +## +#M NaturalHomomorphismBySubspace( , ) . . . for free left modules +## +## Return the identity mapping. +## +InstallMethod( NaturalHomomorphismBySubspace, + "for left module and trivial left module", + IsIdenticalObj, + [ IsFreeLeftModule, IsFreeLeftModule and IsTrivial ], + SUM_FLAGS, # better than everything else + function( V, W ) + return IdentityMapping( V ); + end ); + + +############################################################################# +## +#F NaturalHomomorphismBySubspaceOntoFullRowSpace( , ) +## +InstallGlobalFunction( NaturalHomomorphismBySubspaceOntoFullRowSpace, + function( V, W ) + local F, + Wvectors, + mb, + compl, + gen, + B, + img, + canbas, + zero, + Bimgs, + nathom; + + # Check that the modules are finite dimensional. + if not IsFiniteDimensional( V ) or not IsFiniteDimensional( W ) then + TryNextMethod(); + elif not IsSubset( V, W ) then + Error( " must be contained in " ); + fi; + + # If the left acting domains are different, adjust them. + F:= LeftActingDomain( V ); + if F <> LeftActingDomain( W ) then + F:= Intersection2( F, LeftActingDomain( W ) ); + V:= AsLeftModule( F, V ); + W:= AsLeftModule( F, W ); + fi; + + # If `V' is equal to `W', return a zero mapping. + if Dimension( V ) = Dimension( W ) then + return ZeroMapping( V, FullRowModule( F, 0 ) ); + fi; + + # Compute a basis of `V' through a basis of `W'. + Wvectors:= BasisVectors( Basis( W ) ); + if IsEmpty( Wvectors ) then + mb:= MutableBasis( F, Wvectors, Zero( W ) ); + else + mb:= MutableBasis( F, Wvectors ); + fi; + compl:= []; + for gen in BasisVectors( Basis( V ) ) do + if CloseMutableBasis( mb, gen ) then + Add( compl, gen ); + fi; + od; + B:= BasisNC( V, Concatenation( Wvectors, compl ) ); + + # Compute the linear mapping by images. + img:= FullRowModule( F, Length( compl ) ); + canbas:= CanonicalBasis( img ); + zero:= Zero( img ); + Bimgs:= Concatenation( List( Wvectors, v -> zero ), + BasisVectors( canbas ) ); + nathom:= LeftModuleHomomorphismByMatrix( B, Bimgs, canbas ); +#T take a special representation for nat. hom.s, +#T (just compute coefficients, and then choose a subset ...) + SetIsSurjective( nathom, true ); + + # Enter the preimages info. + nathom!.basisimage:= canbas; + nathom!.preimagesbasisimage:= Immutable( compl ); +#T relations are not needed if the kernel is known ? + + SetKernelOfAdditiveGeneralMapping( nathom, W ); + + # Run the implications for the factor. + UseFactorRelation( V, W, img ); + + return nathom; + end ); + + +############################################################################# +## +#M NaturalHomomorphismBySubspace( , ) . . . for two free left modules +## +## return a left module m.b.m. +## +InstallMethod( NaturalHomomorphismBySubspace, + "for two finite dimensional free left modules", + IsIdenticalObj, + [ IsFreeLeftModule, IsFreeLeftModule ], + NaturalHomomorphismBySubspaceOntoFullRowSpace ); + + +############################################################################# +## +#M \*( , ) . . . . . . . . . . . . . for scalar and linear m.b.m. +## +InstallMethod( \*, + "for scalar and linear m.b.m.", + [ IsMultiplicativeElement, + IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( scalar, map ) + local mult, # the multiple of `map', result + F; # left acting domain + + # Check the scalar. + # (Maybe it is in fact another mapping, and we want to compose.) + if not IsInt( scalar ) + and not IsElmsColls( FamilyObj( scalar ), + FamilyObj( LeftActingDomain( Range( map ) ) ) ) then + TryNextMethod(); + fi; + + # Construct the linear mapping (if possible). + mult:= LeftModuleHomomorphismByMatrix( + map!.basissource, + scalar * map!.matrix, + map!.basisrange ); + + # If the scalar is invertible in the left acting domain of the source + # then surjectivity and injectivity are maintained as well as the image. + F:= LeftActingDomain( Source( map ) ); + if scalar in F and IsUnit( F, scalar ) then + + if HasIsInjective( map ) then + SetIsInjective( mult, IsInjective( map ) ); + fi; + if HasIsSurjective( map ) then + SetIsSurjective( mult, IsSurjective( map ) ); + fi; + + if IsBound( map!.basisimage ) then + scalar:= Inverse( scalar ); + mult!.basisimage := map!.basisimage; + mult!.preimagesbasisimage := Immutable( + List( map!.preimagesbasisimage, v -> scalar * v ) ); + mult!.relations := map!.relations; + fi; + + fi; + + return mult; + end ); + + +############################################################################# +## +#M AdditiveInverseOp( ) . . . . . . . . . . . . . . for linear m.b.m. +## +InstallMethod( AdditiveInverseOp, + "for linear m.b.m.", + [ IsGeneralMapping and IsLinearMappingByMatrixDefaultRep ], + function( map ) + local ainv; # the additive inverse of `map', result + + # Construct the linear general mapping (if possible). + ainv:= LeftModuleHomomorphismByMatrix( + map!.basissource, + AdditiveInverse( map!.matrix ), + map!.basisrange ); + + # Maintain preimages info. + if IsBound( map!.basisimage ) then + ainv!.basisimage := map!.basisimage; + ainv!.preimagesbasisimage := Immutable( + List( map!.preimagesbasisimage, AdditiveInverse ) ); + ainv!.relations := map!.relations; + fi; + + # Surjectivity and injectivity are maintained. + if HasIsInjective( map ) then + SetIsInjective( ainv, IsInjective( map ) ); + fi; + if HasIsSurjective( map ) then + SetIsSurjective( ainv, IsSurjective( map ) ); + fi; + + return ainv; + end ); + + +############################################################################# +## +#M CompositionMapping2( , map1> ) . for left mod. hom. & lin. m.b.m. +## +InstallMethod( CompositionMapping2, + "for left module hom. and linear m.b.m.", + FamSource1EqFamRange2, + [ IsLeftModuleHomomorphism, + IsLeftModuleHomomorphism and IsLinearMappingByMatrixDefaultRep ], + function( map2, map1 ) + local comp, # composition of and , result + BR, # basis of the range of `map2' + mat2; # matrix corresponding to `map2' + + # Compute images for the generators of `map1'. + if IsLinearMappingByMatrixDefaultRep( map2 ) + and map1!.basisrange = map2!.basissource then + + BR := map2!.basisrange; + mat2 := map2!.matrix; + + else + + BR:= Range( map2 ); + if not IsFiniteDimensional( BR ) then + TryNextMethod(); + fi; + BR:= Basis( BR ); + mat2:= List( BasisVectors( map1!.basisrange ), + v -> Coefficients( BR, ImagesRepresentative( map2, v ) ) ); + + fi; + + # Construct the linear mapping. + comp:= LeftModuleHomomorphismByMatrix( map1!.basissource, + map1!.matrix * mat2, BR ); + + # Return the composition. + return comp; + end ); + + +############################################################################# +## +#M \+( , map2> ) . . . . . . . . . . . . . . . . for two linear m.b.m. +## +## Two general mappings that respect addition can be added pointwise +## if their images are equal and their preimages are equal. +## The sum does also respect addition. +## +## If both general mappings respect zero, additive inverses, scalar +## multiplication then the sum also does. +## +BindGlobal( "SumOfMBMAndMapping", function( map1, map2 ) + local sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + fi; + + if IsLinearMappingByMatrixDefaultRep( map2 ) + and map1!.basissource = map2!.basissource + and map1!.basisrange = map2!.basisrange then + + # If the bases in both mappings are the same, + # it suffices to add the matrices. + sum:= LeftModuleHomomorphismByMatrix( + map1!.basissource, + map1!.matrix + map2!.matrix, + map1!.basisrange ); + + else + + # Compute images of the generators of `map1' under `map2'. + sum:= LeftModuleHomomorphismByMatrix( + map1!.basissource, + map1!.matrix + + List( BasisVectors( map1!.basissource ), + v -> Coefficients( map1!.basisrange, + ImagesRepresentative( map2, v ) ) ), + map1!.basisrange ); + + fi; + + # Return the sum. + return sum; +end ); + +BindGlobal( "SumOfMappingAndMBM", function( map1, map2 ) + local sum; + + # Check that the linear mappings can be added. + if Source( map1 ) <> Source( map2 ) + or Range( map1 ) <> Range( map2 ) then + Error( " and must have same source and range" ); + fi; + + if IsLinearMappingByMatrixDefaultRep( map1 ) + and map1!.basissource = map2!.basissource + and map1!.basisrange = map2!.basisrange then + + # If the bases in both mappings are the same, + # it suffices to add the matrices. + sum:= LeftModuleHomomorphismByMatrix( + map1!.basissource, + map1!.matrix + map2!.matrix, + map1!.basisrange ); + + else + + # Compute images of the generators of `map2' under `map1'. + sum:= LeftModuleHomomorphismByMatrix( + map2!.basissource, + List( BasisVectors( map2!.basissource ), + v -> Coefficients( map2!.basisrange, + ImagesRepresentative( map1, v ) ) ) + + map2!.matrix, + map2!.basisrange ); + + fi; + + # Return the sum. + return sum; +end ); + +InstallOtherMethod( \+, + "for linear m.b.m. and mapping", + IsIdenticalObj, + [ IsMapping and IsLinearMappingByMatrixDefaultRep, + IsMapping ], + SumOfMBMAndMapping ); + +InstallOtherMethod( \+, + "for mapping and linear m.b.m.", + IsIdenticalObj, + [ IsMapping, + IsMapping and IsLinearMappingByMatrixDefaultRep ], + SumOfMappingAndMBM ); + + +############################################################################# +## +#M \+( , ) . . . . for mapping by matrix and mapping by images +## +InstallMethod( \+, + "for linear m.b.m. and linear m.b.i.", + IsIdenticalObj, + [ IsMapping and IsLinearMappingByMatrixDefaultRep, + IsMapping and IsLinearGeneralMappingByImagesDefaultRep ], + SumOfMBMAndMapping ); + +InstallMethod( \+, + "for linear m.b.i. and linear m.b.m.", + IsIdenticalObj, + [ IsMapping and IsLinearGeneralMappingByImagesDefaultRep, + IsMapping and IsLinearMappingByMatrixDefaultRep ], + SumOfMappingAndMBM ); + + +############################################################################# +## +## 3. methods for vector spaces of linear mappings +## + + +############################################################################# +## +#M NiceFreeLeftModuleInfo( ) . . . . . . for a space of linear mappings +#M NiceVector( , ) . . for space of lin. mappings, and lin. mapping +#M UglyVector( , ) . . . for space of linear mappings, and matrix +## +InstallHandlingByNiceBasis( "IsLinearMappingsModule", rec( + detect := function( F, gens, V, zero ) + local S, R; + if not IsGeneralMappingCollection( V ) then + return false; + fi; + gens:= AsList( gens ); + if IsEmpty( gens ) then + S:= Source( zero ); + R:= Range( zero ); + else + S:= Source( gens[1] ); + R:= Range( gens[1] ); + fi; + + # Check that the mappings have left modules as source and range. + if not IsLeftModule( S ) + or not IsLeftModule( R ) + or not ForAll( gens, IsMapping ) then + return false; + fi; + + # Check that all generators have the same source and range, + # and that source and range are in fact left modules. + if ForAny( gens, map -> Source( map ) <> S ) + or ForAny( gens, map -> Range( map ) <> R ) then + return false; + fi; + return true; + end, + + NiceFreeLeftModuleInfo := function( V ) + local F, z, S, R; + F:= LeftActingDomain( V ); + z:= Zero( V ); + S:= Source( z ); + R:= Range( z ); + + # Write `S' and `R' over `F' (necessary for the nice left module). + if LeftActingDomain( S ) <> F then + S:= AsLeftModule( F, S ); + R:= AsLeftModule( F, R ); + fi; + + return rec( basissource := Basis( S ), + basisrange := Basis( R ) ); + end, + + NiceVector := function( V, v ) + local info, M, i, c; + info:= NiceFreeLeftModuleInfo( V ); + if IsLinearMappingByMatrixDefaultRep( v ) + and info.basissource = v!.basissource + and info.basisrange = v!.basisrange then + M:= v!.matrix; + else + M:= []; + for i in BasisVectors( info.basissource ) do + c:= Coefficients( info.basisrange, ImagesRepresentative( v, i ) ); + if c = fail then + return fail; + fi; + Add( M, c ); + od; + fi; + return M; + end, + + UglyVector := function( V, mat ) + local info; + info:= NiceFreeLeftModuleInfo( V ); + return LeftModuleHomomorphismByMatrix( info.basissource, + mat, info.basisrange ); + end ) ); + + +############################################################################# +## +## 4. methods for algebras of linear mappings +## + + +############################################################################# +## +#M RingByGenerators( ) . . ring generated by a list of lin. mappings +## +## If is a list of linear mappings of finite vector spaces then +## we construct a hom algebra over the prime field. +## +InstallOtherMethod( RingByGenerators, + "for a list of linear mappings of finite vector spaces", + [ IsGeneralMappingCollection ], + function( maps ) + local S; + + maps:= AsList( maps ); + if IsEmpty( maps ) then + Error( "need at least one element" ); + fi; + if not ForAll( maps, IsLeftModuleHomomorphism ) then + TryNextMethod(); + fi; + S:= Source( maps[1] ); + if IsVectorSpace( S ) + and IsFFECollection( LeftActingDomain( S ) ) then + return FLMLORByGenerators( GF( Characteristic( S ) ), maps ); + elif IsVectorSpace( S ) + and IsCyclotomicCollection( LeftActingDomain( S ) ) then + return FLMLORByGenerators( Integers, maps ); + else + TryNextMethod(); + fi; + end ); + + +############################################################################# +## +#M DefaultRingByGenerators( ) . . ring cont. a list of lin. mappings +## +## If is a list of mappings of vector spaces then +## we construct an algebra over the prime field. +## (So this may differ from the result of `RingByGenerators' if the +## characteristic is zero.) +## +InstallOtherMethod( DefaultRingByGenerators, + "for a list of linear mappings of vector spaces", + [ IsGeneralMappingCollection ], + function( maps ) + local S; + maps:= AsList( maps ); + if IsEmpty( maps ) then + Error( "need at least one element" ); + fi; + if not ForAll( maps, IsLeftModuleHomomorphism ) then + TryNextMethod(); + fi; + S:= Source( maps[1] ); + if IsVectorSpace( S ) + and IsFFECollection( LeftActingDomain( S ) ) then + return FLMLORByGenerators( GF( Characteristic( S ) ), maps ); + elif IsVectorSpace( S ) + and IsCyclotomicCollection( LeftActingDomain( S ) ) then + return FLMLORByGenerators( Rationals, maps ); + else + TryNextMethod(); + fi; + end ); + + +############################################################################# +## +#M RingWithOneByGenerators( ) . . . . . for a list of linear mappings +## +## If is a list of linear mappings of a finite vector space then +## we construct a hom algebra-with-one over the prime field. +## +InstallOtherMethod( RingWithOneByGenerators, + "for a list of linear mappings of finite vector spaces", + [ IsGeneralMappingCollection ], + function( maps ) + local S; + + maps:= AsList( maps ); + if IsEmpty( maps ) then + Error( "need at least one element" ); + fi; + if not ForAll( maps, IsLeftModuleHomomorphism ) then + TryNextMethod(); + fi; + S:= Source( maps[1] ); + if IsVectorSpace( S ) + and IsFFECollection( LeftActingDomain( S ) ) + and S = Range( maps[1] ) then + return FLMLORWithOneByGenerators( GF( Characteristic( S ) ), maps ); + elif IsVectorSpace( S ) + and IsCyclotomicCollection( LeftActingDomain( S ) ) then + return FLMLORWithOneByGenerators( Integers, maps ); + else + TryNextMethod(); + fi; + end ); + + +############################################################################# +## +#M IsGeneratorsOfFLMLOR( , ) +#M IsGeneratorsOfFLMLORWithOne( , ) +## +#T check that sources and ranges coincide: +#T if ForAny( maps, map -> Source( map ) <> S or Range( map ) <> S ) then + +#T add implication that a FLMLOR of mappings is associative! + +#T for ideals construction, inherit the info? +#T SetNiceFreeLeftModuleInfo( I, NiceFreeLeftModuleInfo( A ) ); + + +############################################################################# +## +## 5. methods for full hom spaces +## + + +############################################################################# +## +#M IsFullHomModule( V ) . . . . . . . . . . . for space of linear mappings +## +InstallMethod( IsFullHomModule, + "for space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection ], + V -> Dimension( V ) = Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basissource ) ) + * Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basisrange ) ) ); + + +############################################################################# +## +#M Dimension( ) . . . . . . . . . for full hom space of linear mappings +## +InstallMethod( Dimension, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + V -> Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basissource ) ) + * Dimension( UnderlyingLeftModule( NiceFreeLeftModuleInfo( V ).basisrange ) ) ); + + +############################################################################# +## +#M Random( ) . . . . . . . . . . . for full hom space of linear mappings +## +InstallMethodWithRandomSource( Random, + "for a random source and full hom space of linear mappings", + [ IsRandomSource, IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + function( rs, M ) + local BS, BR; + + BR:= NiceFreeLeftModuleInfo( M ); + BS:= BR.basissource; + BR:= BR.basisrange; + + return LeftModuleHomomorphismByMatrix( BS, + RandomMat( rs, + Dimension( UnderlyingLeftModule( BS ) ), + Dimension( UnderlyingLeftModule( BR ) ), + LeftActingDomain( M ) ), + BR ); + end ); + + +############################################################################# +## +#M Representative( ) . . . . . . . for full hom space of linear mappings +## +## This method is necessary for example for computing the `Zero' value of +## . Note that does in general *not* store any generators! +## +InstallMethod( Representative, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + function( M ) + local BS, BR; + + BR:= NiceFreeLeftModuleInfo( M ); + BS:= BR.basissource; + BR:= BR.basisrange; + + return LeftModuleHomomorphismByMatrix( BS, + NullMat( Dimension( UnderlyingLeftModule( BS ) ), + Dimension( UnderlyingLeftModule( BR ) ), + LeftActingDomain( M ) ), + BR ); + end ); + + +############################################################################# +## +#M GeneratorsOfLeftModule( ) . . . for full hom space of linear mappings +## +BindGlobal( "StandardGeneratorsOfFullHomModule", function( M ) + local BS, BR, R, one, m, n, zeromat, gens, i, j, gen; + + BR:= NiceFreeLeftModuleInfo( M ); + BS:= BR.basissource; + BR:= BR.basisrange; + R:= LeftActingDomain( M ); + one:= One( R ); + m:= Dimension( UnderlyingLeftModule( BS ) ); + n:= Dimension( UnderlyingLeftModule( BR ) ); + zeromat:= NullMat( m, n, R ); + gens:= []; + for i in [ 1 .. m ] do + for j in [ 1 .. n ] do + gen:= List( zeromat, ShallowCopy ); + gen[i][j]:= one; + Add( gens, LeftModuleHomomorphismByMatrix( BS, gen, BR ) ); + od; + od; + + return gens; +end ); + +InstallMethod( GeneratorsOfLeftModule, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + StandardGeneratorsOfFullHomModule ); + + +############################################################################# +## +#M NiceFreeLeftModule( ) . . . . . for full hom space of linear mappings +## +## We need a special method since we decided not to store vector space +## generators in full hom spaces; +## note that the default methods for `NiceFreeLeftModule' are installed with +## requirement `HasGeneratorsOfLeftModule'. +## +InstallMethod( NiceFreeLeftModule, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + function( M ) + if HasGeneratorsOfLeftModule( M ) then + TryNextMethod(); + fi; + GeneratorsOfLeftModule( M ); + if not HasGeneratorsOfLeftModule( M ) then + TryNextMethod(); + fi; + return NiceFreeLeftModule( M ); + end ); + + +############################################################################# +## +#M ViewObj( ) . . . . . . . . . . for full hom space of linear mappings +#M PrintObj( ) . . . . . . . . . . for full hom space of linear mappings +## +BindGlobal( "ViewFullHomModule", function( M ) + local info; + + info:= NiceFreeLeftModuleInfo( M ); + if IsIdenticalObj( info.basissource, info.basisrange ) then + Print( "End( " ); + View( LeftActingDomain( M ) ); + Print( ", " ); + View( UnderlyingLeftModule( info.basissource ) ); + Print( " )" ); + else + Print( "Hom( " ); + View( LeftActingDomain( M ) ); + Print( ", " ); + View( UnderlyingLeftModule( info.basissource ) ); + Print( ", " ); + View( UnderlyingLeftModule( info.basisrange ) ); + Print( " )" ); + fi; +end ); + +InstallMethod( ViewObj, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], SUM_FLAGS, + ViewFullHomModule ); + +InstallMethod( PrintObj, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], SUM_FLAGS, + ViewFullHomModule ); + + +############################################################################# +## +#M \in( , ) . . . . . . . . . . for full hom space of linear mappings +## +InstallMethod( \in, + "for full hom space of linear mappings", + IsElmsColls, + [ IsGeneralMapping, + IsFreeLeftModule and IsGeneralMappingCollection + and IsFullHomModule ], + function( map, M ) + local info; + info:= NiceFreeLeftModuleInfo( M ); + return Source( map ) = UnderlyingLeftModule( info.basissource ) + and Range( map ) = UnderlyingLeftModule( info.basisrange ) + and IsLeftModuleHomomorphism( map ); + end ); + + +############################################################################# +## +#M IsPseudoCanonicalBasisFullHomModule( ) . . . . for a full hom module +## +InstallMethod( IsPseudoCanonicalBasisFullHomModule, + "for a basis of a full hom module", + [ IsBasis ], + function( B ) + local V; + + V:= UnderlyingLeftModule( B ); + if IsGeneralMappingCollection( V ) then + if not IsFullHomModule( V ) then + return false; + fi; + return BasisVectors( B ) = StandardGeneratorsOfFullHomModule( V ); + else + Error( "do not know what a pseudo canon. basis for is" ); + fi; + end ); + + +############################################################################# +## +#M BasisVectors( ) . . . for pseudo canonical basis of a full hom module +## +InstallMethod( BasisVectors, + "for pseudo canonical basis of a full hom module", + [ IsBasis and IsPseudoCanonicalBasisFullHomModule ], + B -> StandardGeneratorsOfFullHomModule( UnderlyingLeftModule( B ) ) ); + + +############################################################################# +## +#M Coefficients( , ) for a pseudo canon. basis of a full hom module +## +InstallOtherMethod( Coefficients, + "for pseudo canon. basis of a full hom module, and lin. mapping", + IsCollsElms, + [ IsBasis and IsPseudoCanonicalBasisFullHomModule, IsGeneralMapping ], + function( B, map ) + local V, info; + V:= UnderlyingLeftModule( B ); + if not IsGeneralMappingCollection( V ) then + TryNextMethod(); + fi; + info:= NiceFreeLeftModuleInfo( V ); + if Source( map ) = UnderlyingLeftModule( info.basissource ) + and Range( map ) = UnderlyingLeftModule( info.basisrange ) + and IsLeftModuleHomomorphism( map ) then + return Concatenation( + List( BasisVectors( info.basissource ), + v -> Coefficients( info.basisrange, + ImagesRepresentative( map, v ) ) ) ); + else + return fail; + fi; + end ); + +InstallMethod( Coefficients, + "for pseudo can. basis of full hom module, and lin. m.b.m.", + IsCollsElms, + [ IsBasis and IsPseudoCanonicalBasisFullHomModule, + IsMapping and IsLinearMappingByMatrixDefaultRep ], + function( B, map ) + local V, info; + V:= UnderlyingLeftModule( B ); + if not IsGeneralMappingCollection( V ) then + TryNextMethod(); + fi; + info:= NiceFreeLeftModuleInfo( V ); + if map!.basissource = info.basissource + and map!.basisrange = info.basisrange then + return Concatenation( map!.matrix ); + elif Source( map ) = UnderlyingLeftModule( info.basissource ) + and Range( map ) = UnderlyingLeftModule( info.basisrange ) then + return Concatenation( + List( BasisVectors( info.basissource ), + v -> Coefficients( info.basisrange, + ImagesRepresentative( map, v ) ) ) ); + else + return fail; + fi; + end ); + + +############################################################################# +## +#M Basis( ) . . . . . . . . . . . . . . . . . . . . for full hom module +## +InstallMethod( Basis, + "for full hom space of linear mappings", + [ IsFreeLeftModule and IsFullHomModule ], 100, + function( V ) + local B; + B:= Objectify( NewType( FamilyObj( V ), + IsFiniteBasisDefault + and IsPseudoCanonicalBasisFullHomModule + and IsAttributeStoringRep ), + rec() ); + SetUnderlyingLeftModule( B, V ); + if IsFiniteDimensional( V ) then + SetIsFinite( B, true ); + #T Check whether its is a) correct and even if so + #T b) sometimes to expensive + SetBasisVectors( B, GeneratorsOfLeftModule(V) ); + fi; + return B; + end ); + + +############################################################################# +## +#M Hom( , , ) +## +InstallMethod( Hom, + "for division ring and two free left modules", + [ IsDivisionRing, IsFreeLeftModule, IsFreeLeftModule ], + function( F, V, W ) + local M; # the free module record, result + + if V = W then + return End( F, V ); + fi; + if LeftActingDomain( V ) <> F then + V:= AsLeftModule( F, V ); + fi; + if LeftActingDomain( W ) <> F then + W:= AsLeftModule( F, W ); + fi; + + M:= Objectify( NewType( CollectionsFamily( GeneralMappingsFamily( + ElementsFamily( FamilyObj( V ) ), + ElementsFamily( FamilyObj( W ) ) ) ), + IsFreeLeftModule + and IsFullHomModule + and IsLinearMappingsModule + and IsGeneralMappingCollection + and IsAttributeStoringRep ), + rec() ); + + SetLeftActingDomain( M, F ); + SetNiceFreeLeftModuleInfo( M, rec( + basissource := Basis( V ), + basisrange := Basis( W ) ) ); + + return M; + end ); + + +############################################################################# +## +#M End( , ) . . . . . . . . . for division ring and free left module +## +## We use the generators that are also taken for full matrix FLMLORs. +## +InstallMethod( End, + "for division ring and space of linear mappings", + [ IsDivisionRing, IsFreeLeftModule ], + function( F, V ) + local n, # dimension of `V' + i, # loop over the rows + gens, # list of generators + one, # the identity of the field + B, # basis of `V' + A; # algebra, result + + if LeftActingDomain( V ) <> F then + V:= AsLeftModule( F, V ); + fi; + + n:= Dimension( V ); + gens:= NullMat( n, n, F ); + gens:= [ gens, List( gens, ShallowCopy ) ]; + one:= One( F ); + + # Construct the generators. + gens[1][1][1]:= one; + gens[2][1][n]:= one; + for i in [ 2 .. n ] do + gens[2][i][i-1]:= one; + od; + B:= Basis( V ); + gens:= List( gens, mat -> LeftModuleHomomorphismByMatrix( B, mat, B ) ); + + # Construct the FLMLOR. + A:= AlgebraWithOneByGenerators( F, gens ); + SetIsFullHomModule( A, true ); + SetNiceFreeLeftModuleInfo( A, rec( + basissource := B, + basisrange := B ) ); + + # Return the FLMLOR. + return A; + end ); + + +#T InstallMethod( Field, true, [ IsGeneralMappingCollection ], 0, ... ); +#T InstallMethod( DefaultField, true, [ IsGeneralMappingCollection ], 0, ... ); diff --git a/src/code.c b/src/code.c index 5ff2315c98..40268f9de8 100644 --- a/src/code.c +++ b/src/code.c @@ -57,6 +57,7 @@ DECL_MODULE_STATE Int CountExpr; static ModuleStateOffset CodeStateOffset = -1; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct CodeModuleState * CShelper(void) { return (struct CodeModuleState *)StateSlotsAtOffset(CodeStateOffset); diff --git a/src/collectors.cc b/src/collectors.cc index 3a8f37b314..c3561ea8db 100644 --- a/src/collectors.cc +++ b/src/collectors.cc @@ -63,6 +63,7 @@ DECL_MODULE_STATE UInt SC_MAX_STACK_SIZE; static ModuleStateOffset CollectorsStateOffset = -1; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct CollectorsState_ * CollectorsState(void) { return (struct CollectorsState_ *)StateSlotsAtOffset(CollectorsStateOffset); @@ -380,7 +381,7 @@ static Int SingleCollectWord(Obj sc, Obj vv, Obj w) Obj tmp; // temporary obj for power - Int resized = 0;// indicates whether a Resize() happened + BOOL resized = FALSE;// indicates whether a Resize() happened // is the first non-trivial entry in start = SC_NUMBER_RWS_GENERATORS(sc); @@ -421,23 +422,23 @@ static Int SingleCollectWord(Obj sc, Obj vv, Obj w) const UInt desiredStackSize = sizeof(Obj) * (max + 2); if ( SIZE_OBJ(vnw) < desiredStackSize ) { ResizeBag( vnw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vlw) < desiredStackSize ) { ResizeBag( vlw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vpw) < desiredStackSize ) { ResizeBag( vpw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vew) < desiredStackSize ) { ResizeBag( vew, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vge) < desiredStackSize ) { ResizeBag( vge, desiredStackSize ); - resized = 1; + resized = TRUE; } if( resized ) return -1; @@ -891,7 +892,7 @@ static Int CombiCollectWord(Obj sc, Obj vv, Obj w) Obj tmp; // temporary obj for power - Int resized = 0;// indicates whether a Resize() happened + BOOL resized = FALSE;// indicates whether a Resize() happened // if is the identity return now if ( NPAIRS_WORD(w) == 0 ) { @@ -929,23 +930,23 @@ static Int CombiCollectWord(Obj sc, Obj vv, Obj w) const UInt desiredStackSize = sizeof(Obj) * (max + 2); if ( SIZE_OBJ(vnw) < desiredStackSize ) { ResizeBag( vnw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vlw) < desiredStackSize ) { ResizeBag( vlw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vpw) < desiredStackSize ) { ResizeBag( vpw, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vew) < desiredStackSize ) { ResizeBag( vew, desiredStackSize ); - resized = 1; + resized = TRUE; } if ( SIZE_OBJ(vge) < desiredStackSize ) { ResizeBag( vge, desiredStackSize ); - resized = 1; + resized = TRUE; } if( resized ) return -1; diff --git a/src/cyclotom.c b/src/cyclotom.c index 3025530f94..17b61a3c03 100644 --- a/src/cyclotom.c +++ b/src/cyclotom.c @@ -185,6 +185,7 @@ DECL_MODULE_STATE UInt LastNCyc; #ifdef HPCGAP }; // end of struct CycModuleState +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct CycModuleState *CycState(void) { return (struct CycModuleState *)StateSlotsAtOffset(CycStateOffset); @@ -835,7 +836,7 @@ static UInt FindCommonField(UInt nl, UInt nr, UInt *ml, UInt *mr) "This computation requires a cyclotomic field of degree %d, larger " "than the current limit of %d", n, (Int)CyclotomicsLimit, - "You may return after raising the limit with SetCyclotomicsLimit"); + "you can enter 'return;' after raising the limit with SetCyclotomicsLimit"); } // Finish up diff --git a/src/error.c b/src/error.c index 2618e32739..325a661234 100644 --- a/src/error.c +++ b/src/error.c @@ -184,12 +184,17 @@ static Obj FuncCURRENT_STATEMENT_LOCATION(Obj self, Obj context) return retlist; } -static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj stream, Obj context, - Obj activeContext, Obj level, - Obj totalDepth) +static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, + Obj stream, + Obj context, + Obj activeContext, + Obj level, + Obj prefixWidth) { + volatile Obj location = Fail; + if (IsBottomLVars(context)) - return 0; + return Fail; // HACK: we want to redirect output // Try to print the output to stream. Use *errout* as a fallback. @@ -208,35 +213,26 @@ static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj stream, Obj context, BOOL rethrow = FALSE; GAP_TRY { - UInt levelInt = INT_INTOBJ(level); - UInt totalDepthInt = INT_INTOBJ(totalDepth); - UInt prefixWidth = 0; - UInt levelWidth = 0; - UInt i; - - char prefix[32]; Obj func = FUNC_LVARS(context); Obj funcname = NAME_FUNC(func); Int line = -1; - GAP_ASSERT(func); + Stat call = STAT_LVARS(context); Obj body = BODY_FUNC(func); Obj filename = GET_FILENAME_BODY(body); - while (totalDepthInt > 0) { - prefixWidth++; - totalDepthInt /= 10; - } - if (activeContext != Fail) { - i = levelInt; + char prefix[32]; + UInt levelInt = INT_INTOBJ(level); + UInt levelWidth = 0; + UInt i = levelInt; while (i > 0) { levelWidth++; i /= 10; } snprintf(prefix, sizeof(prefix), "%c%*s[%lu] ", context == activeContext ? '*' : ' ', - (int)(prefixWidth - levelWidth), "", + (int)(INT_INTOBJ(prefixWidth) - levelWidth), "", (unsigned long)levelInt); Pr("%s", (Int)prefix, 0); } @@ -274,11 +270,7 @@ static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj stream, Obj context, SWITCH_TO_OLD_LVARS(currLVars); } if (line > 0) { - Pr("\n", 0, 0); - for (i = 0; i < prefixWidth + 2; i++) { - Pr(" ", 0, 0); - } - Pr("@ %g:%d", (Int)filename, line); + location = NewPlistFromArgs(filename, INTOBJ_INT(line)); } } GAP_CATCH @@ -292,7 +284,7 @@ static Obj FuncPRINT_CURRENT_STATEMENT(Obj self, Obj stream, Obj context, if (rethrow) GAP_THROW(); - return 0; + return location; } /**************************************************************************** @@ -422,7 +414,6 @@ static Obj CallErrorInner(const Char * msg, Int arg2, UInt justQuit, UInt mayReturnVoid, - UInt mayReturnObj, Obj lateMessage) { // Must do this before creating any other GAP objects, @@ -447,7 +438,6 @@ static Obj CallErrorInner(const Char * msg, #endif AssPRec(r, RNamName("context"), STATE(CurrLVars)); AssPRec(r, RNamName("justQuit"), justQuit ? True : False); - AssPRec(r, RNamName("mayReturnObj"), mayReturnObj ? True : False); AssPRec(r, RNamName("mayReturnVoid"), mayReturnVoid ? True : False); AssPRec(r, RNamName("lateMessage"), lateMessage); l = NewPlistFromArgs(EarlyMsg); @@ -469,7 +459,7 @@ static Obj CallErrorInner(const Char * msg, void ErrorQuit(const Char * msg, Int arg1, Int arg2) { - CallErrorInner(msg, arg1, arg2, 1, 0, 0, False); + CallErrorInner(msg, arg1, arg2, 1, 0, False); Panic("ErrorQuit must not return"); } @@ -496,28 +486,19 @@ void ErrorMayQuitNrAtLeastArgs(Int narg, Int actual) } -/**************************************************************************** -** -*F ErrorReturnObj( , , , ) . . print and return obj -*/ -Obj ErrorReturnObj(const Char * msg, Int arg1, Int arg2, const Char * msg2) -{ - Obj LateMsg; - LateMsg = MakeString(msg2); - return CallErrorInner(msg, arg1, arg2, 0, 0, 1, LateMsg); -} - - /**************************************************************************** ** *F ErrorReturnVoid( , , , ) . . . print and return */ void ErrorReturnVoid(const Char * msg, Int arg1, Int arg2, const Char * msg2) { - Obj LateMsg; - LateMsg = MakeString(msg2); - CallErrorInner(msg, arg1, arg2, 0, 1, 0, LateMsg); - // ErrorMode( msg, arg1, arg2, (Obj)0, msg2, 'x' ); + if (msg2 == 0) { + msg2 = "you can enter 'return;' to continue"; + } + + Obj lateMsg = MakeString("you can enter 'quit;' to quit to outer loop, or\n"); + AppendString(lateMsg, MakeString(msg2)); + CallErrorInner(msg, arg1, arg2, 0, 1, lateMsg); } /**************************************************************************** @@ -526,8 +507,8 @@ void ErrorReturnVoid(const Char * msg, Int arg1, Int arg2, const Char * msg2) */ void ErrorMayQuit(const Char * msg, Int arg1, Int arg2) { - Obj LateMsg = MakeString("type 'quit;' to quit to outer loop"); - CallErrorInner(msg, arg1, arg2, 0, 0, 0, LateMsg); + Obj LateMsg = MakeString("you can enter 'quit;' to quit to outer loop"); + CallErrorInner(msg, arg1, arg2, 0, 0, LateMsg); Panic("ErrorMayQuit must not return"); } @@ -648,7 +629,7 @@ void ErrorBoundedInt( void AssertionFailure(void) { - ErrorReturnVoid("Assertion failure", 0, 0, "you may 'return;'"); + ErrorReturnVoid("Assertion failure", 0, 0, 0); } void AssertionFailureWithMessage(Obj message) @@ -659,7 +640,7 @@ void AssertionFailureWithMessage(Obj message) AssertionFailure(); } else if (IS_STRING_REP(message)) { - ErrorReturnVoid("Assertion failure: %g", (Int)message, 0, "you may 'return;'"); + ErrorReturnVoid("Assertion failure: %g", (Int)message, 0, 0); } else { PrintObj(message); diff --git a/src/error.h b/src/error.h index 7915e12756..d0d8749d97 100644 --- a/src/error.h +++ b/src/error.h @@ -69,13 +69,6 @@ void ErrorMayQuitNrArgs(Int narg, Int actual) NORETURN; void ErrorMayQuitNrAtLeastArgs(Int narg, Int actual) NORETURN; -/**************************************************************************** -** -*F ErrorReturnObj( , , , ) . . print and return obj -*/ -Obj ErrorReturnObj(const Char * msg, Int arg1, Int arg2, const Char * msg2); - - /**************************************************************************** ** *F ErrorReturnVoid( , , , ) . . . print and return diff --git a/src/exprs.c b/src/exprs.c index 2c234633ad..840d2d709b 100644 --- a/src/exprs.c +++ b/src/exprs.c @@ -66,6 +66,7 @@ DECL_MODULE_STATE UInt OldPrintPrecedence; static ModuleStateOffset ExprsStateOffset = -1; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct ExprsState * ExprsState(void) { return (struct ExprsState *)StateSlotsAtOffset(ExprsStateOffset); diff --git a/src/funcs.c b/src/funcs.c index 62919177f5..4d585e5bb2 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -50,6 +50,7 @@ struct FuncsModuleState { #ifdef HPCGAP }; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct FuncsModuleState *FuncsState(void) { return (struct FuncsModuleState *)StateSlotsAtOffset(FuncsStateOffset); @@ -386,8 +387,7 @@ void RecursionDepthTrap( void ) if (GetRecursionDepth() > 0) { recursionDepth = GetRecursionDepth(); SetRecursionDepth(0); - ErrorReturnVoid("recursion depth trap (%d)", (Int)recursionDepth, 0, - "you may 'return;'"); + ErrorReturnVoid("recursion depth trap (%d)", (Int)recursionDepth, 0, 0); SetRecursionDepth(recursionDepth); } } diff --git a/src/gap.c b/src/gap.c index 711c0eb142..e88bcc8711 100644 --- a/src/gap.c +++ b/src/gap.c @@ -409,7 +409,6 @@ int realmain(int argc, const char * argv[]) { UInt type; // result of compile Obj func; // function (compiler) - Int4 crc; // crc of file to compile // initialize everything and read init.g which runs the GAP session InitializeGap(&argc, argc, argv, 1); @@ -425,12 +424,11 @@ int realmain(int argc, const char * argv[]) if (!CloseInput(&input)) { return 2; } - crc = SyGAPCRC(SyCompileInput); type = CompileFunc( MakeImmString(SyCompileOutput), func, MakeImmString(SyCompileName), - crc, + SyGAPCRC(SyCompileInput), MakeImmString(SyCompileMagic1) ); return ( type == 0 ) ? 1 : 0; } diff --git a/src/gaptime.c b/src/gaptime.c index c0fe220192..4bc40fe55f 100644 --- a/src/gaptime.c +++ b/src/gaptime.c @@ -267,17 +267,17 @@ static Obj FuncNanosecondsSinceEpochInfo(Obj self) Obj res, tmp; Int8 resolution; const char * method = "unsupported"; - Int monotonic = 0; + BOOL monotonic = FALSE; #if defined(__APPLE__) && defined(__MACH__) method = "mach_absolute_time"; - monotonic = 1; + monotonic = TRUE; #elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) method = "clock_gettime"; - monotonic = 1; + monotonic = TRUE; #elif defined(HAVE_GETTIMEOFDAY) method = "gettimeofday"; - monotonic = 0; + monotonic = FALSE; #endif res = NEW_PREC(4); @@ -315,7 +315,7 @@ static Obj FuncSleep(Obj self, Obj secs) if (HaveInterrupt()) { ClearError(); // The interrupt may still be pending ErrorReturnVoid("user interrupt in sleep", 0, 0, - "you can 'return;' as if the sleep was finished"); + "you can enter 'return;' as if the sleep was finished"); } return 0; @@ -339,7 +339,7 @@ static Obj FuncMicroSleep(Obj self, Obj msecs) ClearError(); // The interrupt may still be pending ErrorReturnVoid( "user interrupt in microsleep", 0, 0, - "you can 'return;' as if the microsleep was finished"); + "you can enter 'return;' as if the microsleep was finished"); } return 0; diff --git a/src/gasman.c b/src/gasman.c index 6712ebec79..0575a384b7 100644 --- a/src/gasman.c +++ b/src/gasman.c @@ -129,7 +129,7 @@ #include #include -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ #include #endif @@ -1957,7 +1957,7 @@ static NOINLINE void GenStackFuncBags(void) DisableMarkBagValidation = 1; #endif -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ emscripten_scan_stack(ScanRange); emscripten_scan_registers(ScanRange); // The standard scanning may not be required with @@ -2026,7 +2026,7 @@ static UInt CollectBags_Mark(UInt FullBags) // For old bags, we invoke the marking function for bags with the // given TNUM. // Young bags normally are never put onto the changed list, because - // CHANGED_BAGS ignores young bags. However, it can happen if we + // CHANGED_BAG ignores young bags. However, it can happen if we // resize an old bag and it needs to be moved as a result, or if we // swap the masterpointers of an old and a young bag. In that case, // we must be careful to not collect the young bag (which was old @@ -2566,7 +2566,7 @@ void CheckMasterPointers( void ) // we must make sure to mark the new bag2 as changed, too (and vice-versa). // // 2. Both bags are young. Then they typically will not be on the list of -// changed bags, as CHANGED_BAGS just skips them. +// changed bags, as CHANGED_BAG just skips them. // However, while CHANGED_BAG will never put a young bag on the list of // changed bags, young bags can still be put on the ChangedBags list in // step 3, so we need to do something similar as in step 1. diff --git a/src/gvars.c b/src/gvars.c index e705d8e885..76d2746c9b 100644 --- a/src/gvars.c +++ b/src/gvars.c @@ -675,7 +675,7 @@ void MakeThreadLocalVar ( if (IS_INTOBJ(ExprGVar(gvar))) value = (Obj) 0; SET_ELM_GVAR_LIST( ExprGVars, gvar, INTOBJ_INT(rnam) ); - SetHasExprCopiesFopies(gvar, 1); + SetHasExprCopiesFopies(gvar, TRUE); CHANGED_GVAR_LIST( ExprGVars, gvar ); if (value && TLVars) SetTLDefault(TLVars, rnam, value); @@ -690,7 +690,7 @@ void MakeThreadLocalVar ( Obj FuncDeclareGlobalName(Obj self, Obj name) { RequireStringRep("DeclareGlobalName", name); - SetIsDeclaredName(GVarName(CONST_CSTR_STRING(name)), 1); + SetIsDeclaredName(GVarName(CONST_CSTR_STRING(name)), TRUE); return 0; } @@ -832,24 +832,29 @@ static Obj FuncAUTO(Obj self, Obj args) UInt gvar; // one global variable UInt i; // loop variable + RequirePlainList(SELF_NAME, args); + RequireDenseList(SELF_NAME, args); + RequireArgumentCondition(SELF_NAME, args, LEN_PLIST(args) >= 2, + "must be a list of length at least 2"); + // get and check the function - func = ELM_LIST( args, 1 ); + func = ELM_PLIST( args, 1 ); RequireFunction(SELF_NAME, func); // get the argument - arg = ELM_LIST( args, 2 ); + arg = ELM_PLIST( args, 2 ); // make the list of function and argument list = NewPlistFromArgs(func, arg); // make the global variables automatic for ( i = 3; i <= LEN_LIST(args); i++ ) { - name = ELM_LIST( args, i ); + name = ELM_PLIST( args, i ); RequireStringRep(SELF_NAME, name); gvar = GVarName( CONST_CSTR_STRING(name) ); SET_ELM_GVAR_LIST( ValGVars, gvar, 0 ); SET_ELM_GVAR_LIST( ExprGVars, gvar, list ); - SetHasExprCopiesFopies(gvar, 1); + SetHasExprCopiesFopies(gvar, TRUE); CHANGED_GVAR_LIST( ExprGVars, gvar ); } @@ -1058,7 +1063,7 @@ static Obj FuncUNB_GVAR(Obj self, Obj gvar) */ typedef struct { Obj * copy; - UInt isFopy; + BOOL isFopy; const Char * name; } StructCopyGVar; @@ -1100,7 +1105,7 @@ void InitCopyGVar ( Panic("no room to record CopyGVar"); } CopyAndFopyGVars[NCopyAndFopyGVars].copy = copy; - CopyAndFopyGVars[NCopyAndFopyGVars].isFopy = 0; + CopyAndFopyGVars[NCopyAndFopyGVars].isFopy = FALSE; CopyAndFopyGVars[NCopyAndFopyGVars].name = name; NCopyAndFopyGVars++; #ifdef HPCGAP @@ -1137,7 +1142,7 @@ void InitFopyGVar ( Panic("no room to record FopyGVar"); } CopyAndFopyGVars[NCopyAndFopyGVars].copy = copy; - CopyAndFopyGVars[NCopyAndFopyGVars].isFopy = 1; + CopyAndFopyGVars[NCopyAndFopyGVars].isFopy = TRUE; CopyAndFopyGVars[NCopyAndFopyGVars].name = name; NCopyAndFopyGVars++; #ifdef HPCGAP @@ -1181,7 +1186,7 @@ void UpdateCopyFopyInfo ( void ) MakeBagPublic(cops); #endif SET_ELM_GVAR_LIST( FopiesGVars, gvar, cops ); - SetHasExprCopiesFopies(gvar, 1); + SetHasExprCopiesFopies(gvar, TRUE); CHANGED_GVAR_LIST( FopiesGVars, gvar ); } } @@ -1193,7 +1198,7 @@ void UpdateCopyFopyInfo ( void ) MakeBagPublic(cops); #endif SET_ELM_GVAR_LIST( CopiesGVars, gvar, cops ); - SetHasExprCopiesFopies(gvar, 1); + SetHasExprCopiesFopies(gvar, TRUE); CHANGED_GVAR_LIST( CopiesGVars, gvar ); } } diff --git a/src/hpc/thread.c b/src/hpc/thread.c index 420074bf93..67f5219fda 100644 --- a/src/hpc/thread.c +++ b/src/hpc/thread.c @@ -975,7 +975,7 @@ static void InterruptCurrentThread(int locked, Stat stat) if (handler) CALL_WITH_CATCH(handler, NEW_PLIST(T_PLIST, 0)); else - ErrorReturnVoid("system interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("system interrupt", 0, 0, 0); if (!locked) pthread_mutex_unlock(thread->lock); } diff --git a/src/io.c b/src/io.c index f17e34e606..eac2600859 100644 --- a/src/io.c +++ b/src/io.c @@ -471,7 +471,7 @@ UInt CloseInput(TypInputFile * input) // if the input stream supports seeking, update its position to // reflect the actual state of things: we may have read and buffered // more bytes than we actually processed - int offset = strlen(input->ptr); + size_t offset = strlen(input->ptr); // check for EOF if (input->ptr[0] == '\377' && input->ptr[1] == '\0') offset = 0; @@ -1513,8 +1513,6 @@ static Obj FuncALL_KEYWORDS(Obj self) ** '%g' the corresponding argument is the address of a T_STRING string ** object which is printed. This is similar to using '%s' to print ** CSTR_STRING(arg), but is safe during garbage collection. -** '%G' the corresponding argument is the address of an Obj which points -** to a string in STRING_REP format which is printed in '%S' format ** '%C' the corresponding argument is the address of an Obj which points ** to a string in STRING_REP format which is printed with C escapes ** '%d' the corresponding argument is a signed integer, which is printed. @@ -1556,7 +1554,7 @@ static inline void FormatOutput( } // handle the case of a missing argument - if (arg1 == 0 && (*p == 's' || *p == 'S' || *p == 'C' || *p == 'I')) { + if (arg1 == 0 && (*p == 's' || *p == 'g' || *p == 'C' || *p == 'I')) { put_a_char(state, '<'); put_a_char(state, 'n'); put_a_char(state, 'u'); @@ -1566,6 +1564,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%d' print an integer @@ -1591,6 +1590,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%s' or '%g' print a string @@ -1650,6 +1650,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%C' print a string with the necessary C escapes @@ -1699,6 +1700,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%I' print an identifier @@ -1742,12 +1744,14 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%c' print a character else if ( *p == 'c' ) { put_a_char(state, (Char)arg1); arg1 = arg2; + arg2 = 0; } // '%%' print a '%' character diff --git a/src/iostream.c b/src/iostream.c index c108389724..3773f4b3a3 100644 --- a/src/iostream.c +++ b/src/iostream.c @@ -30,6 +30,7 @@ #include "io.h" #include "lists.h" #include "modules.h" +#include "plist.h" #include "stringobj.h" #include "sysenv.h" #include "sysfiles.h" @@ -858,13 +859,14 @@ static Obj FuncCREATE_PTY_IOSTREAM(Obj self, Obj dir, Obj prog, Obj args) Char * argv[MAX_ARGS + 2]; UInt i, len; Int pty; - len = LEN_LIST(args); + RequirePlainList(SELF_NAME, args); + len = LEN_PLIST(args); if (len > MAX_ARGS) ErrorQuit("Too many arguments", 0, 0); ConvString(dir); ConvString(prog); for (i = 1; i <= len; i++) { - allargs[i] = ELM_LIST(args, i); + allargs[i] = ELM_PLIST(args, i); ConvString(allargs[i]); } // From here we cannot afford to have a garbage collection @@ -1098,13 +1100,13 @@ FuncExecuteProcess(Obj self, Obj dir, Obj prg, Obj in, Obj out, Obj args) RequireStringRep(SELF_NAME, prg); Int iin = GetSmallInt(SELF_NAME, in); Int iout = GetSmallInt(SELF_NAME, out); - RequireSmallList(SELF_NAME, args); + RequirePlainList(SELF_NAME, args); // create an argument array - for (i = 1; i <= LEN_LIST(args); i++) { + for (i = 1; i <= LEN_PLIST(args); i++) { if (i == 1023) break; - tmp = ELM_LIST(args, i); + tmp = ELM_PLIST(args, i); RequireStringRep(SELF_NAME, tmp); ExecArgs[i] = tmp; } diff --git a/src/julia_gc.c b/src/julia_gc.c index 568b567b1e..f04d51e918 100644 --- a/src/julia_gc.c +++ b/src/julia_gc.c @@ -67,6 +67,8 @@ // should not be enabled by default. // #define VALIDATE_MARKING +// if DISABLE_STACK_SCAN is defined, all stack scanning is disabled +// #define DISABLE_STACK_SCAN // if USE_GAP_INSIDE_JULIA is defined, then some hacks which are needed // to make julia-inside-gap work are disabled. This is mainly for use in @@ -166,13 +168,15 @@ static jl_datatype_t * DatatypeGapObj; static jl_datatype_t * DatatypeSmallBag; static jl_datatype_t * DatatypeLargeBag; +#ifndef DISABLE_STACK_SCAN static jl_task_t * ScannedRootTask; +#endif static size_t MaxPoolObjSize; static int FullGC; static UInt StartTime, TotalTime; -#if !defined(USE_GAP_INSIDE_JULIA) +#if !defined(USE_GAP_INSIDE_JULIA) && !defined(DISABLE_STACK_SCAN) static Bag * GapStackBottom; static jl_task_t * RootTaskOfMainThread; #endif @@ -184,8 +188,10 @@ static TNumFreeFuncBags TabFreeFuncBags[NUM_TYPES]; // HACK: TabMarkFuncBags is accessed by MarkCopyingSubBags in src/objects.c TNumMarkFuncBags TabMarkFuncBags[NUM_TYPES]; +#ifndef DISABLE_STACK_SCAN static TaskInfoTree * TaskStacks; static pthread_mutex_t TaskStacksMutex; +#endif // // global bags @@ -325,6 +331,8 @@ void MarkJuliaWeakRef(void * p, void * ref) } +#ifndef DISABLE_STACK_SCAN + // Overview of conservative stack scanning // // A key aspect of conservative marking is that we need to determine whether a @@ -627,6 +635,8 @@ static void GapTaskScanner(jl_task_t * task, int root_task) } } +#endif // DISABLE_STACK_SCAN + // Julia callback static void PreGCHook(int full) { @@ -653,7 +663,9 @@ static void PreGCHook(int full) // Julia callback static void PostGCHook(int full) { +#ifndef DISABLE_STACK_SCAN ScannedRootTask = 0; +#endif TotalTime += SyTime() - StartTime; #ifdef COLLECT_MARK_CACHE_STATS /* printf("\n>>>Attempts: %ld\nHit rate: %lf\nCollision rate: %lf\n", @@ -758,6 +770,7 @@ void GAP_InitJuliaMemoryInterface(jl_module_t * module, jl_init(); #endif +#ifndef DISABLE_STACK_SCAN if (jl_n_gcthreads > 1) pthread_mutex_init(&TaskStacksMutex, NULL); TaskStacks = TaskInfoTreeMake(); @@ -766,6 +779,7 @@ void GAP_InitJuliaMemoryInterface(jl_module_t * module, // TLS and thus need to be installed after initialization. jl_gc_set_cb_root_scanner(GapRootScanner, 1); jl_gc_set_cb_task_scanner(GapTaskScanner, 1); +#endif jl_gc_set_cb_pre_gc(PreGCHook, 1); jl_gc_set_cb_post_gc(PostGCHook, 1); // jl_gc_enable(0); /// DEBUGGING @@ -816,7 +830,7 @@ void InitBags(UInt initial_size, Bag * stack_bottom) { TotalTime = 0; -#if !defined(USE_GAP_INSIDE_JULIA) +#if !defined(USE_GAP_INSIDE_JULIA) && !defined(DISABLE_STACK_SCAN) // initialize Julia memory interface. Note that this is only necessary // when we run standalone. In contrast, when GAP is loaded from GAP.jl // then GAP.jl invokes `GAP_InitJuliaMemoryInterface` at an appropriate diff --git a/src/lists.c b/src/lists.c index feb5c1584c..969d82573e 100644 --- a/src/lists.c +++ b/src/lists.c @@ -2415,7 +2415,7 @@ static Int CheckInit ( { Int i; // loop variable Int j; // loop variable - Int success = 1; + BOOL success = TRUE; Int fnums[] = { FN_IS_DENSE, FN_IS_NDENSE, FN_IS_HOMOG, FN_IS_NHOMOG, @@ -2453,7 +2453,7 @@ static Int CheckInit ( if ( ClearFiltsTNums[i] == 0 ) { Pr( "#W ClearFiltsListTNums [%s] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2464,7 +2464,7 @@ static Int CheckInit ( if ( HasFiltListTNums[i][fnums[j]] == -1 ) { Pr( "#W HasFiltListTNums [%s] [%s] missing\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; HasFiltListTNums[i][fnums[j]] = 0; } } @@ -2477,7 +2477,7 @@ static Int CheckInit ( if ( SetFiltListTNums[i][fnums[j]] == 0 ) { Pr( "#W SetFiltListTNums [%s] [%s] missing\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } } @@ -2489,7 +2489,7 @@ static Int CheckInit ( if ( ResetFiltListTNums[i][fnums[j]] == 0 ) { Pr( "#W ResetFiltListTNums [%s] [%s] missing\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } } @@ -2508,7 +2508,7 @@ static Int CheckInit ( Pr( "#W ResetFiltListTNums [%s] [%s] failed to reset\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } } @@ -2524,7 +2524,7 @@ static Int CheckInit ( Pr( "#W SetFiltListTNums [%s] [%s] must not change\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } } @@ -2537,7 +2537,7 @@ static Int CheckInit ( if ( ClearFiltsTNums[i]+IMMUTABLE != ClearFiltsTNums[i+IMMUTABLE]) { Pr( "#W ClearFiltsTNums [%s] mismatch between mutable and immutable\n", (Int)TNAM_TNUM(i), 0 ); - success = 0; + success = FALSE; } for ( j = 0; j < ARRAY_SIZE(fnums); j++ ) { @@ -2545,21 +2545,21 @@ static Int CheckInit ( HasFiltListTNums[i+IMMUTABLE][fnums[j]]) { Pr( "#W HasFiltListTNums [%s] [%s] mismatch between mutable and immutable\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } if ( (SetFiltListTNums[i][fnums[j]] | IMMUTABLE) != SetFiltListTNums[i+IMMUTABLE][fnums[j]]) { Pr( "#W SetFiltListTNums [%s] [%s] mismatch between mutable and immutable\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } if ( (ResetFiltListTNums[i][fnums[j]] | IMMUTABLE) != ResetFiltListTNums[i+IMMUTABLE][fnums[j]]) { Pr( "#W ResetFiltListTNums [%s] [%s] mismatch between mutable and immutable\n", (Int)TNAM_TNUM(i), (Int)fnams[j] ); - success = 0; + success = FALSE; } } @@ -2570,43 +2570,43 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ empty -> dense ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_NDENSE] ) { Pr( "#W HasFiltListTNums [%s] [ empty + ndense ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( ! HasFiltListTNums[i][FN_IS_HOMOG] ) { Pr( "#W HasFiltListTNums [%s] [ empty -> homog ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_NHOMOG] ) { Pr( "#W HasFiltListTNums [%s] [ empty + nhomog ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( ! HasFiltListTNums[i][FN_IS_SSORT] ) { Pr( "#W HasFiltListTNums [%s] [ empty -> ssort ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_NSORT] ) { Pr( "#W HasFiltListTNums [%s] [ empty + nsort ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_TABLE] ) { Pr( "#W HasFiltListTNums [%s] [ empty + table ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2615,7 +2615,7 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ dense + ndense ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2624,13 +2624,13 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ ndense + homog ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_TABLE] ) { Pr( "#W HasFiltListTNums [%s] [ ndense + table ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2639,19 +2639,19 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ homog + nhomog ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( ! HasFiltListTNums[i][FN_IS_DENSE] ) { Pr( "#W HasFiltListTNums [%s] [ homog -> dense ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( HasFiltListTNums[i][FN_IS_NDENSE] ) { Pr( "#W HasFiltListTNums [%s] [ homog + ndense ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2660,7 +2660,7 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ nhomog + table ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2669,13 +2669,13 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ table -> homog ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } if ( ! HasFiltListTNums[i][FN_IS_DENSE] ) { Pr( "#W HasFiltListTNums [%s] [ table -> dense ] missing\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } @@ -2684,7 +2684,7 @@ static Int CheckInit ( Pr( "#W HasFiltListTNums [%s] [ ssort + nsort ] illegal\n", (Int)TNAM_TNUM(i), 0); - success = 0; + success = FALSE; } } } diff --git a/src/main.c b/src/main.c index 69d5e3dd95..0d1af37314 100644 --- a/src/main.c +++ b/src/main.c @@ -97,7 +97,6 @@ static void SetupGAPLocation(const char * argv0, char * GAPExecLocation) // In the code below, we keep resetting locBuf, as some of the methods we // try do not promise to leave the buffer empty on a failed return. char locBuf[GAP_PATH_MAX] = ""; - Int4 length = 0; #if defined(__APPLE__) && defined(__MACH__) uint32_t len = sizeof(locBuf); @@ -137,7 +136,7 @@ static void SetupGAPLocation(const char * argv0, char * GAPExecLocation) *GAPExecLocation = 0; // reset buffer after error // now strip the executable name off - length = strlen(GAPExecLocation); + size_t length = strlen(GAPExecLocation); while (length > 0 && GAPExecLocation[length] != '/') { GAPExecLocation[length] = 0; length--; diff --git a/src/objcftl.c b/src/objcftl.c index 472fd33772..83adcc9b13 100644 --- a/src/objcftl.c +++ b/src/objcftl.c @@ -44,6 +44,7 @@ struct CFTLModuleState { #ifdef HPCGAP }; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct CFTLModuleState *CFTLState(void) { return (struct CFTLModuleState *)StateSlotsAtOffset(CFTLStateOffset); diff --git a/src/objset.c b/src/objset.c index d72eaa22c3..1d404a5c8a 100644 --- a/src/objset.c +++ b/src/objset.c @@ -127,7 +127,7 @@ static inline void WRITE_SLOT(Obj container, int slot, Obj elm) static void PrintObjSet(Obj set) { UInt i, size = CONST_ADDR_WORD(set)[OBJSET_SIZE]; - Int comma = 0; + BOOL comma = FALSE; Pr("OBJ_SET([ ", 0, 0); for (i=0; i < size; i++) { Obj obj = READ_SLOT(set, i); @@ -135,7 +135,7 @@ static void PrintObjSet(Obj set) if (comma) { Pr(", ", 0, 0); } else { - comma = 1; + comma = TRUE; } PrintObj(obj); } @@ -146,7 +146,7 @@ static void PrintObjSet(Obj set) static void PrintObjMap(Obj map) { UInt i, size = CONST_ADDR_WORD(map)[OBJSET_SIZE]; - Int comma = 0; + BOOL comma = FALSE; Pr("OBJ_MAP([ ", 0, 0); for (i=0; i < size; i++) { Obj obj = READ_SLOT(map, i * 2); @@ -154,7 +154,7 @@ static void PrintObjMap(Obj map) if (comma) { Pr(", ", 0, 0); } else { - comma = 1; + comma = TRUE; } PrintObj(obj); Pr(", ", 0, 0); diff --git a/src/opers.cc b/src/opers.cc index ce86f7a99d..e2e431f8c9 100644 --- a/src/opers.cc +++ b/src/opers.cc @@ -755,7 +755,8 @@ static Obj FuncWITH_HIDDEN_IMPS_FLAGS(Obj self, Obj flags) #ifdef HPCGAP RegionWriteLock(REGION(WITH_HIDDEN_IMPS_FLAGS_CACHE)); #endif - Int changed, i, lastand, stop; + BOOL changed; + Int i, lastand, stop; Int hidden_imps_length = LEN_PLIST(HIDDEN_IMPS) / 2; Int hash = INT_INTOBJ(FuncHASH_FLAGS(0, flags)) % HIDDEN_IMPS_CACHE_LENGTH; @@ -777,18 +778,18 @@ static Obj FuncWITH_HIDDEN_IMPS_FLAGS(Obj self, Obj flags) #ifdef COUNT_OPERS WITH_HIDDEN_IMPS_MISS++; #endif - changed = 1; + changed = TRUE; lastand = 0; - while(changed) + while (changed) { - changed = 0; + changed = FALSE; for (i = hidden_imps_length, stop = lastand; i > stop; i--) { if( IS_SUBSET_FLAGS(with, ELM_PLIST(HIDDEN_IMPS, i*2)) && !IS_SUBSET_FLAGS(with, ELM_PLIST(HIDDEN_IMPS, i*2-1)) ) { with = FuncAND_FLAGS(0, with, ELM_PLIST(HIDDEN_IMPS, i*2-1)); - changed = 1; + changed = TRUE; stop = 0; lastand = i; } @@ -847,7 +848,8 @@ static Obj FuncWITH_IMPS_FLAGS(Obj self, Obj flags) #ifdef HPCGAP RegionWriteLock(REGION(IMPLICATIONS_SIMPLE)); #endif - Int changed, lastand, i, j, stop, imps_length; + BOOL changed; + Int lastand, i, j, stop, imps_length; Int hash = INT_INTOBJ(FuncHASH_FLAGS(0, flags)) % IMPS_CACHE_LENGTH; Obj cacheval; Obj with = flags; @@ -886,11 +888,11 @@ static Obj FuncWITH_IMPS_FLAGS(Obj self, Obj flags) // the other implications have to be considered in a loop imps_length = LEN_PLIST(IMPLICATIONS_COMPOSED); - changed = 1; + changed = TRUE; lastand = imps_length+1; while(changed) { - changed = 0; + changed = FALSE; for (i = 1, stop = lastand; i < stop; i++) { imp = ELM_PLIST(IMPLICATIONS_COMPOSED, i); @@ -898,7 +900,7 @@ static Obj FuncWITH_IMPS_FLAGS(Obj self, Obj flags) !IS_SUBSET_FLAGS(with, ELM_PLIST(imp, 1)) ) { with = FuncAND_FLAGS(0, with, ELM_PLIST(imp, 1)); - changed = 1; + changed = TRUE; stop = imps_length+1; lastand = i; } @@ -1607,7 +1609,6 @@ static UInt CacheMissStatistics[CACHE_SIZE + 1][7]; template static Obj GetMethodCached(Obj cacheBag, Int prec, Obj ids[]) { - UInt typematch; Obj * cache; Obj method = 0; UInt i; @@ -1625,11 +1626,11 @@ static Obj GetMethodCached(Obj cacheBag, Int prec, Obj ids[]) for (i = target; i < cacheEntrySize * CACHE_SIZE; i += cacheEntrySize) { if (cache[i + 1] == INTOBJ_INT(prec)) { - typematch = 1; + BOOL typematch = TRUE; // This loop runs over the arguments, should be compiled away for (int j = 0; j < n; j++) { if (cache[i + j + 2] != ids[j]) { - typematch = 0; + typematch = FALSE; break; } } diff --git a/src/permutat.cc b/src/permutat.cc index ccd5cfe976..7f7bb034a2 100644 --- a/src/permutat.cc +++ b/src/permutat.cc @@ -113,13 +113,12 @@ DECL_MODULE_STATE Obj TmpPerm; #endif -static UInt1 * UseTmpPerm(UInt size) +static void UseTmpPerm(UInt size) { if (TmpPerm == (Obj)0) TmpPerm = NewBag(T_PERM4, size); else if (SIZE_BAG(TmpPerm) < size) ResizeBag(TmpPerm, size); - return (UInt1 *)(ADDR_OBJ(TmpPerm) + 1); } template diff --git a/src/plist.c b/src/plist.c index c05f9b147a..a9b6d0f7e5 100644 --- a/src/plist.c +++ b/src/plist.c @@ -255,19 +255,19 @@ static Int KTNumPlist(Obj list, Obj * famfirst) // look at the first element elm = ELM_PLIST( list, 1 ); if ( elm == 0 ) { - isDense = 0; + isDense = FALSE; } #ifdef HPCGAP else if ( !CheckReadAccess(elm) ) { - isHom = 0; - areMut = 1; - isTable = 0; + isHom = FALSE; + areMut = TRUE; + isTable = FALSE; } #endif else if (TEST_OBJ_FLAG(elm, OBJ_FLAG_TESTING)) { - isHom = 0; + isHom = FALSE; areMut = IS_PLIST_MUTABLE(elm); - isTable = 0; + isTable = FALSE; } else { #ifdef HPCGAP @@ -285,20 +285,20 @@ static Int KTNumPlist(Obj list, Obj * famfirst) family = FAMILY_TYPE( typeObj ); ktnumFirst = 0; } - isHom = 1; + isHom = TRUE; areMut = IS_MUTABLE_OBJ(elm); // if entry is a homogeneous list this might be a table or list if (ktnumFirst >= T_PLIST_HOM) { - isTable = 1; - isRect = 1; + isTable = TRUE; + isRect = TRUE; len = LEN_PLIST(elm); } else if (ktnumFirst == 0 && IS_HOMOG_LIST(elm)) { - isTable = 1; + isTable = TRUE; // only handle small lists as rectangular if (IS_SMALL_LIST(elm)) { - isRect = 1; + isRect = TRUE; len = LEN_LIST(elm); } } @@ -319,45 +319,45 @@ static Int KTNumPlist(Obj list, Obj * famfirst) for ( ; isDense && (isHom || ! areMut) && i <= lenList; i++ ) { elm = ELM_PLIST( list, i ); if ( elm == 0 ) { - isDense = 0; + isDense = FALSE; } #ifdef HPCGAP else if ( !CheckReadAccess(elm) ) { - isHom = 0; - areMut = 1; - isTable = 0; - isRect = 0; + isHom = FALSE; + areMut = TRUE; + isTable = FALSE; + isRect = FALSE; } #endif else if (TEST_OBJ_FLAG(elm, OBJ_FLAG_TESTING)) { - isHom = 0; + isHom = FALSE; areMut = (areMut || IS_PLIST_MUTABLE(elm)); - isTable = 0; - isRect = 0; + isTable = FALSE; + isRect = FALSE; } else { if (isHom) { loopTypeObj = TYPE_OBJ(elm); if ( loopTypeObj != typeObj && FAMILY_TYPE(loopTypeObj) != family ) { - isHom = 0; - isTable = 0; - isRect = 0; + isHom = FALSE; + isTable = FALSE; + isRect = FALSE; } if ( isTable ) { // check IS_PLIST first, as it is much cheaper if (IS_PLIST(elm)) { if (isRect && LEN_PLIST(elm) != len) { - isRect = 0; + isRect = FALSE; } } else if (IS_SMALL_LIST(elm)) { if (isRect && LEN_LIST(elm) != len) { - isRect = 0; + isRect = FALSE; } } else { - isTable = 0; - isRect = 0; + isTable = FALSE; + isRect = FALSE; } } } @@ -367,13 +367,13 @@ static Int KTNumPlist(Obj list, Obj * famfirst) // if we know it is not dense if (knownNDense) - isDense = 0; + isDense = FALSE; // otherwise if we don't know that it IS dense else if (!knownDense) for ( ; isDense && i <= lenList; i++ ) { elm = ELM_PLIST( list, i ); if ( elm == 0 ) { - isDense = 0; + isDense = FALSE; } } @@ -403,13 +403,13 @@ static Int KTNumPlist(Obj list, Obj * famfirst) else if (IS_FFE(ELM_PLIST(list,1))) { FF fld = FLD_FFE(ELM_PLIST(list,1)); - UInt isFFE = 1; + BOOL isFFE = TRUE; for (i = 2; i <= lenList; i++) { x = ELM_PLIST(list,i); if (!IS_FFE(x) || FLD_FFE(x) != fld) { - isFFE = 0; + isFFE = FALSE; break; } } @@ -446,8 +446,8 @@ static Int KTNumHomPlist(Obj list) Obj elm, x; // one element of Int i; // loop variable Int res; // result - Int isSSort; // list is (known to be) SSorted - Int isNSort; // list is (known to be) non-sorted + BOOL isSSort; // list is (known to be) SSorted + BOOL isNSort; // list is (known to be) non-sorted #ifdef HPCGAP if (!CheckWriteAccess(list)) { @@ -486,13 +486,13 @@ static Int KTNumHomPlist(Obj list) if (IS_FFE(elm)) { FF fld = FLD_FFE(ELM_PLIST(list,1)); - UInt isFFE = 1; + BOOL isFFE = TRUE; for (i = 2; i <= lenList; i++) { x = ELM_PLIST(list,i); if (!IS_FFE(x) || FLD_FFE(x) != fld) { - isFFE = 0; + isFFE = FALSE; break; } } @@ -509,10 +509,10 @@ static Int KTNumHomPlist(Obj list) if (!HAS_FILT_LIST(list, FN_IS_TABLE )) { if ( IS_HOMOG_LIST(elm) ) { - isTable = 1; + isTable = TRUE; if (IS_PLIST(elm)) { - isRect = 1; + isRect = TRUE; len = LEN_PLIST(elm); } } @@ -528,7 +528,7 @@ static Int KTNumHomPlist(Obj list) } else { - isTable = 1; + isTable = TRUE; isRect = HAS_FILT_LIST(list, FN_IS_RECT); } if (isTable && !isRect) @@ -1961,10 +1961,10 @@ static BOOL IsSSortPlist(Obj list) Int lenList; Obj elm1; Obj elm2; - Int areMut; + BOOL areMut; Int i; Obj fam=0; // initialize to help compiler - Int isHom; + BOOL isHom; // get the length lenList = LEN_PLIST( list ); @@ -1987,10 +1987,10 @@ static BOOL IsSSortPlist(Obj list) if (!SyInitializing) { fam = FAMILY_OBJ(elm1); - isHom = 1; + isHom = TRUE; } else - isHom = 0; + isHom = FALSE; // loop over the other elements for ( i = 2; i <= lenList; i++ ) { @@ -2047,10 +2047,10 @@ static BOOL IsSSortPlistDense(Obj list) Int lenList; Obj elm1; Obj elm2; - Int areMut; + BOOL areMut; Int i; Obj fam=0; // initialize to help compiler - Int isHom; + BOOL isHom; // get the length lenList = LEN_PLIST( list ); @@ -2071,10 +2071,10 @@ static BOOL IsSSortPlistDense(Obj list) if (!SyInitializing) { fam = FAMILY_OBJ(elm1); - isHom = 1; + isHom = TRUE; } else - isHom = 0; + isHom = FALSE; // loop over the other elements for ( i = 2; i <= lenList; i++ ) { @@ -2453,7 +2453,7 @@ static Obj FuncIsRectangularTablePlist(Obj self, Obj plist) Obj len; UInt lenlist; UInt i; - UInt hasMut = 0; + BOOL hasMut = FALSE; Obj elm; assert(!HAS_FILT_LIST(plist, FN_IS_RECT)); diff --git a/src/profile.c b/src/profile.c index c6c193adaa..bfd26913cb 100644 --- a/src/profile.c +++ b/src/profile.c @@ -430,7 +430,7 @@ void InformProfilingThatThisIsAForkedGAP(void) char filenamecpy[GAP_PATH_MAX]; // Allow 20 characters to allow space for .%d.gz const int SUPPORTED_PATH_LEN = GAP_PATH_MAX - 20; - if(strlen(profileState.filename) > SUPPORTED_PATH_LEN) { + if (strlen(profileState.filename) > SUPPORTED_PATH_LEN) { Panic("Filename can be at most %d character when forking", SUPPORTED_PATH_LEN); } if (endsWithgz(profileState.filename)) { diff --git a/src/read.c b/src/read.c index 1c12349574..437302919e 100644 --- a/src/read.c +++ b/src/read.c @@ -319,7 +319,7 @@ GAP_STATIC_ASSERT(sizeof(LHSRef) <= 8, "LHSRef is too big"); /**************************************************************************** ** */ -static UInt EvalRef(ReaderState * rs, const LHSRef ref, Int needExpr) +static UInt EvalRef(ReaderState * rs, const LHSRef ref, BOOL needExpr) { TRY_IF_NO_ERROR { @@ -643,7 +643,7 @@ static void ReadReferenceModifiers(ReaderState * rs, TypSymbolSet follow) // read one or more selectors while (IS_IN(rs->s.Symbol, S_LPAREN | S_LBRACK | S_LBRACE | S_DOT)) { LHSRef ref = ReadSelector(rs, follow, level); - level = EvalRef(rs, ref, 1); + level = EvalRef(rs, ref, TRUE); } } @@ -864,13 +864,13 @@ static void ReadCallVarAss(ReaderState * rs, TypSymbolSet follow, Char mode) while (IS_IN(rs->s.Symbol, S_LPAREN | S_LBRACK | S_LBRACE | S_DOT)) { // so the prefix was a reference - UInt level = EvalRef(rs, ref, 1); + UInt level = EvalRef(rs, ref, TRUE); ref = ReadSelector(rs, follow, level); } // if we need a reference if (mode == 'r' || (mode == 'x' && rs->s.Symbol != S_ASSIGN)) { - Int needExpr = mode == 'r' || !IS_IN(rs->s.Symbol, S_SEMICOLON); + BOOL needExpr = mode == 'r' || !IS_IN(rs->s.Symbol, S_SEMICOLON); EvalRef(rs, ref, needExpr); } @@ -2065,7 +2065,7 @@ static void ReadFor(ReaderState * rs, TypSymbolSet follow) // volatile LHSRef ref = ReadVar(rs, follow); if (ref.type != R_INVALID) - EvalRef(rs, ref, 1); + EvalRef(rs, ref, TRUE); CheckUnboundGlobal(rs, ref); // 'in' diff --git a/src/records.c b/src/records.c index e19befec0d..76546db9c1 100644 --- a/src/records.c +++ b/src/records.c @@ -64,7 +64,7 @@ static void NewRNamCallback(SymbolTable * symtab, UInt id, Obj name) */ UInt RNamName(const Char * name) { - UInt len = strlen(name); + size_t len = strlen(name); if (len > 1023) { // Note: We can't pass 'name' here, as it might get moved by garbage collection ErrorQuit("Record names must consist of at most 1023 characters", 0, 0); diff --git a/src/scanner.c b/src/scanner.c index cc607b7582..37e642bb77 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -71,7 +71,7 @@ static void SyntaxErrorOrWarning(ScannerState * s, // error is reported, so the pretty-printed context would leak // a literal 0xFF byte to *errout* with no caret to anchor it. const char * line = GetInputLineBuffer(s->input); - const UInt len = strlen(line); + const size_t len = strlen(line); const int line_is_sentinel = (len == 0 || line[0] == '\377'); if (!line_is_sentinel) { if (line[len-1] != '\n') diff --git a/src/sortbase.h b/src/sortbase.h index 069c97672c..4dfd9afefc 100644 --- a/src/sortbase.h +++ b/src/sortbase.h @@ -164,11 +164,11 @@ static inline void PREFIXNAME(Sort3)(SORT_FUNC_ARGS, Int a, Int b, Int c) { * to be moved, and store the partition_point in the argument * partition_point */ -static inline Int PREFIXNAME(Partition)(SORT_FUNC_ARGS, Int start, Int end, +static inline BOOL PREFIXNAME(Partition)(SORT_FUNC_ARGS, Int start, Int end, Int *partition_point) { Int left = start; Int right = end; - Int first_pass = 1; + BOOL first_pass = TRUE; SORT_CREATE_LOCAL(pivot); PREFIXNAME(Sort3)(SORT_ARGS, start, start / 2 + end / 2, end); @@ -198,7 +198,7 @@ static inline Int PREFIXNAME(Partition)(SORT_FUNC_ARGS, Int start, Int end, *partition_point = left; return first_pass; } - first_pass = 0; + first_pass = FALSE; SWAP_INDICES(SORT_ARGS, left, right); left++; @@ -275,7 +275,8 @@ static void PREFIXNAME(CheckBadPivot)(SORT_FUNC_ARGS, Int start, Int end, Int pi static void PREFIXNAME(QuickSort)(SORT_FUNC_ARGS, Int start, Int end, Int depth) { - Int pivot, first_pass; + Int pivot; + BOOL first_pass; if (end - start < 24) { PREFIXNAME(Insertion)(SORT_ARGS, start, end); diff --git a/src/stats.c b/src/stats.c index fb2de23a1b..7ed53a74ce 100644 --- a/src/stats.c +++ b/src/stats.c @@ -392,7 +392,7 @@ static ALWAYS_INLINE ExecStatus ExecForHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -435,7 +435,7 @@ static ALWAYS_INLINE ExecStatus ExecForHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -530,7 +530,7 @@ static ALWAYS_INLINE ExecStatus ExecForRangeHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -666,7 +666,7 @@ static ALWAYS_INLINE ExecStatus ExecWhileHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -737,7 +737,7 @@ static ALWAYS_INLINE ExecStatus ExecRepeatHelper(Stat stat, UInt nr) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -952,7 +952,7 @@ static ExecStatus ExecReturnObj(Stat stat) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -980,7 +980,7 @@ static ExecStatus ExecReturnVoid(Stat stat) #if !defined(HAVE_SIGNAL) // test for an interrupt if ( HaveInterrupt() ) { - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); } #endif @@ -1027,7 +1027,7 @@ UInt TakeInterrupt( void ) { if (HaveInterrupt()) { UnInterruptExecStat(); - ErrorReturnVoid("user interrupt", 0, 0, "you can 'return;'"); + ErrorReturnVoid("user interrupt", 0, 0, 0); return 1; } return 0; @@ -1067,12 +1067,12 @@ static ExecStatus ExecIntrStat(Stat stat) if (printError) { ErrorReturnVoid("reached the pre-set memory limit\n" "(change it with the -o command line option)", - 0, 0, "you can 'return;'"); + 0, 0, 0); } } else #endif - ErrorReturnVoid( "user interrupt", 0, 0, "you can 'return;'" ); + ErrorReturnVoid("user interrupt", 0, 0, 0); #endif // continue at the interrupted statement diff --git a/src/streams.c b/src/streams.c index d36d67eb46..4750f3dec2 100644 --- a/src/streams.c +++ b/src/streams.c @@ -517,8 +517,7 @@ static Obj FuncLOG_TO(Obj self, Obj filename) { RequireStringRep(SELF_NAME, filename); if ( ! OpenLog( CONST_CSTR_STRING(filename) ) ) { - ErrorReturnVoid("LogTo: cannot log to %g", (Int)filename, 0, - "you can 'return;'"); + ErrorReturnVoid("LogTo: cannot log to %g", (Int)filename, 0, 0); return False; } return True; @@ -533,8 +532,7 @@ static Obj FuncLOG_TO_STREAM(Obj self, Obj stream) { RequireOutputStream(SELF_NAME, stream); if ( ! OpenLogStream(stream) ) { - ErrorReturnVoid("LogTo: cannot log to stream", 0, 0, - "you can 'return;'"); + ErrorReturnVoid("LogTo: cannot log to stream", 0, 0, 0); return False; } return True; @@ -578,8 +576,7 @@ static Obj FuncINPUT_LOG_TO(Obj self, Obj filename) { RequireStringRep(SELF_NAME, filename); if ( ! OpenInputLog( CONST_CSTR_STRING(filename) ) ) { - ErrorReturnVoid("InputLogTo: cannot log to %g", (Int)filename, 0, - "you can 'return;'"); + ErrorReturnVoid("InputLogTo: cannot log to %g", (Int)filename, 0, 0); return False; } return True; @@ -594,8 +591,7 @@ static Obj FuncINPUT_LOG_TO_STREAM(Obj self, Obj stream) { RequireOutputStream(SELF_NAME, stream); if ( ! OpenInputLogStream(stream) ) { - ErrorReturnVoid("InputLogTo: cannot log to stream", 0, 0, - "you can 'return;'"); + ErrorReturnVoid("InputLogTo: cannot log to stream", 0, 0, 0); return False; } return True; @@ -639,8 +635,7 @@ static Obj FuncOUTPUT_LOG_TO(Obj self, Obj filename) { RequireStringRep(SELF_NAME, filename); if ( ! OpenOutputLog( CONST_CSTR_STRING(filename) ) ) { - ErrorReturnVoid("OutputLogTo: cannot log to %g", (Int)filename, 0, - "you can 'return;'"); + ErrorReturnVoid("OutputLogTo: cannot log to %g", (Int)filename, 0, 0); return False; } return True; @@ -655,8 +650,7 @@ static Obj FuncOUTPUT_LOG_TO_STREAM(Obj self, Obj stream) { RequireOutputStream(SELF_NAME, stream); if ( ! OpenOutputLogStream(stream) ) { - ErrorReturnVoid("OutputLogTo: cannot log to stream", 0, 0, - "you can 'return;'"); + ErrorReturnVoid("OutputLogTo: cannot log to stream", 0, 0, 0); return False; } return True; diff --git a/src/stringobj.h b/src/stringobj.h index 9b28f61107..4071c06365 100644 --- a/src/stringobj.h +++ b/src/stringobj.h @@ -358,18 +358,6 @@ EXPORT_INLINE Obj MakeImmStringWithLen(const char * buf, size_t len) } -/**************************************************************************** -** -*F C_NEW_STRING( , , ) . . . . . . create GAP string -** -** This macro is deprecated and only provided for backwards compatibility -** with some package kernel extensions. Use 'MakeStringWithLen' and -** 'MakeImmStringWithLen' instead. -*/ -#define C_NEW_STRING(string,len,cstr) \ - string = MakeStringWithLen( (cstr), (len) ) - - /**************************************************************************** ** *F AppendCStr( , , ) . . append data in a buffer to a string diff --git a/src/sysfiles.c b/src/sysfiles.c index c2cf83db00..98aeb14694 100644 --- a/src/sysfiles.c +++ b/src/sysfiles.c @@ -191,10 +191,7 @@ static ssize_t echoandcheck(int fid, const char *buf, size_t count) ** *F SyGAPCRC( ) . . . . . . . . . . . . . . . . . . crc of a GAP file ** -** This function should be clever and handle white spaces and comments but -** one has to make certain that such characters are not ignored in strings. -** -** This function *never* returns a 0 unless an error occurred. +** This function returns 0 for missing or unreadable files. */ static const UInt4 syCcitt32[ 256 ] = { @@ -248,9 +245,9 @@ Int4 SyGAPCRC( const Char * name ) UInt4 crc; UInt4 old; UInt4 new; - Int4 ch; + Int ch; Int fid; - Int seen_nl; + BOOL seen_nl; // the CRC of a non existing file is 0 fid = SyFopen(name, "r", TRUE); @@ -260,7 +257,7 @@ Int4 SyGAPCRC( const Char * name ) // read in the file byte by byte and compute the CRC crc = 0x12345678L; - seen_nl = 0; + seen_nl = FALSE; while ( (ch = SyGetch(fid) )!= EOF ) { if ( ch == '\377' || ch == '\n' || ch == '\r' ) @@ -269,25 +266,22 @@ Int4 SyGAPCRC( const Char * name ) if ( seen_nl ) continue; else - seen_nl = 1; + seen_nl = TRUE; } else - seen_nl = 0; - old = (crc >> 8) & 0x00FFFFFFL; - new = syCcitt32[ ( (UInt4)( crc ^ ch ) ) & 0xff ]; + seen_nl = FALSE; + old = crc >> 8; + new = syCcitt32[(crc ^ ch) & 0xff]; crc = old ^ new; } - if ( crc == 0 ) { - crc = 1; - } // and close it again SyFclose( fid ); - // Emulate a signed shift: - if (crc & 0x80000000L) - return (Int4) ((crc >> 4) | 0xF0000000L); - else - return (Int4) (crc >> 4); + + // Emulate a signed shift (the C compiler does not specify whether right + // shifts preserve signs or not; it seems more or less all compilers in + // active use these days do, but better safe than sorry) + return ((Int)((crc >> 4) ^ 0x08000000U)) - 0x08000000; } @@ -320,35 +314,36 @@ static Obj FuncCrcString(Obj self, Obj str) UInt4 new; UInt4 i, len; const Char *ptr; - Int4 ch; - Int seen_nl; + Int ch; + BOOL seen_nl; RequireStringRep(SELF_NAME, str); ptr = CONST_CSTR_STRING(str); len = GET_LEN_STRING(str); crc = 0x12345678L; - seen_nl = 0; + seen_nl = FALSE; for (i = 0; i < len; i++) { - ch = (Int4)(ptr[i]); + ch = (Int)(ptr[i]); if ( ch == '\377' || ch == '\n' || ch == '\r' ) ch = '\n'; if ( ch == '\n' ) { if ( seen_nl ) continue; else - seen_nl = 1; + seen_nl = TRUE; } else - seen_nl = 0; - old = (crc >> 8) & 0x00FFFFFFL; - new = syCcitt32[ ( (UInt4)( crc ^ ch ) ) & 0xff ]; + seen_nl = FALSE; + old = crc >> 8; + new = syCcitt32[(crc ^ ch) & 0xff]; crc = old ^ new; } - if ( crc == 0 ) { - crc = 1; - } - return INTOBJ_INT(((Int4) crc) >> 4); + + // Emulate a signed shift (the C compiler does not specify whether right + // shifts preserve signs or not; it seems more or less all compilers in + // active use these days do, but better safe than sorry) + return INTOBJ_INT(((Int)((crc >> 4) ^ 0x08000000U)) - 0x08000000); } // Get OS Kernel version. Used to discover if GAP is running inside @@ -981,7 +976,7 @@ static UInt syLastIntr; // time of the last interrupt #ifdef HAVE_LIBREADLINE -static Int doingReadline; +static BOOL doingReadline; #endif static void syAnswerIntr(int signr) @@ -1207,7 +1202,7 @@ void SyFputs ( const Char * line, Int fid ) { - UInt i; + size_t i; // if outputting to the terminal compute the cursor position and length if ( fid == 1 || fid == 3 ) { @@ -2089,9 +2084,9 @@ static Char * readlineFgets(Char * line, UInt length, Int fid, UInt block) rl_event_hook = (OnCharReadHookActiveCheck()) ? charreadhook_rl : 0; #endif // now do the real work - doingReadline = 1; + doingReadline = TRUE; rlres = readline(STATE(Prompt)); - doingReadline = 0; + doingReadline = FALSE; // we get a NULL pointer on EOF, say by pressing Ctr-d if (!rlres) { if (!SyCTRD) { diff --git a/src/sysfiles.h b/src/sysfiles.h index 046ea30b68..96799788ee 100644 --- a/src/sysfiles.h +++ b/src/sysfiles.h @@ -23,8 +23,7 @@ ** *F SyGAPCRC( ) . . . . . . . . . . . . . . . . . . crc of a GAP file ** -** This function should be clever and handle white spaces and comments but -** one has to certain that such characters are not ignored in strings. +** This function returns 0 for missing or unreadable files. */ Int4 SyGAPCRC(const Char * name); diff --git a/src/sysstr.h b/src/sysstr.h index c9173e5c8e..72ed52e687 100644 --- a/src/sysstr.h +++ b/src/sysstr.h @@ -23,8 +23,8 @@ ** *F IsAlpha( ) . . . . . . . . . . . . . is a character a normal letter ** -** 'IsAlpha' returns 1 if its character argument is a character from the -** range 'a..zA..Z' and 0 otherwise. +** 'IsAlpha' returns TRUE if its character argument is a character from the +** range 'a..zA..Z' and FALSE otherwise. */ #define IsAlpha(ch) (isalpha((unsigned int)ch)) @@ -33,8 +33,8 @@ ** *F IsDigit( ) . . . . . . . . . . . . . . . . . is a character a digit ** -** 'IsDigit' returns 1 if its character argument is a digit from the range -** '0..9' and 0 otherwise. +** 'IsDigit' returns TRUE if its character argument is a digit from the +** range '0..9' and FALSE otherwise. */ #define IsDigit(ch) (isdigit((unsigned int)ch)) @@ -43,8 +43,9 @@ ** *F IsIdent( ) . . . . . . . . is a character valid in a GAP identifier ** -** 'IsIdent' returns 1 if its character argument can be used unquoted inside -** a GAP identifier, i.e., is in the range 'a..zA..Z0-9_@', and 0 otherwise. +** 'IsIdent' returns TRUE if its character argument can be used unquoted +** inside a GAP identifier, i.e., is in the range 'a..zA..Z0-9_@', and +** FALSE otherwise. */ EXPORT_INLINE BOOL IsIdent(char ch) { diff --git a/src/tietze.c b/src/tietze.c index d86049a0ea..fa2ced13fa 100644 --- a/src/tietze.c +++ b/src/tietze.c @@ -289,7 +289,7 @@ static Obj FuncTzReplaceGens(Obj self, Obj tietze) Int total; // total length of relators Int old, new; // generators or inverses Int leng, reduced; // relator lengths - Int altered; // flag + BOOL altered; // flag Int i, j; // loop variables // check the Tietze stack @@ -317,7 +317,7 @@ static Obj FuncTzReplaceGens(Obj self, Obj tietze) rel = ptRels[i]; pt2 = ptRel = ADDR_OBJ( rel ); leng = INT_INTOBJ( ptLens[i] ); - altered = 0; + altered = FALSE; // don't change a square relator defining a valid involution if (ELM_PLIST(flags, i) == INTOBJ_INT(3) && leng == 2 && @@ -336,16 +336,18 @@ static Obj FuncTzReplaceGens(Obj self, Obj tietze) new = INT_INTOBJ( ptInvs[-old] ); if ( ! new ) { - altered = 1; + altered = TRUE; continue; // loop over j } if ( pt2 > ptRel && *pt2 == ptInvs[new] ) { - altered = 1; + altered = TRUE; --pt2; } else { - if ( new != old ) { altered = 1; } + if ( new != old ) { + altered = TRUE; + } *++pt2 = INTOBJ_INT( new ); } } @@ -973,9 +975,8 @@ static Obj FuncTzSearchC(Obj self, Obj args) Int n, m; // subword lengths Int count; // number of altered relators Int i, j, jj, x, y; // loop variables - Int lasty; // flag - Int altered; // flag - Int equal; // flag + Int lasty; // previous value of y + BOOL altered; // flag // get and check arguments if ( ! IS_SMALL_LIST(args) || 4 < LEN_LIST(args) || LEN_LIST(args) < 3 ) { @@ -1036,7 +1037,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) ErrorQuit(" must be false or true", 0, 0); } } - equal = ( equ == True ); + const BOOL equal = ( equ == True ); // Skip relators of inconvenient lengths or with inconvenient flags, // and return if the remaining range is empty @@ -1072,8 +1073,9 @@ static Obj FuncTzSearchC(Obj self, Obj args) inv = 109109 * inv; // initialize the hash table - for ( i = 0; i < 2048; i++ ) - ((UInt4 *)keys1)[i] = ((UInt4 *)keys2)[i] = ((UInt4 *)keys3)[i] = 0; + memset(keys1, 0, sizeof(keys1)); + memset(keys2, 0, sizeof(keys2)); + memset(keys3, 0, sizeof(keys3)); // loop over the Tietze relators, starting at position pos1 for ( y = pos1; y < numrels; ) { @@ -1130,7 +1132,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) ylen = INT_INTOBJ( ptLens[y] ); yflag = INT_INTOBJ( ptFlags[y] ); ylen1 = ylen - 1; - altered = 0; + altered = FALSE; // Loop to the next relator, if the current relator is too short if ( y > lasty @@ -1238,7 +1240,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) } ptFlags[y] = INTOBJ_INT( newflag ); - altered = 1; + altered = TRUE; ++count; break; // loop over i } @@ -1285,7 +1287,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) ptFlags = ADDR_OBJ( flags); ptInvs = ADDR_OBJ( invs ) + (numgens + 1); - altered = 1; + altered = TRUE; ++count; --y; break; // loop over i @@ -1331,7 +1333,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) } ptFlags[y] = INTOBJ_INT( newflag ); - altered = 1; + altered = TRUE; ++count; break; // loop over i } @@ -1378,7 +1380,7 @@ static Obj FuncTzSearchC(Obj self, Obj args) ptFlags = ADDR_OBJ( flags); ptInvs = ADDR_OBJ( invs ) + numgens + 1; - altered = 1; + altered = TRUE; ++count; --y; break; // loop over i diff --git a/src/trans.cc b/src/trans.cc index 891a858598..557e7b02a5 100644 --- a/src/trans.cc +++ b/src/trans.cc @@ -3865,7 +3865,8 @@ Obj OnSetsTrans(Obj set, Obj f) const UInt4 * ptf4; UInt deg; Obj * ptres, tmp, res; - UInt i, isint, k; + UInt i, k; + BOOL isInt; // copy the list into a mutable plist, which we will then modify in place res = PLAIN_LIST_COPY(set); @@ -3876,7 +3877,7 @@ Obj OnSetsTrans(Obj set, Obj f) ptf2 = CONST_ADDR_TRANS2(f); deg = DEG_TRANS2(f); // loop over the entries of the tuple - isint = 1; + isInt = TRUE; for (i = 1; i <= len; i++, ptres++) { tmp = *ptres; if (IS_POS_INTOBJ(tmp)) { @@ -3886,7 +3887,7 @@ Obj OnSetsTrans(Obj set, Obj f) } } else { - isint = 0; + isInt = FALSE; tmp = POW(tmp, f); ptres = ADDR_OBJ(res) + i; ptf2 = CONST_ADDR_TRANS2(f); @@ -3900,7 +3901,7 @@ Obj OnSetsTrans(Obj set, Obj f) deg = DEG_TRANS4(f); // loop over the entries of the tuple - isint = 1; + isInt = TRUE; for (i = 1; i <= len; i++, ptres++) { tmp = *ptres; if (IS_POS_INTOBJ(tmp)) { @@ -3910,7 +3911,7 @@ Obj OnSetsTrans(Obj set, Obj f) } } else { - isint = 0; + isInt = FALSE; tmp = POW(tmp, f); ptres = ADDR_OBJ(res) + i; ptf4 = CONST_ADDR_TRANS4(f); @@ -3921,7 +3922,7 @@ Obj OnSetsTrans(Obj set, Obj f) } // sort the result and remove dups - if (isint) { + if (isInt) { SortPlistByRawObj(res); REMOVE_DUPS_PLIST_INTOBJ(res); RetypeBagSM(res, T_PLIST_CYC_SSORT); diff --git a/src/vec8bit.c b/src/vec8bit.c index 9137672f8c..83f34e0657 100644 --- a/src/vec8bit.c +++ b/src/vec8bit.c @@ -60,6 +60,10 @@ RequireArgumentCondition(funcname, op, IS_MAT8BIT_REP(op), \ "must belong to Is8BitMatrixRep") +#define RequireFFE(funcname, op) \ + RequireArgumentCondition(funcname, op, IS_FFE(op), \ + "must be a finite field element") + /**************************************************************************** ** *F IS_VEC8BIT_REP( ) . . . check that is in 8bit GFQ vector rep @@ -815,6 +819,7 @@ static UInt LcmDegree(UInt d, UInt d1) */ static Obj FuncCONV_VEC8BIT(Obj self, Obj list, Obj q) { + RequireSmallList(SELF_NAME, list); UInt iq = GetPositiveSmallInt(SELF_NAME, q); ConvVec8Bit(list, iq); return 0; @@ -937,6 +942,7 @@ static Obj NewVec8Bit(Obj list, UInt q) */ static Obj FuncCOPY_VEC8BIT(Obj self, Obj list, Obj q) { + RequireSmallList(SELF_NAME, list); UInt iq = GetPositiveSmallInt(SELF_NAME, q); return NewVec8Bit(list, iq); } @@ -1019,9 +1025,7 @@ void PlainVec8Bit(Obj list) */ static Obj FuncPLAIN_VEC8BIT(Obj self, Obj list) { - if (!IS_VEC8BIT_REP(list)) { - RequireArgument(SELF_NAME, list, "must be an 8bit vector"); - } + RequireVec8BitRep(SELF_NAME, list); if (DoFilter(IsLockedRepresentationVector, list) == True) { ErrorMayQuit("Cannot convert a locked vector compressed over " "GF(%d) to a plain list", @@ -1214,8 +1218,8 @@ static Obj ConvertToVectorRep; // BH: changed to static static Obj FuncSUM_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { - GAP_ASSERT(IS_VEC8BIT_REP(vl)); - GAP_ASSERT(IS_VEC8BIT_REP(vr)); + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); Obj sum; if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) { @@ -1395,6 +1399,9 @@ static Obj FuncPROD_VEC8BIT_FFE(Obj self, Obj vec, Obj ffe) Obj info; UInt d; + RequireVec8BitRep(SELF_NAME, vec); + RequireFFE(SELF_NAME, ffe); + if (VAL_FFE(ffe) == 1) { // ffe is the one return CopyVec8Bit(vec, IS_MUTABLE_OBJ(vec)); } @@ -1427,6 +1434,7 @@ static Obj FuncPROD_VEC8BIT_FFE(Obj self, Obj vec, Obj ffe) static Obj FuncZERO_VEC8BIT(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return ZeroVec8Bit(FIELD_VEC8BIT(vec), LEN_VEC8BIT(vec), 1); } @@ -1456,6 +1464,8 @@ static Obj FuncZERO_VEC8BIT_2(Obj self, Obj q, Obj len) static Obj FuncPROD_FFE_VEC8BIT(Obj self, Obj ffe, Obj vec) { + RequireFFE(SELF_NAME, ffe); + RequireVec8BitRep(SELF_NAME, vec); return FuncPROD_VEC8BIT_FFE(self, vec, ffe); } @@ -1492,16 +1502,19 @@ static Obj AInvVec8Bit(Obj vec, UInt mut) static Obj FuncAINV_VEC8BIT_MUTABLE(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return AInvVec8Bit(vec, 1); } static Obj FuncAINV_VEC8BIT_SAME_MUTABILITY(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return AInvVec8Bit(vec, IS_MUTABLE_OBJ(vec)); } static Obj FuncAINV_VEC8BIT_IMMUTABLE(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return AInvVec8Bit(vec, 0); } @@ -1608,6 +1621,8 @@ static void AddVec8BitVec8BitMultInner( static Obj FuncMULT_VECTOR_VEC8BITS(Obj self, Obj vec, Obj mul) { + RequireVec8BitRep(SELF_NAME, vec); + RequireFFE(SELF_NAME, mul); UInt q; q = FIELD_VEC8BIT(vec); @@ -1646,6 +1661,11 @@ static Obj AddRowVector; static Obj FuncADD_ROWVECTOR_VEC8BITS_5( Obj self, Obj vl, Obj vr, Obj mul, Obj from, Obj to) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); + RequireFFE(SELF_NAME, mul); + RequirePositiveSmallInt(SELF_NAME, from); + RequirePositiveSmallInt(SELF_NAME, to); UInt q; UInt len; len = LEN_VEC8BIT(vl); @@ -1720,6 +1740,9 @@ static Obj FuncADD_ROWVECTOR_VEC8BITS_5( static Obj FuncADD_ROWVECTOR_VEC8BITS_3(Obj self, Obj vl, Obj vr, Obj mul) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); + RequireFFE(SELF_NAME, mul); UInt q; if (LEN_VEC8BIT(vl) != LEN_VEC8BIT(vr)) { ErrorMayQuit( @@ -1778,6 +1801,8 @@ static Obj FuncADD_ROWVECTOR_VEC8BITS_3(Obj self, Obj vl, Obj vr, Obj mul) static Obj FuncADD_ROWVECTOR_VEC8BITS_2(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); UInt q; if (LEN_VEC8BIT(vl) != LEN_VEC8BIT(vr)) { ErrorMayQuit( @@ -1913,6 +1938,8 @@ static Obj FuncDIFF_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) Obj diff; // UInt p; + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) { UInt ql = FIELD_VEC8BIT(vl), qr = FIELD_VEC8BIT(vr); @@ -2086,6 +2113,8 @@ static Obj ScalarProductVec8Bits(Obj vl, Obj vr) static Obj FuncPROD_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) return ProdListList(vl, vr); @@ -2146,6 +2175,8 @@ static UInt DistanceVec8Bits(Obj vl, Obj vr) static Obj FuncDISTANCE_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr) || LEN_VEC8BIT(vl) != LEN_VEC8BIT(vr)) return TRY_NEXT_METHOD; @@ -2215,6 +2246,10 @@ static Obj FuncDISTANCE_DISTRIB_VEC8BITS( UInt len; UInt q; + RequirePlainList(SELF_NAME, veclis); + RequireVec8BitRep(SELF_NAME, vec); + RequirePlainList(SELF_NAME, d); + len = LEN_VEC8BIT(vec); q = FIELD_VEC8BIT(vec); @@ -2331,6 +2366,8 @@ static Obj FuncA_CLOSEST_VEC8BIT( UInt len; UInt q; + RequirePlainList(SELF_NAME, veclis); + RequireVec8BitRep(SELF_NAME, vec); RequireNonnegativeSmallInt(SELF_NAME, cnt); RequireNonnegativeSmallInt(SELF_NAME, stop); @@ -2371,6 +2408,8 @@ static Obj FuncA_CLOSEST_VEC8BIT_COORDS( Obj res; + RequirePlainList(SELF_NAME, veclis); + RequireVec8BitRep(SELF_NAME, vec); RequireNonnegativeSmallInt(SELF_NAME, cnt); RequireNonnegativeSmallInt(SELF_NAME, stop); @@ -2413,6 +2452,7 @@ static Obj FuncA_CLOSEST_VEC8BIT_COORDS( static Obj FuncNUMBER_VEC8BIT(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); Obj info; UInt elts; UInt len; @@ -2608,6 +2648,7 @@ static Obj FuncCOSET_LEADERS_INNER_8BITS( RequireSmallInt(SELF_NAME, weight); RequireSmallInt(SELF_NAME, tofind); RequirePlainList(SELF_NAME, leaders); + RequirePlainList(SELF_NAME, felts); lenv = LEN_PLIST(veclis); q = LEN_PLIST(felts); @@ -2628,6 +2669,8 @@ static Obj FuncCOSET_LEADERS_INNER_8BITS( static Obj FuncEQ_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) return EqListList(vl, vr) ? True : False; @@ -2645,6 +2688,8 @@ static Obj FuncEQ_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) static Obj FuncLT_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) { + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); if (FIELD_VEC8BIT(vl) != FIELD_VEC8BIT(vr)) return LtListList(vl, vr) ? True : False; @@ -2665,6 +2710,7 @@ static Obj FuncLT_VEC8BIT_VEC8BIT(Obj self, Obj vl, Obj vr) static Obj FuncSHALLOWCOPY_VEC8BIT(Obj self, Obj list) { + RequireVec8BitRep(SELF_NAME, list); return CopyVec8Bit(list, 1); } @@ -2675,6 +2721,7 @@ static Obj FuncSHALLOWCOPY_VEC8BIT(Obj self, Obj list) */ static Obj FuncLEN_VEC8BIT(Obj self, Obj list) { + RequireVec8BitRep(SELF_NAME, list); return INTOBJ_INT(LEN_VEC8BIT(list)); } @@ -2684,6 +2731,7 @@ static Obj FuncLEN_VEC8BIT(Obj self, Obj list) */ static Obj FuncQ_VEC8BIT(Obj self, Obj list) { + RequireVec8BitRep(SELF_NAME, list); return INTOBJ_INT(FIELD_VEC8BIT(list)); } @@ -2704,6 +2752,7 @@ static Obj FuncELM0_VEC8BIT(Obj self, Obj list, Obj pos) Obj info; UInt elts; + RequireVec8BitRep(SELF_NAME, list); p = GetPositiveSmallInt(SELF_NAME, pos); if (LEN_VEC8BIT(list) < p) { return Fail; @@ -2733,6 +2782,7 @@ static Obj FuncELM_VEC8BIT(Obj self, Obj list, Obj pos) Obj info; UInt elts; + RequireVec8BitRep(SELF_NAME, list); p = GetPositiveSmallInt(SELF_NAME, pos); if (LEN_VEC8BIT(list) < p) { ErrorMayQuit("List Element: [%d] must have an assigned value", @@ -2773,6 +2823,8 @@ static Obj FuncELMS_VEC8BIT(Obj self, Obj list, Obj poss) UInt1 byte; UInt len2; + RequireVec8BitRep(SELF_NAME, list); + RequirePlainList(SELF_NAME, poss); len = LEN_PLIST(poss); info = GetFieldInfo8Bit(FIELD_VEC8BIT(list)); len2 = LEN_VEC8BIT(list); @@ -2840,6 +2892,9 @@ static Obj FuncELMS_VEC8BIT_RANGE(Obj self, Obj list, Obj range) UInt e; UInt1 byte; + RequireVec8BitRep(SELF_NAME, list); + RequireArgumentCondition(SELF_NAME, range, IS_RANGE(range), "must be a range"); + info = GetFieldInfo8Bit(FIELD_VEC8BIT(list)); elts = ELS_BYTE_FIELDINFO_8BIT(info); len = GET_LEN_RANGE(range); @@ -2947,7 +3002,7 @@ void ASS_VEC8BIT(Obj list, Obj pos, Obj elm) ErrorReturnVoid("List assignment would increase length of " "locked compressed vector", 0, 0, - "You can `return;' to ignore the assignment"); + "you can enter 'return;' to ignore the assignment"); return; } ResizeWordSizedBag(list, SIZE_VEC8BIT(p, elts)); @@ -3012,6 +3067,7 @@ void ASS_VEC8BIT(Obj list, Obj pos, Obj elm) static Obj FuncASS_VEC8BIT(Obj self, Obj list, Obj pos, Obj elm) { + RequireVec8BitRep(SELF_NAME, list); ASS_VEC8BIT(list, pos, elm); return 0; } @@ -3032,12 +3088,13 @@ static Obj FuncUNB_VEC8BIT(Obj self, Obj list, Obj pos) Obj info; UInt elts; + RequireVec8BitRep(SELF_NAME, list); // check that is mutable RequireMutable("List Unbind", list, "list"); if (True == DoFilter(IsLockedRepresentationVector, list)) { ErrorReturnVoid( "Unbind of entry of locked compressed vector is forbidden", 0, 0, - "You can `return;' to ignore the assignment"); + "you can enter 'return;' to ignore the assignment"); return 0; } @@ -3121,12 +3178,15 @@ static UInt PositionNonZeroVec8Bit(Obj list, UInt from) static Obj FuncPOSITION_NONZERO_VEC8BIT(Obj self, Obj list, Obj zero) { + RequireVec8BitRep(SELF_NAME, list); return INTOBJ_INT(PositionNonZeroVec8Bit(list, 0)); } static Obj FuncPOSITION_NONZERO_VEC8BIT3(Obj self, Obj list, Obj zero, Obj from) { + RequireVec8BitRep(SELF_NAME, list); + RequireNonnegativeSmallInt(SELF_NAME, from); return INTOBJ_INT(PositionNonZeroVec8Bit(list, INT_INTOBJ(from))); } @@ -3150,6 +3210,9 @@ static Obj FuncAPPEND_VEC8BIT(Obj self, Obj vecl, Obj vecr) const UInt1 * settab; UInt posl, posr; + RequireVec8BitRep(SELF_NAME, vecl); + RequireVec8BitRep(SELF_NAME, vecr); + if (FIELD_VEC8BIT(vecl) != FIELD_VEC8BIT(vecr)) return TRY_NEXT_METHOD; @@ -3157,7 +3220,7 @@ static Obj FuncAPPEND_VEC8BIT(Obj self, Obj vecl, Obj vecr) lenr = LEN_VEC8BIT(vecr); if (True == DoFilter(IsLockedRepresentationVector, vecl) && lenr > 0) { ErrorReturnVoid("Append to locked compressed vector is forbidden", 0, - 0, "You can `return;' to ignore the operation"); + 0, "you can enter 'return;' to ignore the operation"); return 0; } info = GetFieldInfo8Bit(FIELD_VEC8BIT(vecl)); @@ -3224,6 +3287,9 @@ static Obj FuncPROD_VEC8BIT_MATRIX(Obj self, Obj vec, Obj mat) const Obj * ffefelt; Obj x; + RequireVec8BitRep(SELF_NAME, vec); + RequirePlainList(SELF_NAME, mat); + len = LEN_VEC8BIT(vec); l2 = LEN_PLIST(mat); q = FIELD_VEC8BIT(vec); @@ -3310,6 +3376,14 @@ static inline UInt NR_COLS_MAT8BIT(Obj mat) return LEN_VEC8BIT(ELM_MAT8BIT(mat, 1)); } +static inline void RequireNonemptyMat8BitRows(const Char * funcname, Obj mat) +{ + if (LEN_MAT8BIT(mat) == 0) + ErrorMayQuit("%s: compressed 8bit matrices with empty rows are not " + "supported", + (Int)funcname, 0); +} + /**************************************************************************** ** *F PlainMat8Bit( ) @@ -3337,6 +3411,7 @@ static void PlainMat8Bit(Obj mat) static Obj FuncPLAIN_MAT8BIT(Obj self, Obj mat) { + RequireMat8BitRep(SELF_NAME, mat); PlainMat8Bit(mat); return 0; } @@ -3356,6 +3431,7 @@ static Obj FuncCONV_MAT8BIT(Obj self, Obj list, Obj q) Obj tmp; Obj type; + RequirePlainList(SELF_NAME, list); UInt iq = GetPositiveSmallInt(SELF_NAME, q); PLAIN_LIST(list); len = LEN_PLIST(list); @@ -3464,8 +3540,9 @@ static Obj FuncPROD_VEC8BIT_MAT8BIT(Obj self, Obj vec, Obj mat) { UInt q, q1, q2; - GAP_ASSERT(IS_VEC8BIT_REP(vec)); - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireVec8BitRep(SELF_NAME, vec); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); // Now field mismatches -- consider promoting the vector q = FIELD_VEC8BIT(vec); @@ -3549,8 +3626,9 @@ static Obj FuncPROD_MAT8BIT_VEC8BIT(Obj self, Obj mat, Obj vec) { UInt q, q1, q2; - GAP_ASSERT(IS_MAT8BIT_REP(mat)); - GAP_ASSERT(IS_VEC8BIT_REP(vec)); + RequireMat8BitRep(SELF_NAME, mat); + RequireVec8BitRep(SELF_NAME, vec); + RequireNonemptyMat8BitRows(SELF_NAME, mat); // Now field mismatches -- consider promoting the vector q = FIELD_VEC8BIT(vec); @@ -3626,8 +3704,10 @@ static Obj ProdMat8BitMat8Bit(Obj matl, Obj matr) static Obj FuncPROD_MAT8BIT_MAT8BIT(Obj self, Obj matl, Obj matr) { - GAP_ASSERT(IS_MAT8BIT_REP(matl)); - GAP_ASSERT(IS_MAT8BIT_REP(matr)); + RequireMat8BitRep(SELF_NAME, matl); + RequireMat8BitRep(SELF_NAME, matr); + RequireNonemptyMat8BitRows(SELF_NAME, matl); + RequireNonemptyMat8BitRows(SELF_NAME, matr); if (FIELD_MAT8BIT(matl) != FIELD_MAT8BIT(matr)) { return TRY_NEXT_METHOD; @@ -3802,7 +3882,8 @@ static Obj InverseMat8Bit(Obj mat, UInt mut) static Obj FuncINV_MAT8BIT_MUTABLE(Obj self, Obj mat) { - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); if (LEN_MAT8BIT(mat) != LEN_VEC8BIT(ELM_MAT8BIT(mat, 1))) { ErrorMayQuit("InverseOp: matrix must be square, not %d by %d", @@ -3820,7 +3901,8 @@ static Obj FuncINV_MAT8BIT_MUTABLE(Obj self, Obj mat) static Obj FuncINV_MAT8BIT_SAME_MUTABILITY(Obj self, Obj mat) { - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); if (LEN_MAT8BIT(mat) != LEN_VEC8BIT(ELM_MAT8BIT(mat, 1))) { ErrorMayQuit( "InverseSameMutability: matrix must be square, not %d by %d", @@ -3838,7 +3920,8 @@ static Obj FuncINV_MAT8BIT_SAME_MUTABILITY(Obj self, Obj mat) static Obj FuncINV_MAT8BIT_IMMUTABLE(Obj self, Obj mat) { - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); if (LEN_MAT8BIT(mat) != LEN_VEC8BIT(ELM_MAT8BIT(mat, 1))) { ErrorMayQuit("Inverse: matrix must be square, not %d by %d", LEN_MAT8BIT(mat), LEN_VEC8BIT(ELM_MAT8BIT(mat, 1))); @@ -3864,7 +3947,8 @@ static Obj FuncASS_MAT8BIT(Obj self, Obj mat, Obj pos, Obj obj) UInt p; Obj type; - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); p = GetPositiveSmallInt(SELF_NAME, pos); len = LEN_MAT8BIT(mat); @@ -3957,7 +4041,7 @@ static Obj FuncASS_MAT8BIT(Obj self, Obj mat, Obj pos, Obj obj) */ static Obj FuncELM_MAT8BIT(Obj self, Obj mat, Obj pos) { - GAP_ASSERT(IS_MAT8BIT_REP(mat)); + RequireMat8BitRep(SELF_NAME, mat); UInt r = GetPositiveSmallInt(SELF_NAME, pos); if (LEN_MAT8BIT(mat) < r) { ErrorMayQuit("row index %d exceeds %d, the number of rows", r, @@ -4111,8 +4195,10 @@ static Obj SumMat8BitMat8Bit(Obj ml, Obj mr) static Obj FuncSUM_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) { - GAP_ASSERT(IS_MAT8BIT_REP(ml)); - GAP_ASSERT(IS_MAT8BIT_REP(mr)); + RequireMat8BitRep(SELF_NAME, ml); + RequireMat8BitRep(SELF_NAME, mr); + RequireNonemptyMat8BitRows(SELF_NAME, ml); + RequireNonemptyMat8BitRows(SELF_NAME, mr); if (FIELD_MAT8BIT(ml) != FIELD_MAT8BIT(mr)) { return TRY_NEXT_METHOD; @@ -4204,8 +4290,10 @@ static Obj DiffMat8BitMat8Bit(Obj ml, Obj mr) static Obj FuncDIFF_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) { - GAP_ASSERT(IS_MAT8BIT_REP(ml)); - GAP_ASSERT(IS_MAT8BIT_REP(mr)); + RequireMat8BitRep(SELF_NAME, ml); + RequireMat8BitRep(SELF_NAME, mr); + RequireNonemptyMat8BitRows(SELF_NAME, ml); + RequireNonemptyMat8BitRows(SELF_NAME, mr); if (FIELD_MAT8BIT(ml) != FIELD_MAT8BIT(mr)) return TRY_NEXT_METHOD; @@ -4281,7 +4369,7 @@ static void ResizeVec8Bit(Obj vec, UInt newlen, UInt knownclean) if (True == DoFilter(IsLockedRepresentationVector, vec)) { ErrorReturnVoid("Resize of locked compressed vector is forbidden", 0, - 0, "You can `return;' to ignore the operation"); + 0, "you can enter 'return;' to ignore the operation"); return; } @@ -4407,6 +4495,8 @@ static void ShiftRightVec8Bit(Obj vec, UInt amount) // pads with zeros // make room len = LEN_VEC8BIT(vec); ResizeVec8Bit(vec, len + amount, 0); + if (len == 0) + return; q = FIELD_VEC8BIT(vec); info = GetFieldInfo8Bit(q); @@ -4461,6 +4551,10 @@ static void ShiftRightVec8Bit(Obj vec, UInt amount) // pads with zeros static Obj FuncADD_COEFFS_VEC8BIT_3(Obj self, Obj vec1, Obj vec2, Obj mult) { + RequireVec8BitRep(SELF_NAME, vec1); + RequireVec8BitRep(SELF_NAME, vec2); + RequireFFE(SELF_NAME, mult); + UInt q; UInt len; len = LEN_VEC8BIT(vec2); @@ -4525,6 +4619,9 @@ static Obj FuncADD_COEFFS_VEC8BIT_3(Obj self, Obj vec1, Obj vec2, Obj mult) static Obj FuncADD_COEFFS_VEC8BIT_2(Obj self, Obj vec1, Obj vec2) { + RequireVec8BitRep(SELF_NAME, vec1); + RequireVec8BitRep(SELF_NAME, vec2); + UInt q; UInt len; len = LEN_VEC8BIT(vec2); @@ -4578,8 +4675,8 @@ static Obj FuncADD_COEFFS_VEC8BIT_2(Obj self, Obj vec1, Obj vec2) static Obj FuncSHIFT_VEC8BIT_LEFT(Obj self, Obj vec, Obj amount) { - if (!IS_MUTABLE_OBJ(vec)) - RequireArgument(SELF_NAME, vec, "must be mutable"); + RequireVec8BitRep(SELF_NAME, vec); + RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, amount); ShiftLeftVec8Bit(vec, INT_INTOBJ(amount)); return (Obj)0; @@ -4593,9 +4690,10 @@ static Obj FuncSHIFT_VEC8BIT_LEFT(Obj self, Obj vec, Obj amount) static Obj FuncSHIFT_VEC8BIT_RIGHT(Obj self, Obj vec, Obj amount, Obj zero) { - if (!IS_MUTABLE_OBJ(vec)) - RequireArgument(SELF_NAME, vec, "must be mutable"); + RequireVec8BitRep(SELF_NAME, vec); + RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, amount); + RequireFFE(SELF_NAME, zero); ShiftRightVec8Bit(vec, INT_INTOBJ(amount)); return (Obj)0; } @@ -4608,6 +4706,7 @@ static Obj FuncSHIFT_VEC8BIT_RIGHT(Obj self, Obj vec, Obj amount, Obj zero) static Obj FuncRESIZE_VEC8BIT(Obj self, Obj vec, Obj newsize) { + RequireVec8BitRep(SELF_NAME, vec); RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, newsize); ResizeVec8Bit(vec, INT_INTOBJ(newsize), 0); @@ -4622,6 +4721,7 @@ static Obj FuncRESIZE_VEC8BIT(Obj self, Obj vec, Obj newsize) static Obj FuncRIGHTMOST_NONZERO_VEC8BIT(Obj self, Obj vec) { + RequireVec8BitRep(SELF_NAME, vec); return INTOBJ_INT(RightMostNonZeroVec8Bit(vec)); } @@ -4807,6 +4907,12 @@ static Obj FuncPROD_COEFFS_VEC8BIT(Obj self, Obj vl, Obj ll, Obj vr, Obj lr) Obj res; UInt lenp; UInt last; + + RequireVec8BitRep(SELF_NAME, vl); + RequireVec8BitRep(SELF_NAME, vr); + RequireNonnegativeSmallInt(SELF_NAME, ll); + RequireNonnegativeSmallInt(SELF_NAME, lr); + q = FIELD_VEC8BIT(vl); if (q != FIELD_VEC8BIT(vr)) { Obj info1; @@ -4837,8 +4943,6 @@ static Obj FuncPROD_COEFFS_VEC8BIT(Obj self, Obj vl, Obj ll, Obj vr, Obj lr) q = q0; } - RequireNonnegativeSmallInt(SELF_NAME, ll); - RequireNonnegativeSmallInt(SELF_NAME, lr); ll1 = INT_INTOBJ(ll); lr1 = INT_INTOBJ(lr); if (0 > ll1 || ll1 > LEN_VEC8BIT(vl)) @@ -4855,7 +4959,8 @@ static Obj FuncPROD_COEFFS_VEC8BIT(Obj self, Obj vl, Obj ll, Obj vr, Obj lr) else lenp = ll1 + lr1 - 1; res = ZeroVec8Bit(q, lenp, 1); - ProdCoeffsVec8Bit(res, vl, ll1, vr, lr1); + if (lenp > 0) + ProdCoeffsVec8Bit(res, vl, ll1, vr, lr1); last = RightMostNonZeroVec8Bit(res); if (last != lenp) ResizeVec8Bit(res, last, 1); @@ -4897,8 +5002,7 @@ static Obj MakeShiftedVecs(Obj v, UInt len) ResizeVec8Bit(vn, len, 0); len1 = (len == 0) ? 0 : RightMostNonZeroVec8Bit(vn); if (len1 == 0) - ErrorReturnVoid("Zero coefficient vector for reduction", 0, 0, - "you can 'return;'"); + ErrorReturnVoid("Zero coefficient vector for reduction", 0, 0, 0); if (len1 != len) { ResizeVec8Bit(vn, len1, 1); len = len1; @@ -5060,10 +5164,11 @@ static Obj FuncREDUCE_COEFFS_VEC8BIT(Obj self, Obj vl, Obj ll, Obj vrshifted) UInt last; RequireVec8BitRep(SELF_NAME, vl); + RequireNonnegativeSmallInt(SELF_NAME, ll); + RequirePlainList(SELF_NAME, vrshifted); q = FIELD_VEC8BIT(vl); if (q != FIELD_VEC8BIT(ELM_PLIST(vrshifted, 1))) return Fail; - RequireNonnegativeSmallInt(SELF_NAME, ll); if (INT_INTOBJ(ll) > LEN_VEC8BIT(vl)) { ErrorQuit("ReduceCoeffs: given length of left argt (%d) is " "longer than the argt (%d)", @@ -5397,7 +5502,7 @@ static Obj FuncSEMIECHELON_LIST_VEC8BITS(Obj self, Obj mat) Obj row; UInt q; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5436,7 +5541,7 @@ static Obj FuncSEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS(Obj self, Obj mat) UInt q; UInt width; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5475,7 +5580,7 @@ static Obj FuncTRIANGULIZE_LIST_VEC8BITS(Obj self, Obj mat) Obj row; UInt q; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5514,7 +5619,7 @@ static Obj FuncRANK_LIST_VEC8BITS(Obj self, Obj mat) Obj row; UInt q; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5553,7 +5658,7 @@ static Obj FuncDETERMINANT_LIST_VEC8BITS(Obj self, Obj mat) UInt q; Obj det; - GAP_ASSERT(IS_PLIST(mat)); + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) @@ -5613,8 +5718,8 @@ static Int Cmp_MAT8BIT_MAT8BIT(Obj ml, Obj mr) static Obj FuncEQ_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) { - GAP_ASSERT(IS_MAT8BIT_REP(ml)); - GAP_ASSERT(IS_MAT8BIT_REP(mr)); + RequireMat8BitRep(SELF_NAME, ml); + RequireMat8BitRep(SELF_NAME, mr); if (LEN_MAT8BIT(ml) != LEN_MAT8BIT(mr)) return False; @@ -5632,8 +5737,8 @@ static Obj FuncEQ_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) static Obj FuncLT_MAT8BIT_MAT8BIT(Obj self, Obj ml, Obj mr) { - GAP_ASSERT(IS_MAT8BIT_REP(ml)); - GAP_ASSERT(IS_MAT8BIT_REP(mr)); + RequireMat8BitRep(SELF_NAME, ml); + RequireMat8BitRep(SELF_NAME, mr); if (LEN_MAT8BIT(ml) == 0) return (LEN_MAT8BIT(mr) != 0) ? True : False; @@ -5665,6 +5770,7 @@ static Obj FuncTRANSPOSED_MAT8BIT(Obj self, Obj mat) Obj type; RequireMat8BitRep(SELF_NAME, mat); + RequireNonemptyMat8BitRows(SELF_NAME, mat); // we will give result same type as mat // we assume here that there is a first row -- a zero row mat8bit is a @@ -5762,8 +5868,10 @@ static Obj FuncKRONECKERPRODUCT_MAT8BIT_MAT8BIT(Obj self, Obj matl, Obj matr) const UInt1 * getelt, *setelt, *scalar, *add; const UInt1 * datar; - GAP_ASSERT(IS_MAT8BIT_REP(matl)); - GAP_ASSERT(IS_MAT8BIT_REP(matr)); + RequireMat8BitRep(SELF_NAME, matl); + RequireMat8BitRep(SELF_NAME, matr); + RequireNonemptyMat8BitRows(SELF_NAME, matl); + RequireNonemptyMat8BitRows(SELF_NAME, matr); nrowl = LEN_MAT8BIT(matl); nrowr = LEN_MAT8BIT(matr); diff --git a/src/vecgf2.c b/src/vecgf2.c index 6c3e64a1c2..d61c046c3a 100644 --- a/src/vecgf2.c +++ b/src/vecgf2.c @@ -86,6 +86,8 @@ Obj TYPE_LIST_GF2MAT_IMM; */ Obj IsGF2VectorRep; +Obj IsGF2MatrixRep; + /**************************************************************************** ** @@ -100,6 +102,18 @@ static Obj GF2One; */ static Obj GF2Zero; +#define RequireGF2VecRep(funcname, op) \ + RequireArgumentCondition(funcname, op, IS_GF2VEC_REP(op), \ + "must be a GF2 vector") + +#define RequireGF2MatRep(funcname, op) \ + RequireArgumentCondition(funcname, op, IS_GF2MAT_REP(op), \ + "must be a GF2 matrix") + +#define RequireFFE(funcname, op) \ + RequireArgumentCondition(funcname, op, IS_FFE(op), \ + "must be a finite field element") + /**************************************************************************** ** @@ -835,6 +849,12 @@ static Obj FuncPROD_GF2VEC_ANYMAT(Obj self, Obj vec, Obj mat) UInt i; UInt block = 0; + RequireGF2VecRep(SELF_NAME, vec); + RequirePlainList(SELF_NAME, mat); + + if (LEN_PLIST(mat) == 0) + return TRY_NEXT_METHOD; + len = LEN_GF2VEC(vec); if (len > LEN_PLIST(mat)) len = LEN_PLIST(mat); @@ -1389,6 +1409,7 @@ static void ConvGF2Vec(Obj list) */ static Obj FuncCONV_GF2VEC(Obj self, Obj list) { + RequireSmallList(SELF_NAME, list); ConvGF2Vec(list); return 0; } @@ -1467,7 +1488,6 @@ static Obj NewGF2Vec(Obj list) return res; } - /**************************************************************************** ** *F FuncCOPY_GF2VEC( , ) . . . . . convert into a GF2 vector rep @@ -1492,6 +1512,7 @@ static Obj FuncCONV_GF2MAT(Obj self, Obj list) UInt len, i; Obj tmp; UInt mut; + RequireSmallList(SELF_NAME, list); len = LEN_LIST(list); if (len == 0) return (Obj)0; @@ -1664,6 +1685,9 @@ static Int Cmp_GF2VEC_GF2VEC(Obj vl, Obj vr) */ static Obj FuncEQ_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); + // we can do this case MUCH faster if we just want equality if (LEN_GF2VEC(vl) != LEN_GF2VEC(vr)) return False; @@ -1677,6 +1701,7 @@ static Obj FuncEQ_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) */ static Obj FuncLEN_GF2VEC(Obj self, Obj list) { + RequireGF2VecRep(SELF_NAME, list); return INTOBJ_INT(LEN_GF2VEC(list)); } @@ -1692,6 +1717,7 @@ static Obj FuncLEN_GF2VEC(Obj self, Obj list) */ static Obj FuncELM0_GF2VEC(Obj self, Obj list, Obj pos) { + RequireGF2VecRep(SELF_NAME, list); UInt p = GetSmallInt(SELF_NAME, pos); if (LEN_GF2VEC(list) < p) { return Fail; @@ -1712,6 +1738,7 @@ static Obj FuncELM0_GF2VEC(Obj self, Obj list, Obj pos) */ static Obj FuncELM_GF2VEC(Obj self, Obj list, Obj pos) { + RequireGF2VecRep(SELF_NAME, list); UInt p = GetSmallInt(SELF_NAME, pos); if (LEN_GF2VEC(list) < p) { ErrorMayQuit("List Element: [%d] must have an assigned value", @@ -1743,6 +1770,8 @@ static Obj FuncELMS_GF2VEC(Obj self, Obj list, Obj poss) Int i; // loop variable Obj apos; + RequireGF2VecRep(SELF_NAME, list); + // get the length of lenList = LEN_GF2VEC(list); @@ -1830,6 +1859,8 @@ static Obj FuncELMS_GF2VEC(Obj self, Obj list, Obj poss) static Obj FuncASS_GF2VEC(Obj self, Obj list, Obj pos, Obj elm) { + RequireGF2VecRep(SELF_NAME, list); + // check that is mutable RequireMutable("List Assignment", list, "list"); @@ -1875,6 +1906,7 @@ static Obj FuncASS_GF2VEC(Obj self, Obj list, Obj pos, Obj elm) */ static Obj FuncPLAIN_GF2MAT(Obj self, Obj list) { + RequireGF2MatRep(SELF_NAME, list); PlainGF2Mat(list); return 0; } @@ -1892,6 +1924,8 @@ static Obj FuncPLAIN_GF2MAT(Obj self, Obj list) */ static Obj FuncASS_GF2MAT(Obj self, Obj list, Obj pos, Obj elm) { + RequireGF2MatRep(SELF_NAME, list); + // check that is mutable RequireMutable("List Assignment", list, "list"); @@ -1939,6 +1973,7 @@ static Obj FuncASS_GF2MAT(Obj self, Obj list, Obj pos, Obj elm) */ static Obj FuncELM_GF2MAT(Obj self, Obj mat, Obj row) { + RequireGF2MatRep(SELF_NAME, mat); UInt r = GetSmallInt(SELF_NAME, row); if (LEN_GF2MAT(mat) < r) { ErrorMayQuit("row index %d exceeds %d, the number of rows", r, @@ -1955,6 +1990,7 @@ static Obj FuncELM_GF2MAT(Obj self, Obj mat, Obj row) */ static Obj FuncSWAP_ROWS_GF2MAT(Obj self, Obj mat, Obj row1, Obj row2) { + RequireGF2MatRep(SELF_NAME, mat); RequireMutable(SELF_NAME, mat, "mat"); UInt r1 = GetSmallInt(SELF_NAME, row1); @@ -1984,6 +2020,7 @@ static Obj FuncSWAP_ROWS_GF2MAT(Obj self, Obj mat, Obj row1, Obj row2) */ static Obj FuncSWAP_COLS_GF2MAT(Obj self, Obj mat, Obj col1, Obj col2) { + RequireGF2MatRep(SELF_NAME, mat); UInt c1 = GetSmallInt(SELF_NAME, col1); UInt c2 = GetSmallInt(SELF_NAME, col2); UInt m = LEN_GF2MAT(mat); @@ -2032,6 +2069,8 @@ static Obj FuncSWAP_COLS_GF2MAT(Obj self, Obj mat, Obj col1, Obj col2) */ static Obj FuncUNB_GF2VEC(Obj self, Obj list, Obj pos) { + RequireGF2VecRep(SELF_NAME, list); + // check that is mutable RequireMutable("List Unbind", list, "vector"); @@ -2069,6 +2108,8 @@ static Obj FuncUNB_GF2VEC(Obj self, Obj list, Obj pos) */ static Obj FuncUNB_GF2MAT(Obj self, Obj list, Obj pos) { + RequireGF2MatRep(SELF_NAME, list); + // check that is mutable RequireMutable("List Unbind", list, "matrix"); @@ -2108,6 +2149,8 @@ static Obj FuncZERO_GF2VEC(Obj self, Obj mat) Obj zero; UInt len; + RequireGF2VecRep(SELF_NAME, mat); + // create a new GF2 vector len = LEN_GF2VEC(mat); NEW_GF2VEC(zero, TYPE_LIST_GF2VEC, len); @@ -2141,6 +2184,8 @@ static Obj FuncINV_GF2MAT_MUTABLE(Obj self, Obj mat) { UInt len; + RequireGF2MatRep(SELF_NAME, mat); + len = LEN_GF2MAT(mat); if (len != 0) { if (len != LEN_GF2VEC(ELM_GF2MAT(mat, 1))) { @@ -2162,6 +2207,8 @@ static Obj FuncINV_GF2MAT_SAME_MUTABILITY(Obj self, Obj mat) { UInt len; + RequireGF2MatRep(SELF_NAME, mat); + len = LEN_GF2MAT(mat); if (len != 0) { if (len != LEN_GF2VEC(ELM_GF2MAT(mat, 1))) { @@ -2183,6 +2230,8 @@ static Obj FuncINV_GF2MAT_IMMUTABLE(Obj self, Obj mat) { UInt len; + RequireGF2MatRep(SELF_NAME, mat); + len = LEN_GF2MAT(mat); if (len != 0) { if (len != LEN_GF2VEC(ELM_GF2MAT(mat, 1))) { @@ -2203,6 +2252,7 @@ static Obj FuncINV_PLIST_GF2VECS_DESTRUCTIVE(Obj self, Obj list) { UInt len, i; Obj row; + RequirePlainList(SELF_NAME, list); len = LEN_PLIST(list); for (i = 1; i <= len; i++) { row = ELM_PLIST(list, i); @@ -2242,6 +2292,9 @@ static Obj FuncSUM_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) Obj sum; // sum, result UInt ll, lr; + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); + ll = LEN_GF2VEC(vl); lr = LEN_GF2VEC(vr); @@ -2269,6 +2322,9 @@ static Obj FuncSUM_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) */ static Obj FuncMULT_VECTOR_GF2VECS_2(Obj self, Obj vl, Obj mul) { + RequireGF2VecRep(SELF_NAME, vl); + RequireFFE(SELF_NAME, mul); + if (EQ(mul, GF2One)) return (Obj)0; else if (EQ(mul, GF2Zero)) { @@ -2289,6 +2345,8 @@ static Obj FuncMULT_VECTOR_GF2VECS_2(Obj self, Obj vl, Obj mul) */ static Obj FuncPROD_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); return ProdGF2VecGF2Vec(vl, vr); } @@ -2305,6 +2363,8 @@ static Obj FuncPROD_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) */ static Obj FuncPROD_GF2VEC_GF2MAT(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2MatRep(SELF_NAME, vr); return ProdGF2VecGF2Mat(vl, vr); } @@ -2320,6 +2380,8 @@ static Obj FuncPROD_GF2VEC_GF2MAT(Obj self, Obj vl, Obj vr) */ static Obj FuncPROD_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); UInt lenl = LEN_GF2MAT(ml); UInt lenm; if (lenl >= 128) { @@ -2344,6 +2406,8 @@ static Obj FuncPROD_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) */ static Obj FuncPROD_GF2MAT_GF2MAT_SIMPLE(Obj self, Obj ml, Obj mr) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); return ProdGF2MatGF2MatSimple(ml, mr); } @@ -2362,6 +2426,10 @@ static Obj FuncPROD_GF2MAT_GF2MAT_SIMPLE(Obj self, Obj ml, Obj mr) static Obj FuncPROD_GF2MAT_GF2MAT_ADVANCED( Obj self, Obj ml, Obj mr, Obj greaselevel, Obj blocksize) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); + RequireSmallInt(SELF_NAME, greaselevel); + RequireSmallInt(SELF_NAME, blocksize); return ProdGF2MatGF2MatAdvanced(ml, mr, INT_INTOBJ(greaselevel), INT_INTOBJ(blocksize)); } @@ -2379,6 +2447,8 @@ static Obj FuncPROD_GF2MAT_GF2MAT_ADVANCED( */ static Obj FuncPROD_GF2MAT_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2MatRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); return ProdGF2MatGF2Vec(vl, vr); } @@ -2389,6 +2459,10 @@ static Obj FuncPROD_GF2MAT_GF2VEC(Obj self, Obj vl, Obj vr) */ static Obj FuncADDCOEFFS_GF2VEC_GF2VEC_MULT(Obj self, Obj vl, Obj vr, Obj mul) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); + RequireFFE(SELF_NAME, mul); + // do nothing if is zero if (EQ(mul, GF2Zero)) { return INTOBJ_INT(RightMostOneGF2Vec(vl)); @@ -2409,6 +2483,8 @@ static Obj FuncADDCOEFFS_GF2VEC_GF2VEC_MULT(Obj self, Obj vl, Obj vr, Obj mul) */ static Obj FuncADDCOEFFS_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); return AddCoeffsGF2VecGF2Vec(vl, vr); } @@ -2425,6 +2501,8 @@ static Obj FuncSHRINKCOEFFS_GF2VEC(Obj self, Obj vec) UInt * ptr; UInt off; + RequireGF2VecRep(SELF_NAME, vec); + // get length and number of blocks len = LEN_GF2VEC(vec); if (len == 0) { @@ -2522,11 +2600,14 @@ static UInt PositionNonZeroGF2Vec(Obj vec, UInt from) static Obj FuncPOSITION_NONZERO_GF2VEC(Obj self, Obj vec, Obj zero) { + RequireGF2VecRep(SELF_NAME, vec); return INTOBJ_INT(PositionNonZeroGF2Vec(vec, 0)); } static Obj FuncPOSITION_NONZERO_GF2VEC3(Obj self, Obj vec, Obj zero, Obj from) { + RequireGF2VecRep(SELF_NAME, vec); + RequireNonnegativeSmallInt(SELF_NAME, from); return INTOBJ_INT(PositionNonZeroGF2Vec(vec, INT_INTOBJ(from))); } @@ -2538,12 +2619,8 @@ static Obj FuncCOPY_SECTION_GF2VECS( Int ito = GetPositiveSmallInt(SELF_NAME, to); Int ihowmany = GetSmallInt(SELF_NAME, howmany); - if (!IS_GF2VEC_REP(src)) { - RequireArgument(SELF_NAME, src, "must be a GF2 vector"); - } - if (!IS_GF2VEC_REP(dest)) { - RequireArgument(SELF_NAME, dest, "must be a GF2 vector"); - } + RequireGF2VecRep(SELF_NAME, src); + RequireGF2VecRep(SELF_NAME, dest); UInt lens = LEN_GF2VEC(src); UInt lend = LEN_GF2VEC(dest); @@ -2566,6 +2643,9 @@ static Obj FuncCOPY_SECTION_GF2VECS( static Obj FuncAPPEND_GF2VEC(Obj self, Obj vecl, Obj vecr) { UInt lenl, lenr; + RequireGF2VecRep(SELF_NAME, vecl); + RequireGF2VecRep(SELF_NAME, vecr); + RequireMutable(SELF_NAME, vecl, "vector"); lenl = LEN_GF2VEC(vecl); lenr = LEN_GF2VEC(vecr); if (True == DoFilter(IsLockedRepresentationVector, vecl) && lenr > 0) { @@ -2586,6 +2666,7 @@ static Obj FuncAPPEND_GF2VEC(Obj self, Obj vecl, Obj vecr) static Obj FuncSHALLOWCOPY_GF2VEC(Obj self, Obj vec) { + RequireGF2VecRep(SELF_NAME, vec); return ShallowCopyVecGF2(vec); } @@ -2603,6 +2684,8 @@ static Obj FuncSUM_GF2MAT_GF2MAT(Obj self, Obj matl, Obj matr) Obj vl, vr, sv; UInt i; Obj rtype; + RequireGF2MatRep(SELF_NAME, matl); + RequireGF2MatRep(SELF_NAME, matr); ll = LEN_GF2MAT(matl); lr = LEN_GF2MAT(matr); if (ll > lr) { @@ -2695,10 +2778,11 @@ static Obj FuncTRANSPOSED_GF2MAT(Obj self, Obj mat) UInt imod, nrb, nstart; UInt i, j, k, n; - if (TNUM_OBJ(mat) != T_POSOBJ) { - ErrorMayQuit("TRANSPOSED_GF2MAT: Need compressed matrix over GF(2)", - 0, 0); - } + RequireGF2MatRep(SELF_NAME, mat); + + if (LEN_GF2MAT(mat) == 0) + return TRY_NEXT_METHOD; + // type for mat typ = TYPE_LIST_GF2MAT; @@ -2780,6 +2864,7 @@ static Obj FuncNUMBER_GF2VEC(Obj self, Obj vec) Obj zahl; // the long number UInt * num2; mp_limb_t * vp; + RequireGF2VecRep(SELF_NAME, vec); len = LEN_GF2VEC(vec); if (len == 0) return INTOBJ_INT(1); @@ -2842,6 +2927,8 @@ static Obj FuncNUMBER_GF2VEC(Obj self, Obj vec) */ static Obj FuncLT_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) { + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); return (Cmp_GF2VEC_GF2VEC(vl, vr) < 0) ? True : False; } @@ -2876,6 +2963,8 @@ static Int Cmp_GF2MAT_GF2MAT(Obj ml, Obj mr) static Obj FuncEQ_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); if (ELM_PLIST(ml, 1) != ELM_PLIST(mr, 1)) return False; return (0 == Cmp_GF2MAT_GF2MAT(ml, mr)) ? True : False; @@ -2888,6 +2977,8 @@ static Obj FuncEQ_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) static Obj FuncLT_GF2MAT_GF2MAT(Obj self, Obj ml, Obj mr) { + RequireGF2MatRep(SELF_NAME, ml); + RequireGF2MatRep(SELF_NAME, mr); return (Cmp_GF2MAT_GF2MAT(ml, mr) < 0) ? True : False; } @@ -2931,6 +3022,8 @@ static Obj FuncDIST_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) UInt * ptL; // bit field of UInt * ptR; // bit field of UInt * end; // pointer used to zero out end bit + RequireGF2VecRep(SELF_NAME, vl); + RequireGF2VecRep(SELF_NAME, vr); // get and check the length len = LEN_GF2VEC(vl); @@ -2938,6 +3031,8 @@ static Obj FuncDIST_GF2VEC_GF2VEC(Obj self, Obj vl, Obj vr) ErrorMayQuit("DIST_GF2VEC_GF2VEC: vectors must have the same length", 0, 0); } + if (len == 0) + return INTOBJ_INT(0); // calculate the offsets ptL = BLOCKS_GF2VEC(vl); @@ -3010,6 +3105,10 @@ static Obj FuncDIST_VEC_CLOS_VEC( Obj sum; // sum vector UInt len; + RequirePlainList(SELF_NAME, veclis); + RequireGF2VecRep(SELF_NAME, vec); + RequirePlainList(SELF_NAME, d); + len = LEN_GF2VEC(vec); // get space for sum vector @@ -3123,6 +3222,9 @@ static Obj FuncA_CLOS_VEC( Obj best; // best vector UInt len; + RequirePlainList(SELF_NAME, veclis); + RequireGF2VecRep(SELF_NAME, vec); + len = LEN_GF2VEC(vec); RequireNonnegativeSmallInt(SELF_NAME, cnt); @@ -3155,6 +3257,9 @@ static Obj FuncA_CLOS_VEC_COORDS( Obj res; // length 2 plist for results UInt len, len2, i; + RequirePlainList(SELF_NAME, veclis); + RequireGF2VecRep(SELF_NAME, vec); + len = LEN_GF2VEC(vec); len2 = LEN_PLIST(veclis); @@ -3293,6 +3398,7 @@ static Obj FuncCOSET_LEADERS_INNER_GF2( static Obj FuncRIGHTMOST_NONZERO_GF2VEC(Obj self, Obj vec) { + RequireGF2VecRep(SELF_NAME, vec); return INTOBJ_INT(RightMostOneGF2Vec(vec)); } @@ -3362,6 +3468,7 @@ static void ResizeGF2Vec(Obj vec, UInt newlen) static Obj FuncRESIZE_GF2VEC(Obj self, Obj vec, Obj newlen) { + RequireGF2VecRep(SELF_NAME, vec); RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, newlen); ResizeGF2Vec(vec, INT_INTOBJ(newlen)); @@ -3421,6 +3528,7 @@ static void ShiftLeftGF2Vec(Obj vec, UInt amount) static Obj FuncSHIFT_LEFT_GF2VEC(Obj self, Obj vec, Obj amount) { + RequireGF2VecRep(SELF_NAME, vec); RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, amount); ShiftLeftGF2Vec(vec, INT_INTOBJ(amount)); @@ -3484,8 +3592,10 @@ static void ShiftRightGF2Vec(Obj vec, UInt amount) static Obj FuncSHIFT_RIGHT_GF2VEC(Obj self, Obj vec, Obj amount, Obj zero) { + RequireGF2VecRep(SELF_NAME, vec); RequireMutable(SELF_NAME, vec, "vector"); RequireNonnegativeSmallInt(SELF_NAME, amount); + RequireFFE(SELF_NAME, zero); ShiftRightGF2Vec(vec, INT_INTOBJ(amount)); return (Obj)0; } @@ -3546,6 +3656,9 @@ static void AddShiftedVecGF2VecGF2(Obj vec1, Obj vec2, UInt len2, UInt off) static Obj FuncADD_GF2VEC_GF2VEC_SHIFTED(Obj self, Obj vec1, Obj vec2, Obj len2, Obj off) { + RequireGF2VecRep(SELF_NAME, vec1); + RequireGF2VecRep(SELF_NAME, vec2); + RequireMutable(SELF_NAME, vec1, "vector"); RequireNonnegativeSmallInt(SELF_NAME, off); RequireNonnegativeSmallInt(SELF_NAME, len2); Int off1 = INT_INTOBJ(off); @@ -3619,8 +3732,8 @@ FuncPROD_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) Obj prod; UInt last; - RequireSmallInt(SELF_NAME, len1); - RequireSmallInt(SELF_NAME, len2); + RequireNonnegativeSmallInt(SELF_NAME, len1); + RequireNonnegativeSmallInt(SELF_NAME, len2); len2a = INT_INTOBJ(len2); if (len2a > LEN_GF2VEC(vec2)) ErrorMayQuit("PROD_COEFFS_GF2VEC: must not be more than the " @@ -3686,6 +3799,9 @@ FuncREDUCE_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) { UInt last; Int len2a; + RequireGF2VecRep(SELF_NAME, vec1); + RequireGF2VecRep(SELF_NAME, vec2); + RequireMutable(SELF_NAME, vec1, "vector"); RequireNonnegativeSmallInt(SELF_NAME, len1); RequireNonnegativeSmallInt(SELF_NAME, len2); if (INT_INTOBJ(len1) > LEN_GF2VEC(vec1)) @@ -3710,7 +3826,7 @@ FuncREDUCE_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) if (len2a == 0) { ErrorReturnVoid("ReduceCoeffs: second argument must not be zero", 0, - 0, "you may 'return;' to skip the reduction"); + 0, "you can enter 'return;' to skip the reduction"); return 0; } @@ -3729,10 +3845,13 @@ static Obj FuncQUOTREM_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) { Int len2a; - Int len1a = INT_INTOBJ(len1); + Int len1a; Obj quotv, remv, ret; + RequireGF2VecRep(SELF_NAME, vec1); + RequireGF2VecRep(SELF_NAME, vec2); RequireNonnegativeSmallInt(SELF_NAME, len1); RequireNonnegativeSmallInt(SELF_NAME, len2); + len1a = INT_INTOBJ(len1); if (INT_INTOBJ(len1) > LEN_GF2VEC(vec1)) ErrorMayQuit("QuotremCoeffs: given length of left argt " "(%d)\nis longer than the argt (%d)", @@ -3753,7 +3872,7 @@ FuncQUOTREM_COEFFS_GF2VEC(Obj self, Obj vec1, Obj len1, Obj vec2, Obj len2) } if (len2a == 0) { ErrorReturnVoid("QuotremCoeffs: second argument must not be zero", 0, - 0, "you may 'return;' to skip the reduction"); + 0, "you can enter 'return;' to skip the reduction"); return 0; } @@ -3791,6 +3910,7 @@ static Obj FuncSEMIECHELON_LIST_GF2VECS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3825,6 +3945,7 @@ static Obj FuncSEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3855,6 +3976,7 @@ static Obj FuncTRIANGULIZE_LIST_GF2VECS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3886,6 +4008,7 @@ static Obj FuncRANK_LIST_GF2VECS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3916,6 +4039,7 @@ static Obj FuncDETERMINANT_LIST_GF2VECS(Obj self, Obj mat) UInt i, len; UInt width; Obj row; + RequirePlainList(SELF_NAME, mat); len = LEN_PLIST(mat); if (!len) return TRY_NEXT_METHOD; @@ -3948,6 +4072,9 @@ static Obj FuncKRONECKERPRODUCT_GF2MAT_GF2MAT(Obj self, Obj matl, Obj matr) UInt * data; const UInt * datar; + RequireGF2MatRep(SELF_NAME, matl); + RequireGF2MatRep(SELF_NAME, matr); + nrowl = LEN_GF2MAT(matl); nrowr = LEN_GF2MAT(matr); nrowp = nrowl * nrowr; @@ -4036,6 +4163,7 @@ static Obj FuncKRONECKERPRODUCT_GF2MAT_GF2MAT(Obj self, Obj matl, Obj matr) */ static Obj FuncMAT_ELM_GF2MAT(Obj self, Obj mat, Obj row, Obj col) { + RequireGF2MatRep(SELF_NAME, mat); UInt r = GetPositiveSmallInt(SELF_NAME, row); UInt c = GetPositiveSmallInt(SELF_NAME, col); @@ -4063,6 +4191,7 @@ static Obj FuncMAT_ELM_GF2MAT(Obj self, Obj mat, Obj row, Obj col) static Obj FuncSET_MAT_ELM_GF2MAT(Obj self, Obj mat, Obj row, Obj col, Obj elm) { + RequireGF2MatRep(SELF_NAME, mat); UInt r = GetPositiveSmallInt(SELF_NAME, row); UInt c = GetPositiveSmallInt(SELF_NAME, col); @@ -4203,6 +4332,7 @@ static Int InitKernel(StructInitInfo * module) InitCopyGVar("TYPE_LIST_GF2VEC_LOCKED", &TYPE_LIST_GF2VEC_LOCKED); ImportFuncFromLibrary("IsGF2VectorRep", &IsGF2VectorRep); + ImportFuncFromLibrary("IsGF2MatrixRep", &IsGF2MatrixRep); InitCopyGVar("TYPE_LIST_GF2MAT", &TYPE_LIST_GF2MAT); InitCopyGVar("TYPE_LIST_GF2MAT_IMM", &TYPE_LIST_GF2MAT_IMM); diff --git a/src/vecgf2.h b/src/vecgf2.h index ddeac8639a..8471236efd 100644 --- a/src/vecgf2.h +++ b/src/vecgf2.h @@ -20,6 +20,13 @@ #define IS_GF2VEC_REP(obj) \ (TNUM_OBJ(obj) == T_DATOBJ && DoFilter(IsGF2VectorRep, obj) == True) +/**************************************************************************** +** +*F IS_GF2MAT_REP( ) . . . . . . check that is in GF2 matrix rep +*/ +#define IS_GF2MAT_REP(obj) \ + (TNUM_OBJ(obj) == T_POSOBJ && DoFilter(IsGF2MatrixRep, obj) == True) + /**************************************************************************** ** @@ -234,6 +241,7 @@ extern Obj TYPE_LIST_GF2MAT_IMM; extern Obj IsGF2VectorRep; +extern Obj IsGF2MatrixRep; Obj ShallowCopyVecGF2(Obj vec); diff --git a/src/weakptr.c b/src/weakptr.c index 8d27774971..f99e8bde37 100644 --- a/src/weakptr.c +++ b/src/weakptr.c @@ -279,7 +279,7 @@ static Obj FuncWeakPointerObj(Obj self, Obj list) static Int LengthWPObj(Obj wp) { - Int changed = 0; + BOOL changed = FALSE; Int len = STORED_LEN_WPOBJ(wp); #ifdef HPCGAP if (!CheckExclusiveWriteAccess(wp)) @@ -291,7 +291,7 @@ static Int LengthWPObj(Obj wp) elm = ELM_WPOBJ(wp, len); if (elm) break; - changed = 1; + changed = TRUE; len--; } if (changed) diff --git a/tst/mockpkg/gap/mockpkg.gi b/tst/mockpkg/gap/mockpkg.gi index 3bcefc9c79..9ef3c4719a 100644 --- a/tst/mockpkg/gap/mockpkg.gi +++ b/tst/mockpkg/gap/mockpkg.gi @@ -13,3 +13,7 @@ InstallMethod( mockpkg_Operation, [ IsGroup, IsPosInt ], { G, n } -> n ); InstallMethod( mockpkg_Attribute, [ IsSolvableGroup ], G -> G ); InstallMethod( mockpkg_Property, [ IsNilpotentGroup ], IsAbelian ); + +BindGlobal( "mockpkg_Vararg", function(first, rest...) + return Concatenation([first], rest); +end ); diff --git a/tst/testbugfix/2012-11-25-t00264.tst b/tst/testbugfix/2012-11-25-t00264.tst index 29e0fb14ee..3d570f79c5 100644 --- a/tst/testbugfix/2012-11-25-t00264.tst +++ b/tst/testbugfix/2012-11-25-t00264.tst @@ -1,9 +1,11 @@ # 2012/11/25 (AK) # Fix of a bug that was reproducible in GAP 4.5.6 with FGA 1.1.1 +# (20/05/26): gap> Image(iso,PreImagesRepresentative(iso,f.1)); +# cannot be made to work because the code for the NC version is in a package gap> f := FreeGroup(2); gap> iso:=GroupHomomorphismByImagesNC(f,f,[f.1*f.2,f.1*f.2^2],[f.2^2*f.1,f.2*f.1]); [ f1*f2, f1*f2^2 ] -> [ f2^2*f1, f2*f1 ] gap> SetIsSurjective(iso,true); -gap> Image(iso,PreImagesRepresentative(iso,f.1)); +gap> Image(iso,PreImagesRepresentativeNC(iso,f.1)); f1 diff --git a/tst/testbugfix/2026-06-05-ConjugateGroup.tst b/tst/testbugfix/2026-06-05-ConjugateGroup.tst new file mode 100644 index 0000000000..bd8e9c0783 --- /dev/null +++ b/tst/testbugfix/2026-06-05-ConjugateGroup.tst @@ -0,0 +1,13 @@ +# Fix an unexpected error in ConjugateGroup when applied to +# a matrix group not over a field +# See https://github.com/gap-system/gap/issues/6423 +gap> G:=SL(2,Integers mod 4);; +gap> H:=ConjugateGroup(G,G.1);; +gap> G = H; +true + +# original test case +gap> S := SylowSubgroup(SL(2,Integers mod 4),2);; +gap> M := MaximalSubgroups(S);; +gap> Length(M); +3 diff --git a/tst/testinstall/ggmbi.tst b/tst/testinstall/ggmbi.tst new file mode 100644 index 0000000000..ad8465bcfc --- /dev/null +++ b/tst/testinstall/ggmbi.tst @@ -0,0 +1,56 @@ +#@local G, U, nice, gens +gap> START_TEST( "ggmbi.tst" ); + +# Test the situations where the global option 'Run_In_GGMBI' occurs. +# - Print warnings when the deprecated global variable is used. +# (Do not use groups that are larger than their natural modules, +# since they could be cached.) +gap> G:= Group( [ [ 0, -1 ], [ 1, 0 ] ] );; +gap> nice:= NiceMonomorphism( G );; +gap> RUN_IN_GGMBI:= true;; +gap> AsGroupGeneralMappingByImages( nice );; +#I use the global option 'Run_In_GGMBI' not the global variable 'RUN_IN_GGMBI', see '?Run_In_GGMBI' +#I use the global option 'Run_In_GGMBI' not the global variable 'RUN_IN_GGMBI', see '?Run_In_GGMBI' +gap> G:= Group( [ [ 0, -1 ], [ 1, 0 ] ] );; +gap> gens:= GeneratorsOfGroup( G );; +gap> IsHandledByNiceMonomorphism( G ); +true +gap> GroupGeneralMappingByImagesNC( G, G, gens, gens );; +#I use the global option 'Run_In_GGMBI' not the global variable 'RUN_IN_GGMBI', see '?Run_In_GGMBI' +gap> RUN_IN_GGMBI:= false;; + +# - Run some examples where the option gets set, +# and where no other tests were available. +gap> G:= GL( IsPermGroup, 2, 5 );; +gap> U:= SL( IsPermGroup, 2, 5 );; +gap> Size( FittingFreeSubgroupSetup( G, U ).ker ); +2 + +# +gap> G:= Image( IsomorphismPermGroup( SchurCover( AlternatingGroup( 6 ) ) ) );; +gap> Size( SylowViaRadical( G, 3 ) ); +27 + +# +gap> G:= GL( IsPermGroup, 2, 5 );; +gap> Length( HallViaRadical( G, [ 2 ] ) ); +1 +gap> Length( HallViaRadical( G, [ 3 ] ) ); +1 + +# +gap> G:= SymmetricGroup( 5 );; +gap> Size( Source( EpimorphismSchurCover( G ) ) ); +240 +gap> G:= AlternatingGroup( 5 );; +gap> Size( Source( EpimorphismSchurCover( G ) ) ); +120 + +# +gap> G:= Group( Z(3) * [ [ [ 1, 1 ], [ 0, 1 ] ] ] );; +gap> Size( Image( SparseActionHomomorphism( G, +> Elements( GF(3)^2 ), [ Z(3) * [ 1, 0 ] ], OnRight ) ) ); +6 + +# +gap> STOP_TEST( "ggmbi.tst" ); diff --git a/tst/testinstall/grppc.tst b/tst/testinstall/grppc.tst index 873257c589..b2501dfc65 100644 --- a/tst/testinstall/grppc.tst +++ b/tst/testinstall/grppc.tst @@ -1,17 +1,25 @@ #@local F,G,S,c,cl,f,g,g1,g10,g3,gens,h,hh,i,m,n,pcgs,r,rws,sys,u,v,x,y,iso gap> START_TEST("grppc.tst"); + +# gap> Display(TrivialGroup(IsPcGroup)); trivial pc-group + +# gap> Display(CyclicGroup(IsPcGroup, 10)); pc-group with 2 pc-generators and relations: g1^2 = g2 g2^5 = id all generators commute, the groups is abelian + +# gap> Display(SymmetricGroup(IsPcGroup, 3)); pc-group with 2 pc-generators and relations: g1^2 = id g2^3 = id g2^g1 = g2^2 + +# gap> h:=Group((1,2,3,4),(1,2));; gap> m:=IsomorphismPcGroup(h);; gap> hh:=Image(m,h);; @@ -30,6 +38,8 @@ all other pairs of generators commute gap> pcgs:=Pcgs(hh);; gap> ForAll(pcgs,i->PreImagesRepresentative(m,i) in h); true + +# gap> g:=WreathProduct(Group((1,2,3),(1,2)),Group((1,2,3,4,5,6,7)));; gap> i:=IsomorphismPcGroup(g);; gap> g:=Range(i);; @@ -183,6 +193,21 @@ true gap> IsIdenticalObj( Range( iso ), ImagesSource( iso ) ); true +# +gap> G:=AlternatingGroup(5);; +gap> IsomorphismPcGroup(G); +fail +gap> IsomorphismSpecialPcGroup(G); +fail +gap> G:=Range(IsomorphismFpGroup(G));; +gap> IsomorphismPcGroup(G); +fail +gap> IsomorphismSpecialPcGroup(G); +fail +gap> IsomorphismPcGroup(FreeGroup(1)); +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 3rd choice method found for `IsomorphismPcGroup' on 1 arguments + # gap> G:= AbelianGroup( IsPcGroup, [ 3, 3, 3 ] );; gap> S:= AbelianGroup( IsPcGroup, [ 3, 3 ] );; diff --git a/tst/testinstall/kernel/gap.tst b/tst/testinstall/kernel/gap.tst index 493afea431..ba82a4c3ca 100644 --- a/tst/testinstall/kernel/gap.tst +++ b/tst/testinstall/kernel/gap.tst @@ -112,9 +112,9 @@ fail gap> CURRENT_STATEMENT_LOCATION(GetCurrentLVars()); fail gap> PRINT_CURRENT_STATEMENT("*errout*", GetCurrentLVars(), fail, 1, 1); +fail gap> f:=function() local l; l:=GetCurrentLVars(); PRINT_CURRENT_STATEMENT("*errout*", l, fail, 1, 1); Print("\n"); end;; f(); PRINT_CURRENT_STATEMENT( "*errout*", l, fail, 1, 1 ); - @ stream:1 # gap> CALL_WITH_CATCH(fail,fail); diff --git a/tst/testinstall/kernel/streams.tst b/tst/testinstall/kernel/streams.tst index ebf5349ae6..12a3859cf5 100644 --- a/tst/testinstall/kernel/streams.tst +++ b/tst/testinstall/kernel/streams.tst @@ -293,7 +293,7 @@ Error, ExecuteProcess: must be a small integer (not the value 'fail') gap> ExecuteProcess("","",0,fail,fail); Error, ExecuteProcess: must be a small integer (not the value 'fail') gap> ExecuteProcess("","",0,0,fail); -Error, ExecuteProcess: must be a small list (not the value 'fail') +Error, ExecuteProcess: must be a plain list (not the value 'fail') gap> ExecuteProcess("","",0,0,[1]); Error, ExecuteProcess: must be a string (not the integer 1) diff --git a/tst/testinstall/kernel/vec8bit.tst b/tst/testinstall/kernel/vec8bit.tst index 6e951a3ef0..b9fe3df7e4 100644 --- a/tst/testinstall/kernel/vec8bit.tst +++ b/tst/testinstall/kernel/vec8bit.tst @@ -2,11 +2,1198 @@ # Tests for functions defined in src/vec8bit.c # gap> START_TEST("kernel/vec8bit.tst"); +gap> q := 5;; +gap> z := 0*Z(q);; +gap> o := Z(q)^0;; +gap> t := Z(q);; +gap> V8 := function(list) +> local v; +> v := ShallowCopy(list); +> CONV_VEC8BIT(v, q); +> return v; +> end;; +gap> M8 := function(rows) +> local m, i; +> m := List(rows, ShallowCopy); +> for i in [1 .. Length(m)] do +> CONV_VEC8BIT(m[i], q); +> od; +> CONV_MAT8BIT(m, q); +> return m; +> end;; +gap> IM8 := function(rows) +> local m; +> m := M8(rows); +> MakeImmutable(m); +> return m; +> end;; +gap> ZeroRowMat8 := function() +> local m; +> m := []; +> CONV_MAT8BIT(m, q); +> return m; +> end;; +gap> Mx08 := n -> M8(List([1 .. n], i -> []));; +gap> Veclis8 := function(rows) +> local f, fdi, fdip, veclis, row, mults, j, mult; +> f := AsSSortedList(GF(q)); +> fdi := []; +> for j in [2 .. Length(f)] do +> fdi[j - 1] := f[j] - f[j - 1]; +> od; +> Add(fdi, -Last(f)); +> fdip := List(fdi, x -> Position(fdi, x)); +> veclis := []; +> for row in rows do +> mults := []; +> mults[Length(fdi) + 1] := false; +> for j in [1 .. Length(fdi)] do +> if fdip[j] < j then +> mult := mults[fdip[j]]; +> else +> mult := fdi[j] * row; +> fi; +> mults[j] := mult; +> od; +> Add(veclis, mults); +> od; +> return veclis; +> end;; +gap> empty := V8([]);; +gap> one := V8([o]);; +gap> oneZero := V8([z]);; +gap> pair := V8([o, t]);; +gap> pair2 := V8([t, o]);; +gap> f5 := AsSSortedList(GF(q));; # +# CONV_VEC8BIT +# +gap> v := [];; CONV_VEC8BIT(v, q); v; +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> CONV_VEC8BIT(fail, q); +Error, CONV_VEC8BIT: must be a small list (not the value 'fail') +gap> CONV_VEC8BIT(v, fail); +Error, CONV_VEC8BIT: must be a positive small integer (not the value 'fail\ +') + +# +# COPY_VEC8BIT +# +gap> v := [];; w := COPY_VEC8BIT(v, q); v; +< mutable compressed vector length 0 over GF(5) > +[ ] + +# bad arguments +gap> COPY_VEC8BIT(fail, q); +Error, COPY_VEC8BIT: must be a small list (not the value 'fail') +gap> COPY_VEC8BIT(v, fail); +Error, COPY_VEC8BIT: must be a positive small integer (not the value 'fail\ +') + +# +# PLAIN_VEC8BIT +# +gap> v := V8([]);; PLAIN_VEC8BIT(v);; IsPlistRep(v); Length(v); +true +0 + +# bad arguments +gap> PLAIN_VEC8BIT(fail); +Error, PLAIN_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fa\ +il') + +# +# LEN_VEC8BIT +# +gap> LEN_VEC8BIT(empty); +0 +gap> LEN_VEC8BIT(pair); +2 + +# bad arguments +gap> LEN_VEC8BIT(fail); +Error, LEN_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') + +# +# ELM0_VEC8BIT +# +gap> ELM0_VEC8BIT(empty, 1); +fail +gap> ELM0_VEC8BIT(one, 1); +Z(5)^0 + +# bad arguments +gap> ELM0_VEC8BIT(fail, 1); +Error, ELM0_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fai\ +l') +gap> ELM0_VEC8BIT(empty, fail); +Error, ELM0_VEC8BIT: must be a positive small integer (not the value 'fa\ +il') + +# +# ELM_VEC8BIT +# +gap> ELM_VEC8BIT(one, 1); +Z(5)^0 + +# bad arguments +gap> ELM_VEC8BIT(fail, 1); +Error, ELM_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') +gap> ELM_VEC8BIT(one, fail); +Error, ELM_VEC8BIT: must be a positive small integer (not the value 'fai\ +l') + +# +# ELMS_VEC8BIT +# +gap> ELMS_VEC8BIT(empty, []) = empty; +true +gap> ELMS_VEC8BIT(pair, [2]); # = V8([t])); +[ Z(5) ] + +# bad arguments +gap> ELMS_VEC8BIT(fail, []); +Error, ELMS_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fai\ +l') +gap> ELMS_VEC8BIT(empty, fail); +Error, ELMS_VEC8BIT: must be a plain list (not the value 'fail') + +# +# ELMS_VEC8BIT_RANGE +# +gap> ELMS_VEC8BIT_RANGE(one, [1 .. 1]); +Error, ELMS_VEC8BIT_RANGE: must be a range (not a strictly-sorted plai\ +n list of cyclotomics) +gap> ELMS_VEC8BIT_RANGE(pair, [1 .. 2]) = pair; +true + +# bad arguments +gap> ELMS_VEC8BIT_RANGE(fail, [1 .. 1]); +Error, ELMS_VEC8BIT_RANGE: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> ELMS_VEC8BIT_RANGE(one, fail); +Error, ELMS_VEC8BIT_RANGE: must be a range (not the value 'fail') + +# +# ASS_VEC8BIT +# +gap> v := V8([]);; ASS_VEC8BIT(v, 1, z);; v = V8([z]); +true +gap> v := [Z(23), Z(23)];; ConvertToVectorRep(v);; ASS_VEC8BIT(v, 1, Z(23^5));; +gap> Is8BitVectorRep(v); +false +gap> v; +[ z, Z(23) ] + +# bad arguments +gap> v := V8([z, z]);; +gap> ASS_VEC8BIT(fail, 1, z); +Error, ASS_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') +gap> ASS_VEC8BIT(v, fail, z); +Error, ASS_VEC8BIT: must be a positive small integer (not the value 'fai\ +l') +gap> ASS_VEC8BIT(v, 1, fail);; +gap> IsPlistRep(v); +true +gap> v; +[ fail, 0*Z(5) ] + +# +# UNB_VEC8BIT +# +gap> v := V8([o]);; UNB_VEC8BIT(v, 1);; v = empty; +true + +# bad arguments +gap> UNB_VEC8BIT(fail, 1); +Error, UNB_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') +gap> UNB_VEC8BIT(v, fail); +Error, UNB_VEC8BIT: must be a positive small integer (not the value 'fai\ +l') + +# +# Q_VEC8BIT +# +gap> Q_VEC8BIT(empty); +5 + +# bad arguments +gap> Q_VEC8BIT(fail); +Error, Q_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail') + +# +# SHALLOWCOPY_VEC8BIT +# +gap> v := SHALLOWCOPY_VEC8BIT(empty);; v = empty and not IsIdenticalObj(v, empty); +true + +# bad arguments +gap> SHALLOWCOPY_VEC8BIT(fail); +Error, SHALLOWCOPY_VEC8BIT: must belong to Is8BitVectorRep (not the val\ +ue 'fail') + +# +# SUM_VEC8BIT_VEC8BIT +# +gap> SUM_VEC8BIT_VEC8BIT(empty, empty); +< mutable compressed vector length 0 over GF(5) > +gap> SUM_VEC8BIT_VEC8BIT(one, oneZero); +[ Z(5)^0 ] + +# bad arguments +gap> SUM_VEC8BIT_VEC8BIT(fail, empty); +Error, SUM_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value\ + 'fail') +gap> SUM_VEC8BIT_VEC8BIT(empty, fail); +Error, SUM_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value\ + 'fail') + +# +# DIFF_VEC8BIT_VEC8BIT +# +gap> DIFF_VEC8BIT_VEC8BIT(empty, empty); +< mutable compressed vector length 0 over GF(5) > +gap> DIFF_VEC8BIT_VEC8BIT(one, oneZero); +[ Z(5)^0 ] + +# bad arguments +gap> DIFF_VEC8BIT_VEC8BIT(fail, empty); +Error, DIFF_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> DIFF_VEC8BIT_VEC8BIT(empty, fail); +Error, DIFF_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') + +# +# PROD_VEC8BIT_FFE +# +gap> PROD_VEC8BIT_FFE(empty, o); +< mutable compressed vector length 0 over GF(5) > +gap> PROD_VEC8BIT_FFE(one, z); +[ 0*Z(5) ] + +# bad arguments +gap> PROD_VEC8BIT_FFE(fail, o); +Error, PROD_VEC8BIT_FFE: must belong to Is8BitVectorRep (not the value '\ +fail') +gap> PROD_VEC8BIT_FFE(empty, fail); +Error, PROD_VEC8BIT_FFE: must be a finite field element (not the value '\ +fail') + +# +# PROD_FFE_VEC8BIT +# +gap> PROD_FFE_VEC8BIT(o, empty); +< mutable compressed vector length 0 over GF(5) > +gap> PROD_FFE_VEC8BIT(z, one); +[ 0*Z(5) ] + +# bad arguments +gap> PROD_FFE_VEC8BIT(fail, empty); +Error, PROD_FFE_VEC8BIT: must be a finite field element (not the value '\ +fail') +gap> PROD_FFE_VEC8BIT(o, fail); +Error, PROD_FFE_VEC8BIT: must belong to Is8BitVectorRep (not the value '\ +fail') + +# +# AINV_VEC8BIT_MUTABLE +# +gap> AINV_VEC8BIT_MUTABLE(empty); +< mutable compressed vector length 0 over GF(5) > +gap> AINV_VEC8BIT_MUTABLE(oneZero); +[ 0*Z(5) ] + +# bad arguments +gap> AINV_VEC8BIT_MUTABLE(fail); +Error, AINV_VEC8BIT_MUTABLE: must belong to Is8BitVectorRep (not the val\ +ue 'fail') + +# +# AINV_VEC8BIT_IMMUTABLE +# +gap> AINV_VEC8BIT_IMMUTABLE(empty); +< immutable compressed vector length 0 over GF(5) > +gap> AINV_VEC8BIT_IMMUTABLE(oneZero); +[ 0*Z(5) ] + +# bad arguments +gap> AINV_VEC8BIT_IMMUTABLE(fail); +Error, AINV_VEC8BIT_IMMUTABLE: must belong to Is8BitVectorRep (not the v\ +alue 'fail') + +# +# AINV_VEC8BIT_SAME_MUTABILITY +# +gap> AINV_VEC8BIT_SAME_MUTABILITY(empty); +< mutable compressed vector length 0 over GF(5) > +gap> AINV_VEC8BIT_SAME_MUTABILITY(oneZero); +[ 0*Z(5) ] + +# bad arguments +gap> AINV_VEC8BIT_SAME_MUTABILITY(fail); +Error, AINV_VEC8BIT_SAME_MUTABILITY: must belong to Is8BitVectorRep (not\ + the value 'fail') + +# +# ZERO_VEC8BIT +# +gap> ZERO_VEC8BIT(empty); +< mutable compressed vector length 0 over GF(5) > +gap> ZERO_VEC8BIT(pair); +[ 0*Z(5), 0*Z(5) ] + +# bad arguments +gap> ZERO_VEC8BIT(fail); +Error, ZERO_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fail\ +') + +# +# ZERO_VEC8BIT_2 +# +gap> ZERO_VEC8BIT_2(q, 0); +< mutable compressed vector length 0 over GF(5) > +gap> ZERO_VEC8BIT_2(q, 2); +[ 0*Z(5), 0*Z(5) ] + +# bad arguments +gap> ZERO_VEC8BIT_2(fail, 0); +Error, ZERO_VEC8BIT_2: must be a positive small integer (not the value 'fa\ +il') +gap> ZERO_VEC8BIT_2(q, fail); +Error, ZERO_VEC8BIT_2: must be a non-negative small integer (not the val\ +ue 'fail') + +# +# EQ_VEC8BIT_VEC8BIT +# +gap> EQ_VEC8BIT_VEC8BIT(empty, empty); +true +gap> EQ_VEC8BIT_VEC8BIT(empty, one); +false + +# bad arguments +gap> EQ_VEC8BIT_VEC8BIT(fail, empty); +Error, EQ_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') +gap> EQ_VEC8BIT_VEC8BIT(empty, fail); +Error, EQ_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') + +# +# LT_VEC8BIT_VEC8BIT +# +gap> LT_VEC8BIT_VEC8BIT(empty, one); +true +gap> LT_VEC8BIT_VEC8BIT(one, empty); +false + +# bad arguments +gap> LT_VEC8BIT_VEC8BIT(fail, one); +Error, LT_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') +gap> LT_VEC8BIT_VEC8BIT(empty, fail); +Error, LT_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') + +# +# PROD_VEC8BIT_VEC8BIT +# +gap> PROD_VEC8BIT_VEC8BIT(empty, empty); +0*Z(5) +gap> PROD_VEC8BIT_VEC8BIT(one, one); +Z(5)^0 + +# bad arguments +gap> PROD_VEC8BIT_VEC8BIT(fail, empty); +Error, PROD_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> PROD_VEC8BIT_VEC8BIT(empty, fail); +Error, PROD_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') + +# +# DISTANCE_VEC8BIT_VEC8BIT +# +gap> DISTANCE_VEC8BIT_VEC8BIT(empty, empty); +0 +gap> DISTANCE_VEC8BIT_VEC8BIT(one, oneZero); +1 + +# bad arguments +gap> DISTANCE_VEC8BIT_VEC8BIT(fail, empty); +Error, DISTANCE_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> DISTANCE_VEC8BIT_VEC8BIT(empty, fail); +Error, DISTANCE_VEC8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the \ +value 'fail') + +# +# ADD_ROWVECTOR_VEC8BITS_5 +# +gap> v := V8([o, z]);; ADD_ROWVECTOR_VEC8BITS_5(v, V8([z, o]), o, 2, 2);; v = V8([o, o]); +true + +# bad arguments +gap> ADD_ROWVECTOR_VEC8BITS_5(fail, V8([z, o]), o, 2, 2); +Error, ADD_ROWVECTOR_VEC8BITS_5: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_5(v, fail, o, 2, 2); +Error, ADD_ROWVECTOR_VEC8BITS_5: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_5(v, V8([z, o]), fail, 2, 2); +Error, ADD_ROWVECTOR_VEC8BITS_5: must be a finite field element (not the\ + value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_5(v, V8([z, o]), o, fail, 2); +Error, ADD_ROWVECTOR_VEC8BITS_5: must be a positive small integer (not \ +the value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_5(v, V8([z, o]), o, 2, fail); +Error, ADD_ROWVECTOR_VEC8BITS_5: must be a positive small integer (not th\ +e value 'fail') + +# +# ADD_ROWVECTOR_VEC8BITS_3 +# +gap> v := V8([]);; ADD_ROWVECTOR_VEC8BITS_3(v, empty, o);; v = empty; +true + +# bad arguments +gap> ADD_ROWVECTOR_VEC8BITS_3(fail, empty, o); +Error, ADD_ROWVECTOR_VEC8BITS_3: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_3(v, fail, o); +Error, ADD_ROWVECTOR_VEC8BITS_3: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_3(v, empty, fail); +Error, ADD_ROWVECTOR_VEC8BITS_3: must be a finite field element (not the\ + value 'fail') + +# +# ADD_ROWVECTOR_VEC8BITS_2 +# +gap> v := V8([]);; ADD_ROWVECTOR_VEC8BITS_2(v, empty);; v = empty; +true + +# bad arguments +gap> ADD_ROWVECTOR_VEC8BITS_2(fail, empty); +Error, ADD_ROWVECTOR_VEC8BITS_2: must belong to Is8BitVectorRep (not the \ +value 'fail') +gap> ADD_ROWVECTOR_VEC8BITS_2(v, fail); +Error, ADD_ROWVECTOR_VEC8BITS_2: must belong to Is8BitVectorRep (not the \ +value 'fail') + +# +# MULT_VECTOR_VEC8BITS +# +gap> v := V8([]);; MULT_VECTOR_VEC8BITS(v, o);; v = empty; +true + +# bad arguments +gap> MULT_VECTOR_VEC8BITS(fail, o); +Error, MULT_VECTOR_VEC8BITS: must belong to Is8BitVectorRep (not the val\ +ue 'fail') +gap> MULT_VECTOR_VEC8BITS(v, fail); +Error, MULT_VECTOR_VEC8BITS: must be a finite field element (not the val\ +ue 'fail') + +# +# POSITION_NONZERO_VEC8BIT +# +gap> POSITION_NONZERO_VEC8BIT(empty, z); +1 +gap> POSITION_NONZERO_VEC8BIT(one, z); +1 + +# bad arguments +gap> POSITION_NONZERO_VEC8BIT(fail, z); +Error, POSITION_NONZERO_VEC8BIT: must belong to Is8BitVectorRep (not th\ +e value 'fail') +gap> POSITION_NONZERO_VEC8BIT(empty, fail); +1 + +# +# POSITION_NONZERO_VEC8BIT3 +# +gap> POSITION_NONZERO_VEC8BIT3(empty, z, 1); +1 +gap> POSITION_NONZERO_VEC8BIT3(V8([z, o]), z, 2); +3 + +# bad arguments +gap> POSITION_NONZERO_VEC8BIT3(fail, z, 1); +Error, POSITION_NONZERO_VEC8BIT3: must belong to Is8BitVectorRep (not t\ +he value 'fail') +gap> POSITION_NONZERO_VEC8BIT3(empty, fail, 1); +1 +gap> POSITION_NONZERO_VEC8BIT3(empty, z, fail); +Error, POSITION_NONZERO_VEC8BIT3: must be a non-negative small integer \ +(not the value 'fail') + +# +# APPEND_VEC8BIT +# +gap> v := V8([]);; APPEND_VEC8BIT(v, one);; v = one; +true + +# bad arguments +gap> APPEND_VEC8BIT(fail, one); +Error, APPEND_VEC8BIT: must belong to Is8BitVectorRep (not the value 'f\ +ail') +gap> APPEND_VEC8BIT(v, fail); +Error, APPEND_VEC8BIT: must belong to Is8BitVectorRep (not the value 'f\ +ail') + +# +# NUMBER_VEC8BIT +# +gap> NUMBER_VEC8BIT(empty); +1 +gap> NUMBER_VEC8BIT(one); +1 + +# bad arguments +gap> NUMBER_VEC8BIT(fail); +Error, NUMBER_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fa\ +il') + +# +# PROD_VEC8BIT_MATRIX +# +gap> PROD_VEC8BIT_MATRIX(one, [fail]); +"TRY_NEXT_METHOD" +gap> PROD_VEC8BIT_MATRIX(one, [one]); +[ Z(5)^0 ] + +# bad arguments +gap> PROD_VEC8BIT_MATRIX(fail, [fail]); +Error, PROD_VEC8BIT_MATRIX: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> PROD_VEC8BIT_MATRIX(one, fail); +Error, PROD_VEC8BIT_MATRIX: must be a plain list (not the value 'fail') + +# +# CONV_MAT8BIT +# +gap> m := [V8([]), V8([])];; CONV_MAT8BIT(m, q);; EQ_MAT8BIT_MAT8BIT(m, Mx08(2)); +true + +# bad arguments +gap> CONV_MAT8BIT(fail, q); +Error, CONV_MAT8BIT: must be a plain list (not the value 'fail') +gap> CONV_MAT8BIT(m, fail); +Error, CONV_MAT8BIT: must be a plain list (not a positional object) + +# +# PLAIN_MAT8BIT +# +gap> m := Mx08(2);; PLAIN_MAT8BIT(m);; IsPlistRep(m) and m = [[], []]; +true + +# bad arguments +gap> PLAIN_MAT8BIT(fail); +Error, PLAIN_MAT8BIT: must belong to Is8BitMatrixRep (not the value 'fai\ +l') + +# +# PROD_VEC8BIT_MAT8BIT +# +gap> PROD_VEC8BIT_MAT8BIT(empty, ZeroRowMat8()); +Error, PROD_VEC8BIT_MAT8BIT: compressed 8bit matrices with empty rows are not \ +supported +gap> PROD_VEC8BIT_MAT8BIT(empty, Mx08(2)); +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> PROD_VEC8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, PROD_VEC8BIT_MAT8BIT: must belong to Is8BitVectorRep (not the val\ +ue 'fail') +gap> PROD_VEC8BIT_MAT8BIT(empty, fail); +Error, PROD_VEC8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the val\ +ue 'fail') + +# +# PROD_MAT8BIT_VEC8BIT +# +gap> PROD_MAT8BIT_VEC8BIT(ZeroRowMat8(), empty); +Error, PROD_MAT8BIT_VEC8BIT: compressed 8bit matrices with empty rows are not \ +supported +gap> PROD_MAT8BIT_VEC8BIT(Mx08(2), empty); +[ 0*Z(5), 0*Z(5) ] + +# bad arguments +gap> PROD_MAT8BIT_VEC8BIT(fail, empty); +Error, PROD_MAT8BIT_VEC8BIT: must belong to Is8BitMatrixRep (not the val\ +ue 'fail') +gap> PROD_MAT8BIT_VEC8BIT(ZeroRowMat8(), fail); +Error, PROD_MAT8BIT_VEC8BIT: must belong to Is8BitVectorRep (not the val\ +ue 'fail') + +# +# PROD_MAT8BIT_MAT8BIT +# +gap> PROD_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +Error, PROD_MAT8BIT_MAT8BIT: compressed 8bit matrices with empty rows are not \ +supported +gap> PROD_MAT8BIT_MAT8BIT(M8([[o], [z]]), Mx08(1)) = Mx08(2); +true + +# bad arguments +gap> PROD_MAT8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, PROD_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the va\ +lue 'fail') +gap> PROD_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, PROD_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the va\ +lue 'fail') + +# +# INV_MAT8BIT_MUTABLE +# +gap> INV_MAT8BIT_MUTABLE(ZeroRowMat8()); +Error, INV_MAT8BIT_MUTABLE: compressed 8bit matrices with empty rows are not s\ +upported +gap> INV_MAT8BIT_MUTABLE(M8([[o]])) = M8([[o]]); +true + +# bad arguments +gap> INV_MAT8BIT_MUTABLE(fail); +Error, INV_MAT8BIT_MUTABLE: must belong to Is8BitMatrixRep (not the valu\ +e 'fail') + +# +# INV_MAT8BIT_SAME_MUTABILITY +# +gap> INV_MAT8BIT_SAME_MUTABILITY(ZeroRowMat8()); +Error, INV_MAT8BIT_SAME_MUTABILITY: compressed 8bit matrices with empty rows a\ +re not supported +gap> INV_MAT8BIT_SAME_MUTABILITY(M8([[o]])) = M8([[o]]); +true + +# bad arguments +gap> INV_MAT8BIT_SAME_MUTABILITY(fail); +Error, INV_MAT8BIT_SAME_MUTABILITY: must belong to Is8BitMatrixRep (not \ +the value 'fail') + +# +# INV_MAT8BIT_IMMUTABLE +# +gap> INV_MAT8BIT_IMMUTABLE(ZeroRowMat8()); +Error, INV_MAT8BIT_IMMUTABLE: compressed 8bit matrices with empty rows are not\ + supported +gap> INV_MAT8BIT_IMMUTABLE(IM8([[o]])) = IM8([[o]]); +true + +# bad arguments +gap> INV_MAT8BIT_IMMUTABLE(fail); +Error, INV_MAT8BIT_IMMUTABLE: must belong to Is8BitMatrixRep (not the va\ +lue 'fail') + +# +# ASS_MAT8BIT +# +gap> ASS_MAT8BIT(ZeroRowMat8(), 1, empty); +Error, ASS_MAT8BIT: compressed 8bit matrices with empty rows are not supported +gap> m := Mx08(1);; ASS_MAT8BIT(m, 2, empty);; m = Mx08(2); +true + +# bad arguments +gap> ASS_MAT8BIT(fail, 1, empty); +Error, ASS_MAT8BIT: must belong to Is8BitMatrixRep (not the value 'fail'\ +) +gap> ASS_MAT8BIT(ZeroRowMat8(), fail, empty); +Error, ASS_MAT8BIT: compressed 8bit matrices with empty rows are not supported +gap> ASS_MAT8BIT(ZeroRowMat8(), 1, fail); +Error, ASS_MAT8BIT: compressed 8bit matrices with empty rows are not supported + +# +# ELM_MAT8BIT +# +gap> ELM_MAT8BIT(Mx08(2), 1); +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> ELM_MAT8BIT(fail, 1); +Error, ELM_MAT8BIT: must belong to Is8BitMatrixRep (not the value 'fail'\ +) +gap> ELM_MAT8BIT(Mx08(2), fail); +Error, ELM_MAT8BIT: must be a positive small integer (not the value 'fai\ +l') + +# +# SWAP_ROWS_MAT8BIT +# +gap> m := Mx08(2);; SWAP_ROWS_MAT8BIT(m, 1, 2);; m = Mx08(2); +true + +# bad arguments +gap> SWAP_ROWS_MAT8BIT(fail, 1, 2); +Error, SWAP_ROWS_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') +gap> SWAP_ROWS_MAT8BIT(m, fail, 2); +Error, SWAP_ROWS_MAT8BIT: must be a small integer (not the value 'fail'\ +) +gap> SWAP_ROWS_MAT8BIT(m, 1, fail); +Error, SWAP_ROWS_MAT8BIT: must be a small integer (not the value 'fail'\ +) + +# +# SWAP_COLS_MAT8BIT +# +gap> m := ZeroRowMat8();; SWAP_COLS_MAT8BIT(m, 1, 1);; EQ_MAT8BIT_MAT8BIT(m, ZeroRowMat8()); +true + +# bad arguments +gap> SWAP_COLS_MAT8BIT(fail, 1, 1); +Error, SWAP_COLS_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') +gap> SWAP_COLS_MAT8BIT(m, fail, 1); +Error, SWAP_COLS_MAT8BIT: must be a small integer (not the value 'fail'\ +) +gap> SWAP_COLS_MAT8BIT(m, 1, fail); +Error, SWAP_COLS_MAT8BIT: must be a small integer (not the value 'fail'\ +) + +# +# SUM_MAT8BIT_MAT8BIT +# +gap> SUM_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +Error, SUM_MAT8BIT_MAT8BIT: compressed 8bit matrices with empty rows are not s\ +upported +gap> SUM_MAT8BIT_MAT8BIT(Mx08(2), Mx08(2)) = Mx08(2); +true + +# bad arguments +gap> SUM_MAT8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, SUM_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value\ + 'fail') +gap> SUM_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, SUM_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value\ + 'fail') + +# +# DIFF_MAT8BIT_MAT8BIT +# +gap> DIFF_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +Error, DIFF_MAT8BIT_MAT8BIT: compressed 8bit matrices with empty rows are not \ +supported +gap> DIFF_MAT8BIT_MAT8BIT(Mx08(2), Mx08(2)) = Mx08(2); +true + +# bad arguments +gap> DIFF_MAT8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, DIFF_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the valu\ +e 'fail') +gap> DIFF_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, DIFF_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the valu\ +e 'fail') + +# +# ADD_COEFFS_VEC8BIT_3 +# +gap> v := V8([]);; ADD_COEFFS_VEC8BIT_3(v, empty, o); +0 +gap> v; +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> ADD_COEFFS_VEC8BIT_3(fail, empty, o); +Error, ADD_COEFFS_VEC8BIT_3: must belong to Is8BitVectorRep (not the va\ +lue 'fail') +gap> ADD_COEFFS_VEC8BIT_3(v, fail, o); +Error, ADD_COEFFS_VEC8BIT_3: must belong to Is8BitVectorRep (not the va\ +lue 'fail') +gap> ADD_COEFFS_VEC8BIT_3(v, empty, fail); +Error, ADD_COEFFS_VEC8BIT_3: must be a finite field element (not the va\ +lue 'fail') + +# +# ADD_COEFFS_VEC8BIT_2 +# +gap> v := V8([]);; ADD_COEFFS_VEC8BIT_2(v, empty); +0 +gap> v; +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> ADD_COEFFS_VEC8BIT_2(fail, empty); +Error, ADD_COEFFS_VEC8BIT_2: must belong to Is8BitVectorRep (not the va\ +lue 'fail') +gap> ADD_COEFFS_VEC8BIT_2(v, fail); +Error, ADD_COEFFS_VEC8BIT_2: must belong to Is8BitVectorRep (not the va\ +lue 'fail') + +# +# SHIFT_VEC8BIT_LEFT +# +gap> v := V8([]);; SHIFT_VEC8BIT_LEFT(v, 3);; v = empty; +true + +# bad arguments +gap> SHIFT_VEC8BIT_LEFT(fail, 3); +Error, SHIFT_VEC8BIT_LEFT: must belong to Is8BitVectorRep (not the value\ + 'fail') +gap> SHIFT_VEC8BIT_LEFT(v, fail); +Error, SHIFT_VEC8BIT_LEFT: must be a non-negative small integer (not \ +the value 'fail') + +# +# SHIFT_VEC8BIT_RIGHT +# +gap> v := V8([]);; SHIFT_VEC8BIT_RIGHT(v, 3, z);; v = V8([z, z, z]); +true + +# bad arguments +gap> SHIFT_VEC8BIT_RIGHT(fail, 3, z); +Error, SHIFT_VEC8BIT_RIGHT: must belong to Is8BitVectorRep (not the valu\ +e 'fail') +gap> SHIFT_VEC8BIT_RIGHT(v, fail, z); +Error, SHIFT_VEC8BIT_RIGHT: must be a non-negative small integer (not\ + the value 'fail') +gap> SHIFT_VEC8BIT_RIGHT(v, 3, fail); +Error, SHIFT_VEC8BIT_RIGHT: must be a finite field element (not the val\ +ue 'fail') + +# +# RESIZE_VEC8BIT +# +gap> v := V8([]);; RESIZE_VEC8BIT(v, 2);; v = V8([z, z]); +true + +# bad arguments +gap> RESIZE_VEC8BIT(fail, 2); +Error, RESIZE_VEC8BIT: must belong to Is8BitVectorRep (not the value 'fa\ +il') +gap> RESIZE_VEC8BIT(v, fail); +Error, RESIZE_VEC8BIT: must be a non-negative small integer (not the\ + value 'fail') + +# +# RIGHTMOST_NONZERO_VEC8BIT +# +gap> RIGHTMOST_NONZERO_VEC8BIT(empty); +0 +gap> RIGHTMOST_NONZERO_VEC8BIT(V8([z, o])); +2 + +# bad arguments +gap> RIGHTMOST_NONZERO_VEC8BIT(fail); +Error, RIGHTMOST_NONZERO_VEC8BIT: must belong to Is8BitVectorRep (not th\ +e value 'fail') + +# +# PROD_COEFFS_VEC8BIT +# +gap> PROD_COEFFS_VEC8BIT(empty, 0, empty, 0); +< mutable compressed vector length 0 over GF(5) > +gap> PROD_COEFFS_VEC8BIT(one, 1, one, 1); +[ Z(5)^0 ] + +# bad arguments +gap> PROD_COEFFS_VEC8BIT(fail, 0, empty, 0); +Error, PROD_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not the value\ + 'fail') +gap> PROD_COEFFS_VEC8BIT(empty, fail, empty, 0); +Error, PROD_COEFFS_VEC8BIT: must be a non-negative small integer (not the\ + value 'fail') +gap> PROD_COEFFS_VEC8BIT(empty, 0, fail, 0); +Error, PROD_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not the value\ + 'fail') +gap> PROD_COEFFS_VEC8BIT(empty, 0, empty, fail); +Error, PROD_COEFFS_VEC8BIT: must be a non-negative small integer (not the\ + value 'fail') + +# +# REDUCE_COEFFS_VEC8BIT +# +gap> s := MAKE_SHIFTED_COEFFS_VEC8BIT(V8([o]), 1);; +gap> v := V8([o]);; REDUCE_COEFFS_VEC8BIT(v, 1, s); +0 +gap> v; +< mutable compressed vector length 0 over GF(5) > + +# bad arguments +gap> REDUCE_COEFFS_VEC8BIT(fail, 1, s); +Error, REDUCE_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not the val\ +ue 'fail') +gap> REDUCE_COEFFS_VEC8BIT(v, fail, s); +Error, REDUCE_COEFFS_VEC8BIT: must be a non-negative small integer (not t\ +he value 'fail') +gap> REDUCE_COEFFS_VEC8BIT(v, 1, fail); +Error, REDUCE_COEFFS_VEC8BIT: must be a plain list (not the value \ +'fail') + +# +# QUOTREM_COEFFS_VEC8BIT +# +gap> s := MAKE_SHIFTED_COEFFS_VEC8BIT(V8([o]), 1);; +gap> QUOTREM_COEFFS_VEC8BIT(empty, 0, s); +[ < mutable compressed vector length 0 over GF(5) >, + < mutable compressed vector length 0 over GF(5) > ] + +# bad arguments +gap> QUOTREM_COEFFS_VEC8BIT(fail, 0, s); +Error, QUOTREM_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not the va\ +lue 'fail') +gap> QUOTREM_COEFFS_VEC8BIT(empty, fail, s); +Error, QUOTREM_COEFFS_VEC8BIT: must be a non-negative small integer (not \ +the value 'fail') +gap> QUOTREM_COEFFS_VEC8BIT(empty, 0, fail); +Error, QUOTREM_COEFFS_VEC8BIT: must be a plain list (not the value\ + 'fail') + +# +# MAKE_SHIFTED_COEFFS_VEC8BIT +# +gap> s := MAKE_SHIFTED_COEFFS_VEC8BIT(V8([o]), 1);; s[4]; +1 +gap> s[5]; +Z(5)^0 + +# bad arguments +gap> MAKE_SHIFTED_COEFFS_VEC8BIT(fail, 1); +Error, MAKE_SHIFTED_COEFFS_VEC8BIT: must belong to Is8BitVectorRep (not t\ +he value 'fail') +gap> MAKE_SHIFTED_COEFFS_VEC8BIT(V8([o]), fail); +Error, MAKE_SHIFTED_COEFFS_VEC8BIT: must be a non-negative small integer \ +(not the value 'fail') + +# +# DISTANCE_DISTRIB_VEC8BITS +# +gap> d := [0, 0];; DISTANCE_DISTRIB_VEC8BITS(Veclis8([one]), oneZero, d);; d; +[ 1, 4 ] + +# bad arguments +gap> DISTANCE_DISTRIB_VEC8BITS(fail, oneZero, d); +Error, DISTANCE_DISTRIB_VEC8BITS: must be a plain list (not the value\ + 'fail') +gap> DISTANCE_DISTRIB_VEC8BITS(Veclis8([one]), fail, d); +Error, DISTANCE_DISTRIB_VEC8BITS: must belong to Is8BitVectorRep (not th\ +e value 'fail') +gap> DISTANCE_DISTRIB_VEC8BITS(Veclis8([one]), oneZero, fail); +Error, DISTANCE_DISTRIB_VEC8BITS: must be a plain list (not the value 'fai\ +l') + +# +# A_CLOSEST_VEC8BIT +# +gap> A_CLOSEST_VEC8BIT(Veclis8([one]), one, 0, 0); +[ Z(5)^0 ] + +# bad arguments +gap> A_CLOSEST_VEC8BIT(fail, one, 0, 0); +Error, A_CLOSEST_VEC8BIT: must be a plain list (not the value 'fail') +gap> A_CLOSEST_VEC8BIT(Veclis8([one]), fail, 0, 0); +Error, A_CLOSEST_VEC8BIT: must belong to Is8BitVectorRep (not the value \ +'fail') +gap> A_CLOSEST_VEC8BIT(Veclis8([one]), one, fail, 0); +Error, A_CLOSEST_VEC8BIT: must be a non-negative small integer (not the \ +value 'fail') +gap> A_CLOSEST_VEC8BIT(Veclis8([one]), one, 0, fail); +Error, A_CLOSEST_VEC8BIT: must be a non-negative small integer (not the\ + value 'fail') + +# +# A_CLOSEST_VEC8BIT_COORDS +# +gap> A_CLOSEST_VEC8BIT_COORDS(Veclis8([one]), one, 0, 0); +[ [ Z(5)^0 ], [ 1 ] ] + +# bad arguments +gap> A_CLOSEST_VEC8BIT_COORDS(fail, one, 0, 0); +Error, A_CLOSEST_VEC8BIT_COORDS: must be a plain list (not the value \ +'fail') +gap> A_CLOSEST_VEC8BIT_COORDS(Veclis8([one]), fail, 0, 0); +Error, A_CLOSEST_VEC8BIT_COORDS: must belong to Is8BitVectorRep (not the\ + value 'fail') +gap> A_CLOSEST_VEC8BIT_COORDS(Veclis8([one]), one, fail, 0); +Error, A_CLOSEST_VEC8BIT_COORDS: must be a non-negative small integer (n\ +ot the value 'fail') +gap> A_CLOSEST_VEC8BIT_COORDS(Veclis8([one]), one, 0, fail); +Error, A_CLOSEST_VEC8BIT_COORDS: must be a non-negative small integer (\ +not the value 'fail') + +# +# COSET_LEADERS_INNER_8BITS +# +gap> leaders := [Immutable(oneZero)];; leaders[6] := false;; + +#gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), 1, 1, leaders, f5); +#4 +#gap> leaders[2]; +#[ Z(5)^0 ] +# +# bad arguments +gap> COSET_LEADERS_INNER_8BITS(fail, 1, 1, leaders, f5); +Error, COSET_LEADERS_INNER_8BITS: must be a plain list (not the value\ + 'fail') +gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), fail, 1, leaders, f5); +Error, COSET_LEADERS_INNER_8BITS: must be a small integer (not the va\ +lue 'fail') +gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), 1, fail, leaders, f5); +Error, COSET_LEADERS_INNER_8BITS: must be a small integer (not the va\ +lue 'fail') +gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), 1, 1, fail, f5); +Error, COSET_LEADERS_INNER_8BITS: must be a plain list (not the valu\ +e 'fail') +gap> COSET_LEADERS_INNER_8BITS(Veclis8([one]), 1, 1, leaders, fail); +Error, COSET_LEADERS_INNER_8BITS: must be a plain list (not the value \ +'fail') + +# +# SEMIECHELON_LIST_VEC8BITS +# +gap> s := SEMIECHELON_LIST_VEC8BITS([one]);; s.heads = [1] and s.vectors = [one]; +true + +# bad arguments +gap> SEMIECHELON_LIST_VEC8BITS(fail); +Error, SEMIECHELON_LIST_VEC8BITS: must be a plain list (not the value 'f\ +ail') + +# +# SEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS +# +gap> s := SEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS([one]);; s.heads = [1] and s.vectors = [one] and s.coeffs = [one]; +true + +# bad arguments +gap> SEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS(fail); +Error, SEMIECHELON_LIST_VEC8BITS_TRANSFORMATIONS: must be a plain list (\ +not the value 'fail') + +# +# TRIANGULIZE_LIST_VEC8BITS +# +gap> m := [one];; TRIANGULIZE_LIST_VEC8BITS(m);; m = [one]; +true + +# bad arguments +gap> TRIANGULIZE_LIST_VEC8BITS(fail); +Error, TRIANGULIZE_LIST_VEC8BITS: must be a plain list (not the value 'f\ +ail') + +# +# RANK_LIST_VEC8BITS +# +gap> RANK_LIST_VEC8BITS([one]); +1 + +# bad arguments +gap> RANK_LIST_VEC8BITS(fail); +Error, RANK_LIST_VEC8BITS: must be a plain list (not the value 'fail') + +# +# DETERMINANT_LIST_VEC8BITS +# +gap> DETERMINANT_LIST_VEC8BITS([one]); +Z(5)^0 + +# bad arguments +gap> DETERMINANT_LIST_VEC8BITS(fail); +Error, DETERMINANT_LIST_VEC8BITS: must be a plain list (not the value 'f\ +ail') + +# +# EQ_MAT8BIT_MAT8BIT +# +gap> EQ_MAT8BIT_MAT8BIT(Mx08(2), Mx08(2)) and EQ_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +true + +# bad arguments +gap> EQ_MAT8BIT_MAT8BIT(fail, Mx08(2)); +Error, EQ_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') +gap> EQ_MAT8BIT_MAT8BIT(Mx08(2), fail); +Error, EQ_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') + +# +# LT_MAT8BIT_MAT8BIT +# +gap> LT_MAT8BIT_MAT8BIT(ZeroRowMat8(), Mx08(1)) and not LT_MAT8BIT_MAT8BIT(Mx08(1), ZeroRowMat8()); +true + +# bad arguments +gap> LT_MAT8BIT_MAT8BIT(fail, Mx08(1)); +Error, LT_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') +gap> LT_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, LT_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep (not the value \ +'fail') + +# +# TRANSPOSED_MAT8BIT +# +gap> TRANSPOSED_MAT8BIT(ZeroRowMat8()); +Error, TRANSPOSED_MAT8BIT: compressed 8bit matrices with empty rows are not su\ +pported +gap> EQ_MAT8BIT_MAT8BIT(TRANSPOSED_MAT8BIT(Mx08(2)), ZeroRowMat8()); +true + +# bad arguments gap> TRANSPOSED_MAT8BIT(fail); Error, TRANSPOSED_MAT8BIT: must belong to Is8BitMatrixRep (not the value\ 'fail') +# +# KRONECKERPRODUCT_MAT8BIT_MAT8BIT +# +gap> KRONECKERPRODUCT_MAT8BIT_MAT8BIT(ZeroRowMat8(), ZeroRowMat8()); +Error, KRONECKERPRODUCT_MAT8BIT_MAT8BIT: compressed 8bit matrices with empty r\ +ows are not supported +gap> KRONECKERPRODUCT_MAT8BIT_MAT8BIT(Mx08(2), M8([[o]])) = Mx08(2); +true + +# bad arguments +gap> KRONECKERPRODUCT_MAT8BIT_MAT8BIT(fail, ZeroRowMat8()); +Error, KRONECKERPRODUCT_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep\ + (not the value 'fail') +gap> KRONECKERPRODUCT_MAT8BIT_MAT8BIT(ZeroRowMat8(), fail); +Error, KRONECKERPRODUCT_MAT8BIT_MAT8BIT: must belong to Is8BitMatrixRep\ + (not the value 'fail') + +# +# MAT_ELM_MAT8BIT +# +gap> MAT_ELM_MAT8BIT(M8([[o]]), 1, 1); +Z(5)^0 + +# bad arguments +gap> MAT_ELM_MAT8BIT(fail, 1, 1); +Error, MAT_ELM_MAT8BIT: must belong to Is8BitMatrixRep (not the value 'f\ +ail') +gap> MAT_ELM_MAT8BIT(M8([[o]]), fail, 1); +Error, MAT_ELM_MAT8BIT: must be a positive small integer (not the value \ +'fail') +gap> MAT_ELM_MAT8BIT(M8([[o]]), 1, fail); +Error, MAT_ELM_MAT8BIT: must be a positive small integer (not the value \ +'fail') + +# +# SET_MAT_ELM_MAT8BIT +# +gap> m := M8([[z]]);; SET_MAT_ELM_MAT8BIT(m, 1, 1, o);; m = M8([[o]]); +true + +# bad arguments +gap> SET_MAT_ELM_MAT8BIT(fail, 1, 1, o); +Error, SET_MAT_ELM_MAT8BIT: must belong to Is8BitMatrixRep (not the valu\ +e 'fail') +gap> SET_MAT_ELM_MAT8BIT(m, fail, 1, o); +Error, SET_MAT_ELM_MAT8BIT: must be a positive small integer (not the va\ +lue 'fail') +gap> SET_MAT_ELM_MAT8BIT(m, 1, fail, o); +Error, SET_MAT_ELM_MAT8BIT: must be a positive small integer (not the va\ +lue 'fail') +gap> SET_MAT_ELM_MAT8BIT(m, 1, 1, fail); +Error, Attempt to convert locked compressed vector to plain list + # gap> STOP_TEST("kernel/vec8bit.tst"); diff --git a/tst/testinstall/kernel/vecgf2.tst b/tst/testinstall/kernel/vecgf2.tst index 7c4a838349..c3021d52cb 100644 --- a/tst/testinstall/kernel/vecgf2.tst +++ b/tst/testinstall/kernel/vecgf2.tst @@ -2,10 +2,981 @@ # Tests for functions defined in src/vecgf2.c # gap> START_TEST("kernel/vecgf2.tst"); +gap> z := 0*Z(2);; +gap> o := Z(2)^0;; +gap> V2 := function(list) +> local v; +> v := ShallowCopy(list); +> CONV_GF2VEC(v); +> return v; +> end;; +gap> M2 := function(rows) +> local m, i; +> m := List(rows, ShallowCopy); +> for i in [1 .. Length(m)] do +> CONV_GF2VEC(m[i]); +> od; +> CONV_GF2MAT(m); +> return m; +> end;; +gap> Mx02 := n -> M2(List([1 .. n], i -> []));; +gap> Veclis2 := function(rows) +> local f, fdi, fdip, veclis, row, mults, j, mult; +> f := AsSSortedList(GF(2)); +> fdi := []; +> for j in [2 .. Length(f)] do +> fdi[j - 1] := f[j] - f[j - 1]; +> od; +> Add(fdi, -Last(f)); +> fdip := List(fdi, x -> Position(fdi, x)); +> veclis := []; +> for row in rows do +> mults := []; +> mults[Length(fdi) + 1] := false; +> for j in [1 .. Length(fdi)] do +> if fdip[j] < j then +> mult := mults[fdip[j]]; +> else +> mult := fdi[j] * row; +> fi; +> mults[j] := mult; +> od; +> Add(veclis, mults); +> od; +> return veclis; +> end;; +gap> empty := V2([]);; +gap> one := V2([o]);; +gap> oneZero := V2([z]);; # +# CONV_GF2VEC +# +gap> v := [];; CONV_GF2VEC(v); v; + + +# bad arguments +gap> CONV_GF2VEC(fail); +Error, CONV_GF2VEC: must be a small list (not the value 'fail') + +# +# COPY_GF2VEC +# +gap> v := COPY_GF2VEC([]); + + +# bad arguments +gap> COPY_GF2VEC(fail); +Error, COPY_GF2VEC: argument must be a list of GF2 elements + +# +# PLAIN_GF2VEC +# +gap> v := V2([]);; PLAIN_GF2VEC(v);; IsPlistRep(v) and Length(v) = 0; +true + +# bad arguments +gap> PLAIN_GF2VEC(fail); +Error, PLAIN_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# PLAIN_GF2MAT +# +gap> m := Mx02(2);; PLAIN_GF2MAT(m);; IsPlistRep(m) and m = [[], []]; +true + +# bad arguments +gap> PLAIN_GF2MAT(fail); +Error, PLAIN_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# EQ_GF2VEC_GF2VEC +# +gap> EQ_GF2VEC_GF2VEC(empty, empty); +true +gap> EQ_GF2VEC_GF2VEC(empty, one); +false + +# bad arguments +gap> EQ_GF2VEC_GF2VEC(fail, empty); +Error, EQ_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> EQ_GF2VEC_GF2VEC(empty, fail); +Error, EQ_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# LT_GF2VEC_GF2VEC +# +gap> LT_GF2VEC_GF2VEC(oneZero, one); +true +gap> LT_GF2VEC_GF2VEC(one, oneZero); +false + +# bad arguments +gap> LT_GF2VEC_GF2VEC(fail, one); +Error, LT_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> LT_GF2VEC_GF2VEC(oneZero, fail); +Error, LT_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# EQ_GF2MAT_GF2MAT +# +gap> EQ_GF2MAT_GF2MAT(Mx02(2), Mx02(2)); +true +gap> EQ_GF2MAT_GF2MAT(Mx02(1), Mx02(2)); +false + +# bad arguments +gap> EQ_GF2MAT_GF2MAT(fail, Mx02(2)); +Error, EQ_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> EQ_GF2MAT_GF2MAT(Mx02(2), fail); +Error, EQ_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# LT_GF2MAT_GF2MAT +# +gap> LT_GF2MAT_GF2MAT(Mx02(1), Mx02(2)); +true +gap> LT_GF2MAT_GF2MAT(Mx02(2), Mx02(1)); +false + +# bad arguments +gap> LT_GF2MAT_GF2MAT(fail, Mx02(2)); +Error, LT_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> LT_GF2MAT_GF2MAT(Mx02(1), fail); +Error, LT_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# LEN_GF2VEC +# +gap> LEN_GF2VEC(empty); +0 +gap> LEN_GF2VEC(V2([o, z])); +2 + +# bad arguments +gap> LEN_GF2VEC(fail); +Error, LEN_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# ELM0_GF2VEC +# +gap> ELM0_GF2VEC(empty, 1); +fail +gap> ELM0_GF2VEC(one, 1); +Z(2)^0 + +# bad arguments +gap> ELM0_GF2VEC(fail, 1); +Error, ELM0_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> ELM0_GF2VEC(empty, fail); +Error, ELM0_GF2VEC: must be a small integer (not the value 'fail') + +# +# ELM_GF2VEC +# +gap> ELM_GF2VEC(one, 1); +Z(2)^0 + +# bad arguments +gap> ELM_GF2VEC(fail, 1); +Error, ELM_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> ELM_GF2VEC(one, fail); +Error, ELM_GF2VEC: must be a small integer (not the value 'fail') + +# +# ELMS_GF2VEC +# +gap> ELMS_GF2VEC(empty, []) = empty; +true +gap> ELMS_GF2VEC(V2([o, z]), [1]); + + +# bad arguments +gap> ELMS_GF2VEC(fail, []); +Error, ELMS_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> ELMS_GF2VEC(empty, fail); +Error, Length: must be a list (not the value 'fail') + +# +# ASS_GF2VEC +# +gap> v := V2([]);; ASS_GF2VEC(v, 1, z);; v = oneZero; +true + +# bad arguments +gap> ASS_GF2VEC(fail, 1, z); +Error, ASS_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> ASS_GF2VEC(v, fail, z); +Error, ASS_GF2VEC: must be a small integer (not the value 'fail') +gap> ASS_GF2VEC(v, 1, fail); + +# +# ELM_GF2MAT +# +gap> ELM_GF2MAT(Mx02(2), 1); + + +# bad arguments +gap> ELM_GF2MAT(fail, 1); +Error, ELM_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> ELM_GF2MAT(Mx02(2), fail); +Error, ELM_GF2MAT: must be a small integer (not the value 'fail') + +# +# ASS_GF2MAT +# +gap> m := M2([[]]);; ASS_GF2MAT(m, 2, empty);; m = Mx02(2); +true + +# bad arguments +gap> ASS_GF2MAT(fail, 2, empty); +Error, ASS_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> ASS_GF2MAT(m, fail, empty); +Error, ASS_GF2MAT: must be a small integer (not the value 'fail') +gap> ASS_GF2MAT(m, 2, fail); + +# +# SWAP_ROWS_GF2MAT +# +gap> m := M2([[o], [z]]);; SWAP_ROWS_GF2MAT(m, 1, 2);; m = M2([[z], [o]]); +true + +# bad arguments +gap> SWAP_ROWS_GF2MAT(fail, 1, 2); +Error, SWAP_ROWS_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> SWAP_ROWS_GF2MAT(m, fail, 2); +Error, SWAP_ROWS_GF2MAT: must be a small integer (not the value 'fail') +gap> SWAP_ROWS_GF2MAT(m, 1, fail); +Error, SWAP_ROWS_GF2MAT: must be a small integer (not the value 'fail') + +# +# SWAP_COLS_GF2MAT +# +gap> m := M2([[o, z]]);; SWAP_COLS_GF2MAT(m, 1, 2);; m = M2([[z, o]]); +true + +# bad arguments +gap> SWAP_COLS_GF2MAT(fail, 1, 2); +Error, SWAP_COLS_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> SWAP_COLS_GF2MAT(m, fail, 2); +Error, SWAP_COLS_GF2MAT: must be a small integer (not the value 'fail') +gap> SWAP_COLS_GF2MAT(m, 1, fail); +Error, SWAP_COLS_GF2MAT: must be a small integer (not the value 'fail') + +# +# UNB_GF2VEC +# +gap> v := V2([o]);; UNB_GF2VEC(v, 1);; v = empty; +true + +# bad arguments +gap> UNB_GF2VEC(fail, 1); +Error, UNB_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> UNB_GF2VEC(v, fail); +Error, UNB_GF2VEC: must be a small integer (not the value 'fail') + +# +# UNB_GF2MAT +# +gap> m := M2([[]]);; UNB_GF2MAT(m, 1);; m = []; +true + +# bad arguments +gap> UNB_GF2MAT(fail, 1); +Error, UNB_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> UNB_GF2MAT(m, fail); +Error, UNB_GF2MAT: must be a small integer (not the value 'fail') + +# +# ZERO_GF2VEC +# +gap> ZERO_GF2VEC(empty); + +gap> ZERO_GF2VEC(V2([o, z])); + + +# bad arguments +gap> ZERO_GF2VEC(fail); +Error, ZERO_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# ZERO_GF2VEC_2 +# +gap> ZERO_GF2VEC_2(0); + +gap> ZERO_GF2VEC_2(2); + + +# bad arguments +gap> ZERO_GF2VEC_2(fail); +Error, ZERO_GF2VEC_2: must be a non-negative small integer (not the valu\ +e 'fail') + +# +# INV_GF2MAT_MUTABLE +# +gap> INV_GF2MAT_MUTABLE(M2([[o]])) = M2([[o]]); +true + +# bad arguments +gap> INV_GF2MAT_MUTABLE(fail); +Error, INV_GF2MAT_MUTABLE: must be a GF2 matrix (not the value 'fail') + +# +# INV_GF2MAT_SAME_MUTABILITY +# +gap> INV_GF2MAT_SAME_MUTABILITY(M2([[o]])) = M2([[o]]); +true + +# bad arguments +gap> INV_GF2MAT_SAME_MUTABILITY(fail); +Error, INV_GF2MAT_SAME_MUTABILITY: must be a GF2 matrix (not the value '\ +fail') + +# +# INV_GF2MAT_IMMUTABLE +# +gap> INV_GF2MAT_IMMUTABLE(Immutable(M2([[o]]))) = Immutable(M2([[o]])); +true + +# bad arguments +gap> INV_GF2MAT_IMMUTABLE(fail); +Error, INV_GF2MAT_IMMUTABLE: must be a GF2 matrix (not the value 'fail') + +# +# INV_PLIST_GF2VECS_DESTRUCTIVE +# +gap> m := [one];; INV_PLIST_GF2VECS_DESTRUCTIVE(m) = [one] and m = [one]; +true + +# bad arguments +gap> INV_PLIST_GF2VECS_DESTRUCTIVE(fail); +Error, INV_PLIST_GF2VECS_DESTRUCTIVE: must be a plain list (not the val\ +ue 'fail') + +# +# SUM_GF2VEC_GF2VEC +# +gap> SUM_GF2VEC_GF2VEC(empty, empty); + +gap> SUM_GF2VEC_GF2VEC(one, one); + + +# bad arguments +gap> SUM_GF2VEC_GF2VEC(fail, empty); +Error, SUM_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> SUM_GF2VEC_GF2VEC(empty, fail); +Error, SUM_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# PROD_GF2VEC_GF2VEC +# +gap> PROD_GF2VEC_GF2VEC(one, one); +Z(2)^0 + +# bad arguments +gap> PROD_GF2VEC_GF2VEC(fail, one); +Error, PROD_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> PROD_GF2VEC_GF2VEC(one, fail); +Error, PROD_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# PROD_GF2VEC_GF2MAT +# +gap> PROD_GF2VEC_GF2MAT(empty, Mx02(2)); + + +# bad arguments +gap> PROD_GF2VEC_GF2MAT(fail, Mx02(2)); +Error, PROD_GF2VEC_GF2MAT: must be a GF2 vector (not the value 'fail') +gap> PROD_GF2VEC_GF2MAT(empty, fail); +Error, PROD_GF2VEC_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# PROD_GF2MAT_GF2VEC +# +gap> PROD_GF2MAT_GF2VEC(Mx02(2), empty); + + +# bad arguments +gap> PROD_GF2MAT_GF2VEC(fail, empty); +Error, PROD_GF2MAT_GF2VEC: must be a GF2 matrix (not the value 'fail') +gap> PROD_GF2MAT_GF2VEC(Mx02(2), fail); +Error, PROD_GF2MAT_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# PROD_GF2MAT_GF2MAT +# +gap> PROD_GF2MAT_GF2MAT(M2([[o], [z]]), Mx02(1)) = Mx02(2); +true + +# bad arguments +gap> PROD_GF2MAT_GF2MAT(fail, Mx02(1)); +Error, PROD_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> PROD_GF2MAT_GF2MAT(M2([[o], [z]]), fail); +Error, PROD_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# PROD_GF2MAT_GF2MAT_SIMPLE +# +gap> PROD_GF2MAT_GF2MAT_SIMPLE(M2([[o], [z]]), Mx02(1)) = Mx02(2); +true + +# bad arguments +gap> PROD_GF2MAT_GF2MAT_SIMPLE(fail, Mx02(1)); +Error, PROD_GF2MAT_GF2MAT_SIMPLE: must be a GF2 matrix (not the value 'fa\ +il') +gap> PROD_GF2MAT_GF2MAT_SIMPLE(M2([[o], [z]]), fail); +Error, PROD_GF2MAT_GF2MAT_SIMPLE: must be a GF2 matrix (not the value 'fa\ +il') + +# +# PROD_GF2MAT_GF2MAT_ADVANCED +# +gap> PROD_GF2MAT_GF2MAT_ADVANCED(M2([[o]]), M2([[o]]), 1, 1) = M2([[o]]); +true + +# bad arguments +gap> PROD_GF2MAT_GF2MAT_ADVANCED(fail, M2([[o]]), 1, 1); +Error, PROD_GF2MAT_GF2MAT_ADVANCED: must be a GF2 matrix (not the value '\ +fail') +gap> PROD_GF2MAT_GF2MAT_ADVANCED(M2([[o]]), fail, 1, 1); +Error, PROD_GF2MAT_GF2MAT_ADVANCED: must be a GF2 matrix (not the value '\ +fail') +gap> PROD_GF2MAT_GF2MAT_ADVANCED(M2([[o]]), M2([[o]]), fail, 1); +Error, PROD_GF2MAT_GF2MAT_ADVANCED: must be a small integer (not\ + the value 'fail') +gap> PROD_GF2MAT_GF2MAT_ADVANCED(M2([[o]]), M2([[o]]), 1, fail); +Error, PROD_GF2MAT_GF2MAT_ADVANCED: must be a small integer (not t\ +he value 'fail') + +# +# ADDCOEFFS_GF2VEC_GF2VEC_MULT +# +gap> v := V2([]);; ADDCOEFFS_GF2VEC_GF2VEC_MULT(v, empty, z); +0 +gap> v; + + +# bad arguments +gap> ADDCOEFFS_GF2VEC_GF2VEC_MULT(fail, empty, z); +Error, ADDCOEFFS_GF2VEC_GF2VEC_MULT: must be a GF2 vector (not the value \ +'fail') +gap> ADDCOEFFS_GF2VEC_GF2VEC_MULT(v, fail, z); +Error, ADDCOEFFS_GF2VEC_GF2VEC_MULT: must be a GF2 vector (not the value \ +'fail') +gap> ADDCOEFFS_GF2VEC_GF2VEC_MULT(v, empty, fail); +Error, ADDCOEFFS_GF2VEC_GF2VEC_MULT: must be a finite field element (not\ + the value 'fail') + +# +# ADDCOEFFS_GF2VEC_GF2VEC +# +gap> v := V2([]);; ADDCOEFFS_GF2VEC_GF2VEC(v, empty); +0 +gap> v; + + +# bad arguments +gap> ADDCOEFFS_GF2VEC_GF2VEC(fail, empty); +Error, ADDCOEFFS_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail\ +') +gap> ADDCOEFFS_GF2VEC_GF2VEC(v, fail); +Error, ADDCOEFFS_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail\ +') + +# +# SHRINKCOEFFS_GF2VEC +# +gap> v := V2([o, z]);; SHRINKCOEFFS_GF2VEC(v); +1 +gap> v; + + +# bad arguments +gap> SHRINKCOEFFS_GF2VEC(fail); +Error, SHRINKCOEFFS_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# POSITION_NONZERO_GF2VEC +# +gap> POSITION_NONZERO_GF2VEC(empty, z); +1 +gap> POSITION_NONZERO_GF2VEC(one, z); +1 + +# bad arguments +gap> POSITION_NONZERO_GF2VEC(fail, z); +Error, POSITION_NONZERO_GF2VEC: must be a GF2 vector (not the value 'fai\ +l') +gap> POSITION_NONZERO_GF2VEC(empty, fail); +1 + +# +# POSITION_NONZERO_GF2VEC3 +# +gap> POSITION_NONZERO_GF2VEC3(empty, z, 1); +1 +gap> POSITION_NONZERO_GF2VEC3(V2([z, o]), z, 2); +3 + +# bad arguments +gap> POSITION_NONZERO_GF2VEC3(fail, z, 1); +Error, POSITION_NONZERO_GF2VEC3: must be a GF2 vector (not the value 'fa\ +il') +gap> POSITION_NONZERO_GF2VEC3(empty, fail, 1); +1 +gap> POSITION_NONZERO_GF2VEC3(empty, z, fail); +Error, POSITION_NONZERO_GF2VEC3: must be a non-negative small integer (\ +not the value 'fail') + +# +# MULT_VECTOR_GF2VECS_2 +# +gap> v := V2([o]);; MULT_VECTOR_GF2VECS_2(v, o);; v = one; +true + +# bad arguments +gap> MULT_VECTOR_GF2VECS_2(fail, o); +Error, MULT_VECTOR_GF2VECS_2: must be a GF2 vector (not the value 'fail') +gap> MULT_VECTOR_GF2VECS_2(v, fail); +Error, MULT_VECTOR_GF2VECS_2: must be a finite field element (not the va\ +lue 'fail') + +# +# APPEND_GF2VEC +# +gap> v := V2([]);; APPEND_GF2VEC(v, one);; v = one; +true + +# bad arguments +gap> APPEND_GF2VEC(fail, one); +Error, APPEND_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> APPEND_GF2VEC(v, fail); +Error, APPEND_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# SHALLOWCOPY_GF2VEC +# +gap> v := SHALLOWCOPY_GF2VEC(empty);; v = empty and not IsIdenticalObj(v, empty); +true + +# bad arguments +gap> SHALLOWCOPY_GF2VEC(fail); +Error, SHALLOWCOPY_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# NUMBER_GF2VEC +# +gap> NUMBER_GF2VEC(empty); +1 +gap> NUMBER_GF2VEC(one); +1 + +# bad arguments +gap> NUMBER_GF2VEC(fail); +Error, NUMBER_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# TRANSPOSED_GF2MAT +# +gap> TRANSPOSED_GF2MAT(Mx02(2)); +Error, row index 1 exceeds 0, the number of rows + +# bad arguments gap> TRANSPOSED_GF2MAT(fail); -Error, TRANSPOSED_GF2MAT: Need compressed matrix over GF(2) +Error, TRANSPOSED_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# DIST_GF2VEC_GF2VEC +# +gap> DIST_GF2VEC_GF2VEC(empty, empty); +0 +gap> DIST_GF2VEC_GF2VEC(one, one); +0 + +# bad arguments +gap> DIST_GF2VEC_GF2VEC(fail, empty); +Error, DIST_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> DIST_GF2VEC_GF2VEC(empty, fail); +Error, DIST_GF2VEC_GF2VEC: must be a GF2 vector (not the value 'fail') + +# +# DIST_VEC_CLOS_VEC +# +gap> d := [0, 0];; DIST_VEC_CLOS_VEC(Veclis2([one]), oneZero, d);; d; +[ 1, 1 ] + +# bad arguments +gap> DIST_VEC_CLOS_VEC(fail, oneZero, d); +Error, DIST_VEC_CLOS_VEC: must be a plain list (not the value 'fail') +gap> DIST_VEC_CLOS_VEC(Veclis2([one]), fail, d); +Error, DIST_VEC_CLOS_VEC: must be a GF2 vector (not the value 'fail') +gap> DIST_VEC_CLOS_VEC(Veclis2([one]), oneZero, fail); +Error, DIST_VEC_CLOS_VEC: must be a plain list (not the value 'fail') + +# +# SUM_GF2MAT_GF2MAT +# +gap> SUM_GF2MAT_GF2MAT(Mx02(2), Mx02(2)) = Mx02(2); +true + +# bad arguments +gap> SUM_GF2MAT_GF2MAT(fail, Mx02(2)); +Error, SUM_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> SUM_GF2MAT_GF2MAT(Mx02(2), fail); +Error, SUM_GF2MAT_GF2MAT: must be a GF2 matrix (not the value 'fail') + +# +# A_CLOS_VEC +# +gap> A_CLOS_VEC(Veclis2([one]), one, 0, 0); + + +# bad arguments +gap> A_CLOS_VEC(fail, one, 0, 0); +Error, A_CLOS_VEC: must be a plain list (not the value 'fail') +gap> A_CLOS_VEC(Veclis2([one]), fail, 0, 0); +Error, A_CLOS_VEC: must be a GF2 vector (not the value 'fail') +gap> A_CLOS_VEC(Veclis2([one]), one, fail, 0); +Error, A_CLOS_VEC: must be a non-negative small integer (not the value '\ +fail') +gap> A_CLOS_VEC(Veclis2([one]), one, 0, fail); +Error, A_CLOS_VEC: must be a non-negative small integer (not the value \ +'fail') + +# +# A_CLOS_VEC_COORDS +# +gap> A_CLOS_VEC_COORDS(Veclis2([one]), one, 0, 0); +[ , [ 1 ] ] + +# bad arguments +gap> A_CLOS_VEC_COORDS(fail, one, 0, 0); +Error, A_CLOS_VEC_COORDS: must be a plain list (not the value 'fail') +gap> A_CLOS_VEC_COORDS(Veclis2([one]), fail, 0, 0); +Error, A_CLOS_VEC_COORDS: must be a GF2 vector (not the value 'fail') +gap> A_CLOS_VEC_COORDS(Veclis2([one]), one, fail, 0); +Error, A_CLOS_VEC_COORDS: must be a non-negative small integer (not the \ +value 'fail') +gap> A_CLOS_VEC_COORDS(Veclis2([one]), one, 0, fail); +Error, A_CLOS_VEC_COORDS: must be a non-negative small integer (not the\ + value 'fail') + +# +# COSET_LEADERS_INNER_GF2 +# +gap> leaders := [Immutable(oneZero)];; leaders[3] := false;; +gap> COSET_LEADERS_INNER_GF2(Veclis2([one]), 1, 1, leaders); +1 +gap> leaders[2]; + + +# bad arguments +gap> COSET_LEADERS_INNER_GF2(fail, 1, 1, leaders); +Error, COSET_LEADERS_INNER_GF2: must be a plain list (not the value '\ +fail') +gap> COSET_LEADERS_INNER_GF2(Veclis2([one]), fail, 1, leaders); +Error, COSET_LEADERS_INNER_GF2: must be a small integer (not the valu\ +e 'fail') +gap> COSET_LEADERS_INNER_GF2(Veclis2([one]), 1, fail, leaders); +Error, COSET_LEADERS_INNER_GF2: must be a small integer (not the valu\ +e 'fail') +gap> COSET_LEADERS_INNER_GF2(Veclis2([one]), 1, 1, fail); +Error, COSET_LEADERS_INNER_GF2: must be a plain list (not the value \ +'fail') + +# +# CONV_GF2MAT +# +gap> m := [V2([]), V2([])];; CONV_GF2MAT(m);; m = Mx02(2); +true + +# bad arguments +gap> CONV_GF2MAT(fail); +Error, CONV_GF2MAT: must be a small list (not the value 'fail') + +# +# PROD_GF2VEC_ANYMAT +# +gap> PROD_GF2VEC_ANYMAT(one, [fail]); +"TRY_NEXT_METHOD" +gap> PROD_GF2VEC_ANYMAT(one, [one]); + + +# bad arguments +gap> PROD_GF2VEC_ANYMAT(fail, [fail]); +Error, PROD_GF2VEC_ANYMAT: must be a GF2 vector (not the value 'fail') +gap> PROD_GF2VEC_ANYMAT(one, fail); +Error, PROD_GF2VEC_ANYMAT: must be a plain list (not the value 'fail') + +# +# RIGHTMOST_NONZERO_GF2VEC +# +gap> RIGHTMOST_NONZERO_GF2VEC(empty); +0 +gap> RIGHTMOST_NONZERO_GF2VEC(V2([z, o])); +2 + +# bad arguments +gap> RIGHTMOST_NONZERO_GF2VEC(fail); +Error, RIGHTMOST_NONZERO_GF2VEC: must be a GF2 vector (not the value 'fa\ +il') + +# +# RESIZE_GF2VEC +# +gap> v := V2([]);; RESIZE_GF2VEC(v, 2);; v = V2([z, z]); +true + +# bad arguments +gap> RESIZE_GF2VEC(fail, 2); +Error, RESIZE_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> RESIZE_GF2VEC(v, fail); +Error, RESIZE_GF2VEC: must be a non-negative small integer (not the v\ +alue 'fail') + +# +# SHIFT_LEFT_GF2VEC +# +gap> v := V2([]);; SHIFT_LEFT_GF2VEC(v, 3);; v = empty; +true + +# bad arguments +gap> SHIFT_LEFT_GF2VEC(fail, 3); +Error, SHIFT_LEFT_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> SHIFT_LEFT_GF2VEC(v, fail); +Error, SHIFT_LEFT_GF2VEC: must be a non-negative small integer (not t\ +he value 'fail') + +# +# SHIFT_RIGHT_GF2VEC +# +gap> v := V2([]);; SHIFT_RIGHT_GF2VEC(v, 3, z);; v = V2([z, z, z]); +true + +# bad arguments +gap> SHIFT_RIGHT_GF2VEC(fail, 3, z); +Error, SHIFT_RIGHT_GF2VEC: must be a GF2 vector (not the value 'fail') +gap> SHIFT_RIGHT_GF2VEC(v, fail, z); +Error, SHIFT_RIGHT_GF2VEC: must be a non-negative small integer (not \ +the value 'fail') +gap> SHIFT_RIGHT_GF2VEC(v, 3, fail); +Error, SHIFT_RIGHT_GF2VEC: must be a finite field element (not the valu\ +e 'fail') + +# +# ADD_GF2VEC_GF2VEC_SHIFTED +# +gap> v := V2([]);; ADD_GF2VEC_GF2VEC_SHIFTED(v, one, 0, 1);; v = oneZero; +true + +# bad arguments +gap> ADD_GF2VEC_GF2VEC_SHIFTED(fail, one, 0, 1); +Error, ADD_GF2VEC_GF2VEC_SHIFTED: must be a GF2 vector (not the value '\ +fail') +gap> ADD_GF2VEC_GF2VEC_SHIFTED(v, fail, 0, 1); +Error, ADD_GF2VEC_GF2VEC_SHIFTED: must be a GF2 vector (not the value '\ +fail') +gap> ADD_GF2VEC_GF2VEC_SHIFTED(v, one, fail, 1); +Error, ADD_GF2VEC_GF2VEC_SHIFTED: must be a non-negative small integer \ +(not the value 'fail') +gap> ADD_GF2VEC_GF2VEC_SHIFTED(v, one, 0, fail); +Error, ADD_GF2VEC_GF2VEC_SHIFTED: must be a non-negative small integer (\ +not the value 'fail') + +# +# PROD_COEFFS_GF2VEC +# +gap> PROD_COEFFS_GF2VEC(empty, 0, empty, 0); + +gap> PROD_COEFFS_GF2VEC(one, 1, one, 1); + + +# bad arguments +gap> PROD_COEFFS_GF2VEC(fail, 0, empty, 0); + +gap> PROD_COEFFS_GF2VEC(empty, fail, empty, 0); +Error, PROD_COEFFS_GF2VEC: must be a non-negative small integer (not th\ +e value 'fail') +gap> PROD_COEFFS_GF2VEC(empty, 0, fail, 0); + +gap> PROD_COEFFS_GF2VEC(empty, 0, empty, fail); +Error, PROD_COEFFS_GF2VEC: must be a non-negative small integer (not th\ +e value 'fail') + +# +# REDUCE_COEFFS_GF2VEC +# +gap> v := V2([o]);; w := V2([o, z]);; +gap> REDUCE_COEFFS_GF2VEC(v, 1, w, 1); +0 +gap> v; + + +# bad arguments +gap> REDUCE_COEFFS_GF2VEC(fail, 1, w, 1); +Error, REDUCE_COEFFS_GF2VEC: must be a GF2 vector (not the value 'fail'\ +) +gap> REDUCE_COEFFS_GF2VEC(v, fail, w, 1); +Error, REDUCE_COEFFS_GF2VEC: must be a non-negative small integer (not \ +the value 'fail') +gap> REDUCE_COEFFS_GF2VEC(v, 1, fail, 1); +Error, REDUCE_COEFFS_GF2VEC: must be a GF2 vector (not the value 'fail'\ +) +gap> REDUCE_COEFFS_GF2VEC(v, 1, w, fail); +Error, REDUCE_COEFFS_GF2VEC: must be a non-negative small integer (not \ +the value 'fail') + +# +# QUOTREM_COEFFS_GF2VEC +# +gap> QUOTREM_COEFFS_GF2VEC(empty, 0, w, 1); +[ , ] + +# bad arguments +gap> QUOTREM_COEFFS_GF2VEC(fail, 0, w, 1); +Error, QUOTREM_COEFFS_GF2VEC: must be a GF2 vector (not the value 'fail\ +') +gap> QUOTREM_COEFFS_GF2VEC(empty, fail, w, 1); +Error, QUOTREM_COEFFS_GF2VEC: must be a non-negative small integer (not\ + the value 'fail') +gap> QUOTREM_COEFFS_GF2VEC(empty, 0, fail, 1); +Error, QUOTREM_COEFFS_GF2VEC: must be a GF2 vector (not the value 'fail\ +') +gap> QUOTREM_COEFFS_GF2VEC(empty, 0, w, fail); +Error, QUOTREM_COEFFS_GF2VEC: must be a non-negative small integer (not\ + the value 'fail') + +# +# SEMIECHELON_LIST_GF2VECS +# +gap> s := SEMIECHELON_LIST_GF2VECS([one]);; s.heads = [1] and s.vectors = [one]; +true + +# bad arguments +gap> SEMIECHELON_LIST_GF2VECS(fail); +Error, SEMIECHELON_LIST_GF2VECS: must be a plain list (not the value 'fa\ +il') + +# +# SEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS +# +gap> s := SEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS([one]);; +gap> s.heads; +[ 1 ] +gap> s.vectors = [one]; +true +gap> s.coeffs = [one]; +true + +# bad arguments +gap> SEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS(fail); +Error, SEMIECHELON_LIST_GF2VECS_TRANSFORMATIONS: must be a plain list (n\ +ot the value 'fail') + +# +# TRIANGULIZE_LIST_GF2VECS +# +gap> m := [one];; TRIANGULIZE_LIST_GF2VECS(m);; m = [one]; +true + +# bad arguments +gap> TRIANGULIZE_LIST_GF2VECS(fail); +Error, TRIANGULIZE_LIST_GF2VECS: must be a plain list (not the value 'fa\ +il') + +# +# DETERMINANT_LIST_GF2VECS +# +gap> DETERMINANT_LIST_GF2VECS([one]); +Z(2)^0 + +# bad arguments +gap> DETERMINANT_LIST_GF2VECS(fail); +Error, DETERMINANT_LIST_GF2VECS: must be a plain list (not the value 'fa\ +il') + +# +# RANK_LIST_GF2VECS +# +gap> RANK_LIST_GF2VECS([one]); +1 + +# bad arguments +gap> RANK_LIST_GF2VECS(fail); +Error, RANK_LIST_GF2VECS: must be a plain list (not the value 'fail') + +# +# KRONECKERPRODUCT_GF2MAT_GF2MAT +# +gap> KRONECKERPRODUCT_GF2MAT_GF2MAT(Mx02(2), M2([[o]])) = Mx02(2); +true + +# bad arguments +gap> KRONECKERPRODUCT_GF2MAT_GF2MAT(fail, M2([[o]])); +Error, KRONECKERPRODUCT_GF2MAT_GF2MAT: must be a GF2 matrix (not the va\ +lue 'fail') +gap> KRONECKERPRODUCT_GF2MAT_GF2MAT(Mx02(2), fail); +Error, KRONECKERPRODUCT_GF2MAT_GF2MAT: must be a GF2 matrix (not the va\ +lue 'fail') + +# +# COPY_SECTION_GF2VECS +# +gap> src := V2([o, o]);; dst := V2([z, z, z]);; COPY_SECTION_GF2VECS(src, dst, 1, 2, 2);; dst = V2([z, o, o]); +true + +# bad arguments +gap> COPY_SECTION_GF2VECS(fail, dst, 1, 2, 2); +Error, COPY_SECTION_GF2VECS: must be a GF2 vector (not the value 'fail') +gap> COPY_SECTION_GF2VECS(src, fail, 1, 2, 2); +Error, COPY_SECTION_GF2VECS: must be a GF2 vector (not the value 'fail'\ +) +gap> COPY_SECTION_GF2VECS(src, dst, fail, 2, 2); +Error, COPY_SECTION_GF2VECS: must be a positive small integer (not the \ +value 'fail') +gap> COPY_SECTION_GF2VECS(src, dst, 1, fail, 2); +Error, COPY_SECTION_GF2VECS: must be a positive small integer (not the va\ +lue 'fail') +gap> COPY_SECTION_GF2VECS(src, dst, 1, 2, fail); +Error, COPY_SECTION_GF2VECS: must be a small integer (not the value \ +'fail') + +# +# MAT_ELM_GF2MAT +# +gap> MAT_ELM_GF2MAT(M2([[o]]), 1, 1); +Z(2)^0 + +# bad arguments +gap> MAT_ELM_GF2MAT(fail, 1, 1); +Error, MAT_ELM_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> MAT_ELM_GF2MAT(M2([[o]]), fail, 1); +Error, MAT_ELM_GF2MAT: must be a positive small integer (not the value '\ +fail') +gap> MAT_ELM_GF2MAT(M2([[o]]), 1, fail); +Error, MAT_ELM_GF2MAT: must be a positive small integer (not the value '\ +fail') + +# +# SET_MAT_ELM_GF2MAT +# +gap> m := M2([[z]]);; SET_MAT_ELM_GF2MAT(m, 1, 1, o);; m = M2([[o]]); +true + +# bad arguments +gap> SET_MAT_ELM_GF2MAT(fail, 1, 1, o); +Error, SET_MAT_ELM_GF2MAT: must be a GF2 matrix (not the value 'fail') +gap> SET_MAT_ELM_GF2MAT(m, fail, 1, o); +Error, SET_MAT_ELM_GF2MAT: must be a positive small integer (not the val\ +ue 'fail') +gap> SET_MAT_ELM_GF2MAT(m, 1, fail, o); +Error, SET_MAT_ELM_GF2MAT: must be a positive small integer (not the val\ +ue 'fail') +gap> SET_MAT_ELM_GF2MAT(m, 1, 1, fail); +Error, SET_MAT_ELM_GF2MAT: assigned element must be a GF(2) element (not the v\ +alue 'fail') # gap> STOP_TEST("kernel/vecgf2.tst"); diff --git a/tst/testinstall/maxsub.tst b/tst/testinstall/maxsub.tst index 036381d657..e04103b67b 100644 --- a/tst/testinstall/maxsub.tst +++ b/tst/testinstall/maxsub.tst @@ -9,12 +9,14 @@ gap> SortedList(List(msc, IndexInParent)); [ 2, 3, 4 ] # +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> G := GL(2,4);; gap> msc:=MaximalSubgroupClassReps(G);; gap> ForAll(msc, H -> Parent(H) = G); true gap> SortedList(List(msc, IndexInParent)); [ 3, 5, 6, 10 ] +#@fi # gap> G := GL(2,5);; @@ -25,10 +27,12 @@ gap> SortedList(List(msc, IndexInParent)); [ 2, 5, 6, 10 ] # +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> G := AlternatingGroup(5);; gap> msc := MaximalSubgroupClassReps(G);; gap> SortedList(List(msc, H -> Index(G, H))); [ 5, 6, 10 ] +#@fi # gap> STOP_TEST("maxsub.tst"); diff --git a/tst/testinstall/package.tst b/tst/testinstall/package.tst index 2b1a5d6e84..1ccd238478 100644 --- a/tst/testinstall/package.tst +++ b/tst/testinstall/package.tst @@ -435,9 +435,11 @@ false gap> IsPackageLoaded("mockpkg", ">=2.0"); false +# # instruct GAP to load the package, and record all its declarations # the help book of mockpkg might already have been loaded in other tests # -> we suppress a warning about this +#@if IsPackageMarkedForLoading( "gapdoc", "" ) gap> old_warning_level := InfoLevel( InfoWarning );; gap> SetInfoLevel( InfoWarning, 0 ); gap> PackageVariablesInfo("mockpkg", "0.1");; @@ -450,9 +452,10 @@ new global functions: new global variables: mockpkg_ExtensionData* + mockpkg_Vararg( first, rest... )* new operations: - mockpkg_Operation( arg )* + mockpkg_Operation( ... )* new attributes: mockpkg_Attribute( ... )* @@ -480,9 +483,14 @@ gap> IsDateFormatValid := function( datestring ) > end;; gap> IsDateFormatValid( GAPInfo.Date ); true +#@else +gap> LoadPackage("mockpkg", false); +oops, should not print here +true +#@fi # Test the Cite() command (output changed with GAPDoc 1.6.6 and again with 1.6.7) -#@if CompareVersionNumbers(InstalledPackageVersion("gapdoc"), "1.6.7") +#@if IsPackageMarkedForLoading( "gapdoc", "1.6.7" ) gap> Cite("mockpkg"); Please use one of the following samples to cite mockpkg version from this installation @@ -537,7 +545,7 @@ rg/}}}, } -#@else +#@elif IsPackageMarkedForLoading( "gapdoc", "" ) gap> Cite("mockpkg"); Please use one of the following samples to cite mockpkg version from this installation diff --git a/tst/testspecial/64bit/low-mem-list-types.g.out b/tst/testspecial/64bit/low-mem-list-types.g.out index 086225b90a..87dff93393 100644 --- a/tst/testspecial/64bit/low-mem-list-types.g.out +++ b/tst/testspecial/64bit/low-mem-list-types.g.out @@ -1,19 +1,16 @@ gap> ListWithIdenticalEntries(2^50, 'a'); Error, Cannot allocate 1125899906842633 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> ListWithIdenticalEntries(2^50, true); Error, Cannot allocate 140737488355336 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> ListWithIdenticalEntries(2^50, 2); Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> quit; diff --git a/tst/testspecial/64bit/low-mem-plist-1.g.out b/tst/testspecial/64bit/low-mem-plist-1.g.out index 9264df9d43..921fd7e60e 100644 --- a/tst/testspecial/64bit/low-mem-plist-1.g.out +++ b/tst/testspecial/64bit/low-mem-plist-1.g.out @@ -2,15 +2,13 @@ gap> l := []; [ ] gap> l[2^50] := 1; Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!!!! -Stack trace: not in any function at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> l[2^50] := 2; Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!!!! -Stack trace: not in any function at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> l[3] := 3; 3 diff --git a/tst/testspecial/64bit/low-mem-plist-2.g.out b/tst/testspecial/64bit/low-mem-plist-2.g.out index d50a3a7ab5..757b353f3d 100644 --- a/tst/testspecial/64bit/low-mem-plist-2.g.out +++ b/tst/testspecial/64bit/low-mem-plist-2.g.out @@ -1,13 +1,11 @@ gap> EmptyPlist(2^50); Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> EmptyPlist(2^50); Error, Cannot allocate 9007199254741000 bytes: cannot extend the workspace any more!! -Stack trace: not in any function at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> quit; diff --git a/tst/testspecial/backtrace.g.out b/tst/testspecial/backtrace.g.out index f2130d7a95..053849a831 100644 --- a/tst/testspecial/backtrace.g.out +++ b/tst/testspecial/backtrace.g.out @@ -18,13 +18,15 @@ Stack trace: @ *stdin*:11 ( ) called from read-eval loop at *stdin*:13 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] l[[ 1 .. 3 ]] := 1; @ *stdin*:11 ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] l[[ 1 .. 3 ]] := 1; @ *stdin*:11 arguments: @@ -43,13 +45,15 @@ Stack trace: @ *stdin*:15 ( ) called from read-eval loop at *stdin*:16 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] 1 / 0 @ *stdin*:15 ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] 1 / 0 @ *stdin*:15 arguments: @@ -69,8 +73,9 @@ fi; @ *stdin*:18 ( ) called from read-eval loop at *stdin*:19 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] if x then return 1; fi; @@ -78,6 +83,7 @@ fi; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] if x then return 1; fi; @@ -100,8 +106,9 @@ fi; @ *stdin*:21 ( ) called from read-eval loop at *stdin*:22 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] if 1 then return 1; fi; @@ -109,6 +116,7 @@ fi; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] if 1 then return 1; fi; @@ -132,8 +140,9 @@ fi; @ *stdin*:24 ( ) called from read-eval loop at *stdin*:25 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] if 1 < 0 then return 1; elif 1 then @@ -143,6 +152,7 @@ fi; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] if 1 < 0 then return 1; elif 1 then @@ -166,8 +176,9 @@ od; @ *stdin*:27 ( ) called from read-eval loop at *stdin*:28 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] while 1 do return 1; od; @@ -175,6 +186,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] while 1 do return 1; od; @@ -198,9 +210,10 @@ od; @ *stdin*:30 ( ) called from read-eval loop at *stdin*:31 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> Where(); +Stack trace: *[1] Error( "You cannot loop over the integer ", n, " did you mean the range [1..", n, "]" ); @ GAPROOT/lib/integer.gi:LINE [2] for i in 1 do @@ -210,6 +223,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] Error( "You cannot loop over the integer ", n, " did you mean the range [1..", n, "]" ); @ GAPROOT/lib/integer.gi:LINE arguments: @@ -238,8 +252,9 @@ od; @ *stdin*:33 ( ) called from read-eval loop at *stdin*:34 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] for i in true do return 1; od; @@ -247,6 +262,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] for i in true do return 1; od; @@ -269,8 +285,9 @@ od; @ *stdin*:35 ( ) called from read-eval loop at *stdin*:36 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] for i in true do return 1; od; @@ -278,6 +295,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] for i in true do return 1; od; @@ -302,8 +320,9 @@ od; @ *stdin*:37 ( ) called from read-eval loop at *stdin*:38 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] for i in true do return 1; od; @@ -311,6 +330,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] for i in true do return 1; od; @@ -335,8 +355,9 @@ od; @ *stdin*:39 ( ) called from read-eval loop at *stdin*:40 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] for i in true do return 1; od; @@ -344,6 +365,7 @@ od; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] for i in true do return 1; od; @@ -367,8 +389,9 @@ until 1; @ *stdin*:41 ( ) called from read-eval loop at *stdin*:42 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] repeat x := 1; until 1; @@ -376,6 +399,7 @@ until 1; ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] repeat x := 1; until 1; @@ -396,13 +420,15 @@ Stack trace: @ *stdin*:44 ( ) called from read-eval loop at *stdin*:45 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] Assert( 0, 1 ); @ *stdin*:44 ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] Assert( 0, 1 ); @ *stdin*:44 arguments: @@ -421,13 +447,15 @@ Stack trace: @ *stdin*:47 ( ) called from read-eval loop at *stdin*:48 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] Assert( 0, 1, "hello" ); @ *stdin*:47 ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] Assert( 0, 1, "hello" ); @ *stdin*:47 arguments: @@ -455,8 +483,9 @@ Stack trace: @ *stdin*:55 ( ) called from read-eval loop at *stdin*:56 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> Where(); +Stack trace: *[1] return m[i][j]; @ GAPROOT/lib/matrix.gi:LINE [2] ELM_LIST( m, row, col ) @@ -466,6 +495,7 @@ brk> Where(); ( ) called from read-eval loop at *errin*:1 brk> WhereWithVars(); +Stack trace: *[1] return m[i][j]; @ GAPROOT/lib/matrix.gi:LINE arguments: @@ -501,5 +531,5 @@ Stack trace: @ GAPROOT/lib/oper1.g:LINE ( ) called from read-eval loop at *stdin*:61 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/backtrace2.g.out b/tst/testspecial/backtrace2.g.out index 3583cc7588..2633405b76 100644 --- a/tst/testspecial/backtrace2.g.out +++ b/tst/testspecial/backtrace2.g.out @@ -35,10 +35,11 @@ Stack trace: @ *stdin*:26 ( ) called from read-eval loop at *stdin*:28 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> n; Where(); 3 +Stack trace: *[1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -49,6 +50,7 @@ brk> n; Where(); called from read-eval loop at *errin*:1 brk> DownEnv(); n; Where(); 2 +Stack trace: [1] Error( "!\n" ); @ *stdin*:24 *[2] test( n + 1 ); @@ -59,6 +61,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:2 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -69,6 +72,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:3 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -79,6 +83,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:4 brk> UpEnv(); n; Where(); 2 +Stack trace: [1] Error( "!\n" ); @ *stdin*:24 *[2] test( n + 1 ); @@ -89,6 +94,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:5 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -99,6 +105,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:6 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] Error( "!\n" ); @ *stdin*:24 [2] test( n + 1 ); @@ -130,9 +137,10 @@ Stack trace: @ *stdin*:37 ( ) called from read-eval loop at *stdin*:39 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> n; Where(); 3 +Stack trace: *[1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -143,6 +151,7 @@ brk> n; Where(); called from read-eval loop at *errin*:1 brk> DownEnv(); n; Where(); 2 +Stack trace: [1] 1 / 0 @ *stdin*:35 *[2] test( n + 1 ); @@ -153,6 +162,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:2 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -163,6 +173,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:3 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -173,6 +184,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:4 brk> UpEnv(); n; Where(); 2 +Stack trace: [1] 1 / 0 @ *stdin*:35 *[2] test( n + 1 ); @@ -183,6 +195,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:5 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -193,6 +206,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:6 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] 1 / 0 @ *stdin*:35 [2] test( n + 1 ); @@ -226,9 +240,10 @@ Stack trace: @ *stdin*:49 ( ) called from read-eval loop at *stdin*:51 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> n; Where(); 3 +Stack trace: *[1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); @@ -239,6 +254,7 @@ brk> n; Where(); called from read-eval loop at *errin*:1 brk> DownEnv(); n; Where(); 3 +Stack trace: *[1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); @@ -249,6 +265,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:2 brk> DownEnv(); n; Where(); 2 +Stack trace: [1] IsAbelian( 1 ) @ *stdin*:47 *[2] test( n + 1 ); @@ -259,6 +276,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:3 brk> DownEnv(); n; Where(); 1 +Stack trace: [1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); @@ -269,6 +287,7 @@ brk> DownEnv(); n; Where(); called from read-eval loop at *errin*:4 brk> UpEnv(); n; Where(); 2 +Stack trace: [1] IsAbelian( 1 ) @ *stdin*:47 *[2] test( n + 1 ); @@ -279,6 +298,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:5 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); @@ -289,6 +309,7 @@ brk> UpEnv(); n; Where(); called from read-eval loop at *errin*:6 brk> UpEnv(); n; Where(); 3 +Stack trace: *[1] IsAbelian( 1 ) @ *stdin*:47 [2] test( n + 1 ); diff --git a/tst/testspecial/bad-add.g.out b/tst/testspecial/bad-add.g.out index 9259da66d3..0dcbbfff42 100644 --- a/tst/testspecial/bad-add.g.out +++ b/tst/testspecial/bad-add.g.out @@ -10,5 +10,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-double-1.g.out b/tst/testspecial/bad-array-double-1.g.out index a68076d65a..05de996ca7 100644 --- a/tst/testspecial/bad-array-double-1.g.out +++ b/tst/testspecial/bad-array-double-1.g.out @@ -10,5 +10,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-int-0.g.out b/tst/testspecial/bad-array-int-0.g.out index 17e703a17a..2a307b9437 100644 --- a/tst/testspecial/bad-array-int-0.g.out +++ b/tst/testspecial/bad-array-int-0.g.out @@ -12,5 +12,5 @@ Stack trace: @ *stdin*:5 ( ) called from read-eval loop at *stdin*:7 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-int-1.g.out b/tst/testspecial/bad-array-int-1.g.out index cd7a87a095..ae359c3547 100644 --- a/tst/testspecial/bad-array-int-1.g.out +++ b/tst/testspecial/bad-array-int-1.g.out @@ -9,5 +9,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-string.g.out b/tst/testspecial/bad-array-string.g.out index d0bd81ee20..34dd31bbd0 100644 --- a/tst/testspecial/bad-array-string.g.out +++ b/tst/testspecial/bad-array-string.g.out @@ -10,5 +10,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-undef-0.g.out b/tst/testspecial/bad-array-undef-0.g.out index 5ea205de9a..8ce908cbd9 100644 --- a/tst/testspecial/bad-array-undef-0.g.out +++ b/tst/testspecial/bad-array-undef-0.g.out @@ -10,5 +10,5 @@ Stack trace: @ *stdin*:4 ( ) called from read-eval loop at *stdin*:6 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-array-undef-1.g.out b/tst/testspecial/bad-array-undef-1.g.out index 7efcc85219..d172c4f20f 100644 --- a/tst/testspecial/bad-array-undef-1.g.out +++ b/tst/testspecial/bad-array-undef-1.g.out @@ -11,5 +11,5 @@ Stack trace: @ *stdin*:5 ( ) called from read-eval loop at *stdin*:7 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/bad-minus.g.out b/tst/testspecial/bad-minus.g.out index ec55c46e87..42a34245bd 100644 --- a/tst/testspecial/bad-minus.g.out +++ b/tst/testspecial/bad-minus.g.out @@ -14,5 +14,5 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> QUIT; diff --git a/tst/testspecial/break-loop-loop.g.out b/tst/testspecial/break-loop-loop.g.out index 4da0087abd..c1f24f4ce9 100644 --- a/tst/testspecial/break-loop-loop.g.out +++ b/tst/testspecial/break-loop-loop.g.out @@ -9,8 +9,8 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> x; 1 brk> y; diff --git a/tst/testspecial/broken-test.g.out b/tst/testspecial/broken-test.g.out index bbe429da39..f51326c8ce 100644 --- a/tst/testspecial/broken-test.g.out +++ b/tst/testspecial/broken-test.g.out @@ -9,7 +9,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-3.tst", rec(width := 800)); Error, Invalid test file at broken-test-3.tst:5 @@ -22,7 +22,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-4.tst", rec(width := 800)); Error, Invalid test file: Nested #@if at broken-test-4.tst:2 @@ -35,7 +35,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-5.tst", rec(width := 800)); Error, Invalid test file: two #@else at broken-test-5.tst:7 @@ -48,7 +48,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-6.tst", rec(width := 800)); Error, Invalid test file: Continuation prompt '> ' followed by a tab, expected a regular space at broken-test-6.tst:3 @@ -61,7 +61,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-7.tst", rec(width := 800)); Error, Invalid test file: #@elif after #@else at broken-test-7.tst:7 @@ -74,7 +74,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-8.tst", rec(width := 800)); Error, Invalid test file: #@elif without #@if at broken-test-8.tst:1 @@ -87,7 +87,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("broken-test-9.tst", rec(width := 800)); Error, Invalid test file: Unterminated #@if at broken-test-9.tst:7 @@ -100,7 +100,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("invalidtestfile.tst", rec(width := 800)); Error, Invalid test file at invalidtestfile.tst:7 @@ -113,7 +113,7 @@ Stack trace: @ GAPROOT/lib/test.gi:LINE ( ) called from read-eval loop at *stdin*:2 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Test("empty.tst", rec(width := 800)); #I Test: File does not contain any tests! diff --git a/tst/testspecial/bugfix-2019-09-27-LastPV.g.out b/tst/testspecial/bugfix-2019-09-27-LastPV.g.out index bfb7f37450..c10ae80f68 100644 --- a/tst/testspecial/bugfix-2019-09-27-LastPV.g.out +++ b/tst/testspecial/bugfix-2019-09-27-LastPV.g.out @@ -7,7 +7,7 @@ gap> old_OnBreak:=OnBreak;; gap> OnBreak:=fail;; # prevent backtrace with line numbers that keep chaning gap> View([[badgroup]]); # <- trigger break loop Error, Rational operations: must not be zero -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; [ [ gap> OnBreak:=old_OnBreak;; diff --git a/tst/testspecial/current-env.g.out b/tst/testspecial/current-env.g.out index e90991e7e2..68ec461013 100644 --- a/tst/testspecial/current-env.g.out +++ b/tst/testspecial/current-env.g.out @@ -16,8 +16,8 @@ od; @ *stdin*:6 ( ) called from read-eval loop at *stdin*:9 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> ContentsLVars(CurrentEnv()); rec( func := function( n ) ... end, names := [ "n" ], values := [ 1 ] ) brk> DownEnv(); ContentsLVars(CurrentEnv()); diff --git a/tst/testspecial/debug-var.g.out b/tst/testspecial/debug-var.g.out index c39af18014..bbff49cdd5 100644 --- a/tst/testspecial/debug-var.g.out +++ b/tst/testspecial/debug-var.g.out @@ -19,8 +19,8 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *stdin*:14 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> brk> x; # access global 1 @@ -61,7 +61,7 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *errin*:12 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk_2> quit; brk> brk> z; # access local @@ -80,7 +80,7 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *errin*:17 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk_2> quit; brk> brk> return; @@ -89,7 +89,6 @@ gap> x; 42 gap> y; Error, Variable: 'y' must have a value -Stack trace: not in any function at *stdin*:16 gap> gap> h:=function(p) @@ -107,8 +106,8 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *stdin*:23 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> h(2); Error, foobar Stack trace: @@ -120,8 +119,8 @@ Stack trace: @ *stdin*:12 ( ) called from read-eval loop at *errin*:1 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk_2> brk_2> y; # access higher local as debug var 2 diff --git a/tst/testspecial/error-in-InputTextString.g.out b/tst/testspecial/error-in-InputTextString.g.out index 18aca9b5f0..f27a402920 100644 --- a/tst/testspecial/error-in-InputTextString.g.out +++ b/tst/testspecial/error-in-InputTextString.g.out @@ -1,8 +1,7 @@ gap> Read(InputTextString("Print(1 + [()]);")); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 1st choice method found for `+' on 2 arguments -Stack trace: called from read-eval loop at stream:1 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> QUIT; diff --git a/tst/testspecial/func-and-proc-call-trace.g.out b/tst/testspecial/func-and-proc-call-trace.g.out index 046b27f874..e58f4ef668 100644 --- a/tst/testspecial/func-and-proc-call-trace.g.out +++ b/tst/testspecial/func-and-proc-call-trace.g.out @@ -10,7 +10,7 @@ Stack trace: @ *stdin*:4 ( ) called from read-eval loop at *stdin*:6 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -27,7 +27,7 @@ Stack trace: @ *stdin*:9 ( ) called from read-eval loop at *stdin*:11 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -44,7 +44,7 @@ Stack trace: @ *stdin*:14 ( ) called from read-eval loop at *stdin*:16 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -61,7 +61,7 @@ Stack trace: @ *stdin*:19 ( ) called from read-eval loop at *stdin*:21 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -78,7 +78,7 @@ Stack trace: @ *stdin*:24 ( ) called from read-eval loop at *stdin*:26 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -95,7 +95,7 @@ Stack trace: @ *stdin*:29 ( ) called from read-eval loop at *stdin*:31 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -112,7 +112,7 @@ Stack trace: @ *stdin*:34 ( ) called from read-eval loop at *stdin*:36 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -129,7 +129,7 @@ Stack trace: @ *stdin*:39 ( ) called from read-eval loop at *stdin*:41 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -146,7 +146,7 @@ Stack trace: @ *stdin*:44 ( ) called from read-eval loop at *stdin*:46 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -163,7 +163,7 @@ Stack trace: @ *stdin*:49 ( ) called from read-eval loop at *stdin*:51 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -180,7 +180,7 @@ Stack trace: @ *stdin*:54 ( ) called from read-eval loop at *stdin*:56 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -197,7 +197,7 @@ Stack trace: @ *stdin*:59 ( ) called from read-eval loop at *stdin*:61 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -214,7 +214,7 @@ Stack trace: @ *stdin*:64 ( ) called from read-eval loop at *stdin*:66 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -231,7 +231,7 @@ Stack trace: @ *stdin*:69 ( ) called from read-eval loop at *stdin*:71 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -248,7 +248,7 @@ Stack trace: @ *stdin*:74 ( ) called from read-eval loop at *stdin*:76 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); @@ -265,7 +265,7 @@ Stack trace: @ *stdin*:79 ( ) called from read-eval loop at *stdin*:81 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> quit; gap> Print("\n\n"); diff --git a/tst/testspecial/last-access.g.out b/tst/testspecial/last-access.g.out index d958151341..2bc0c8131e 100644 --- a/tst/testspecial/last-access.g.out +++ b/tst/testspecial/last-access.g.out @@ -5,10 +5,9 @@ gap> 1;2;3;[last,last2,last3]; [ 3, 2, 1 ] gap> Error("err"); Error, err -Stack trace: not in any function at *stdin*:3 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> 1;2;3;[last,last2,last3]; 1 2 diff --git a/tst/testspecial/line-continuation.g.out b/tst/testspecial/line-continuation.g.out index 88f253686c..a6ed2a8a24 100644 --- a/tst/testspecial/line-continuation.g.out +++ b/tst/testspecial/line-continuation.g.out @@ -4,7 +4,6 @@ gap> # counter only once, so that both examples below report the error in line 2 gap> # gap> EvalString("123\\\n45x;"); Error, Variable: '12345x' must have a value -Stack trace: not in any function at stream:2 Error, Could not evaluate string. Stack trace: @@ -12,12 +11,11 @@ Stack trace: @ GAPROOT/lib/string.gi:LINE ( ) called from read-eval loop at *stdin*:6 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; gap> EvalString("123\\\r\n45x;"); Error, Variable: '12345x' must have a value -Stack trace: not in any function at stream:2 Error, Could not evaluate string. Stack trace: @@ -25,7 +23,7 @@ Stack trace: @ GAPROOT/lib/string.gi:LINE ( ) called from read-eval loop at *stdin*:6 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; gap> QUIT; diff --git a/tst/testspecial/mem-overflow.g.out b/tst/testspecial/mem-overflow.g.out index 82620ab76a..9de037b50f 100644 --- a/tst/testspecial/mem-overflow.g.out +++ b/tst/testspecial/mem-overflow.g.out @@ -7,7 +7,8 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:3 -you can 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> # ... then we should be in a break loop. Exit that, perform some other computations. brk> quit; gap> Factorial(42); diff --git a/tst/testspecial/method-not-found-where.g.out b/tst/testspecial/method-not-found-where.g.out index 30601cd166..5f80b728c7 100644 --- a/tst/testspecial/method-not-found-where.g.out +++ b/tst/testspecial/method-not-found-where.g.out @@ -8,11 +8,12 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:4 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> ShowMethods(1); #I Searching Method for IsDiagonalMatrix with 1 argument: #I Total: 3 entries brk> Where(5); +Stack trace: *[1] IsDiagonalMat( a ) @ *stdin*:3 ( ) diff --git a/tst/testspecial/method-not-found.g.out b/tst/testspecial/method-not-found.g.out index fa8a04ad87..2001ae951b 100644 --- a/tst/testspecial/method-not-found.g.out +++ b/tst/testspecial/method-not-found.g.out @@ -7,7 +7,7 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:3 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> return; 'return' cannot be used in this read-eval-print loop brk> QUIT; diff --git a/tst/testspecial/print-formatting.g.out b/tst/testspecial/print-formatting.g.out index 984e623ac8..11a0eb6932 100644 --- a/tst/testspecial/print-formatting.g.out +++ b/tst/testspecial/print-formatting.g.out @@ -22,9 +22,8 @@ gap> gap> # test formatting status for errout gap> 1/0; # trigger a break loop Error, Rational operations: must not be zero -Stack trace: not in any function at *stdin*:14 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> old := PrintFormattingStatus("*errout*"); true brk> SetPrintFormattingStatus("*errout*", false); diff --git a/tst/testspecial/repl-syntax-err.g.out b/tst/testspecial/repl-syntax-err.g.out index 9b4f6bc090..783de07a05 100644 --- a/tst/testspecial/repl-syntax-err.g.out +++ b/tst/testspecial/repl-syntax-err.g.out @@ -7,10 +7,9 @@ gap> # error, which wasn't reported correctly before the above issues was gap> # fixed. gap> Error(""): Error, -Stack trace: not in any function at *stdin*:9 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; Syntax error: ; expected Error(""): diff --git a/tst/testspecial/stack-depth-func.g.out b/tst/testspecial/stack-depth-func.g.out index 60ab11d2a3..26446d3435 100644 --- a/tst/testspecial/stack-depth-func.g.out +++ b/tst/testspecial/stack-depth-func.g.out @@ -14,7 +14,8 @@ Stack trace: [5] f( ); @ *stdin*:2 ... at *stdin*:3 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; # try once more Error, recursion depth trap (10000) Stack trace: @@ -29,5 +30,6 @@ Stack trace: [5] f( ); @ *stdin*:2 ... at *stdin*:3 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/stack-depth-func2.g.out b/tst/testspecial/stack-depth-func2.g.out index 7027f3df17..f82d7ece2f 100644 --- a/tst/testspecial/stack-depth-func2.g.out +++ b/tst/testspecial/stack-depth-func2.g.out @@ -14,7 +14,8 @@ Stack trace: [5] f( ) @ *stdin*:2 ... at *stdin*:3 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; # try once more Error, recursion depth trap (10000) Stack trace: @@ -29,5 +30,6 @@ Stack trace: [5] f( ) @ *stdin*:2 ... at *stdin*:3 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/stack-depth-rec.g.out b/tst/testspecial/stack-depth-rec.g.out index af205e7582..88d55ca50e 100644 --- a/tst/testspecial/stack-depth-rec.g.out +++ b/tst/testspecial/stack-depth-rec.g.out @@ -82,7 +82,8 @@ Stack trace: [5] String( record.(nam) ) @ GAPROOT/lib/record.gi:LINE ... at *stdin*:4 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> return; # try once more Error, recursion depth trap (5000) Stack trace: @@ -97,5 +98,6 @@ Stack trace: [5] String( record.(nam) ) @ GAPROOT/lib/record.gi:LINE ... at *stdin*:4 -you may 'return;' +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/stack-trace-depth.g.out b/tst/testspecial/stack-trace-depth.g.out index 7a30baca80..bb06fe9547 100644 --- a/tst/testspecial/stack-trace-depth.g.out +++ b/tst/testspecial/stack-trace-depth.g.out @@ -45,10 +45,11 @@ Stack trace: [5] f8( ) @ *stdin*:15 ... at *stdin*:35 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> SetUserPreference("WhereDepth", 12); brk> Where(); +Stack trace: * [1] Error( "foo" ); @ *stdin*:3 [2] f11( ) @@ -75,6 +76,7 @@ brk> Where(); called from read-eval loop at *errin*:2 brk> SetUserPreference("WhereDepth", 5); brk> Where(); +Stack trace: *[1] Error( "foo" ); @ *stdin*:3 [2] f11( ) diff --git a/tst/testspecial/stack-trace-label.g.out b/tst/testspecial/stack-trace-label.g.out index a7a71b90c8..2397215b7c 100644 --- a/tst/testspecial/stack-trace-label.g.out +++ b/tst/testspecial/stack-trace-label.g.out @@ -8,7 +8,7 @@ Stack trace: @ *stdin*:3 ( ) called from read-eval loop at *stdin*:5 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> quit; gap> QUIT; diff --git a/tst/testspecial/syntax-tree-error.g.out b/tst/testspecial/syntax-tree-error.g.out index 96794103f1..bff4a4d368 100644 --- a/tst/testspecial/syntax-tree-error.g.out +++ b/tst/testspecial/syntax-tree-error.g.out @@ -12,6 +12,6 @@ Stack trace: *[1] ( ) called from read-eval loop at *stdin*:8 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/top-level-error.g.out b/tst/testspecial/top-level-error.g.out index 9ed8d6c077..b4a6915bca 100644 --- a/tst/testspecial/top-level-error.g.out +++ b/tst/testspecial/top-level-error.g.out @@ -1,7 +1,6 @@ gap> Error("foo"); Error, foo -Stack trace: not in any function at *stdin*:2 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk> QUIT; diff --git a/tst/testspecial/trace.g.out b/tst/testspecial/trace.g.out index 3467715778..844962b4d0 100644 --- a/tst/testspecial/trace.g.out +++ b/tst/testspecial/trace.g.out @@ -31,7 +31,6 @@ gap> o(1,2,3,4,5,6); [ 1, 2, 3, 4, 5, 6 ] gap> o(1,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument operations -Stack trace: not in any function at *stdin*:25 gap> gap> # with tracing @@ -59,7 +58,6 @@ gap> o(1,2,3,4,5,6); [ 1, 2, 3, 4, 5, 6 ] gap> o(1,2,3,4,5,6,7); Error, sorry: cannot yet have X argument operations -Stack trace: not in any function at *stdin*:36 gap> UntraceMethods( o ); # not (yet?) supported gap> @@ -80,7 +78,6 @@ gap> o(1,2,3,4,5,6); [ 1, 2, 3, 4, 5, 6 ] gap> o(1,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument operations -Stack trace: not in any function at *stdin*:47 gap> gap> # @@ -113,7 +110,6 @@ gap> o(IsInt,2,3,4,5,6); [ , 2, 3, 4, 5, 6 ] gap> o(IsInt,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument constructors -Stack trace: not in any function at *stdin*:70 gap> gap> # with tracing @@ -138,7 +134,6 @@ gap> o(IsInt,2,3,4,5,6); [ , 2, 3, 4, 5, 6 ] gap> o(IsInt,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument constructors -Stack trace: not in any function at *stdin*:80 gap> UntraceMethods( o ); gap> @@ -157,6 +152,5 @@ gap> o(IsInt,2,3,4,5,6); [ , 2, 3, 4, 5, 6 ] gap> o(IsInt,2,3,4,5,6,7); # not (yet?) supported Error, sorry: cannot yet have X argument constructors -Stack trace: not in any function at *stdin*:90 gap> QUIT; diff --git a/tst/testspecial/up-down-env.g.out b/tst/testspecial/up-down-env.g.out index f27012aa67..a3c9ea82b0 100644 --- a/tst/testspecial/up-down-env.g.out +++ b/tst/testspecial/up-down-env.g.out @@ -19,7 +19,7 @@ Stack trace: [5] f( lvl - 1 ) @ *stdin*:7 ... at *stdin*:8 -type 'quit;' to quit to outer loop +you can enter 'quit;' to quit to outer loop brk> UpEnv(1); lvl; 0 brk> DownEnv(1); lvl; @@ -55,15 +55,13 @@ brk> ## start a fresh execution context brk> ## brk> Read("top-level-error.g"); Error, foo -Stack trace: not in any function at top-level-error.g:1 -you can 'quit;' to quit to outer loop, or -you can 'return;' to continue +you can enter 'quit;' to quit to outer loop, or +you can enter 'return;' to continue brk_2> Where(20); not in any function at *errin*:1 brk_2> lvl; # since `Read` started a fresh execution context, we can't access lvl here Error, Variable: 'lvl' must have a value -Stack trace: not in any function at *errin*:2 brk_2> quit; brk> lvl;