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 5e3a5ae291..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" @@ -56,7 +56,7 @@ jobs: run: | using Pkg if "${{ matrix.gapjl-version }}" == "latest-release" - Pkg.add("GAP") + Pkg.develop("GAP") else Pkg.add(;name="GAP", rev="${{ matrix.gapjl-version }}") end @@ -67,17 +67,37 @@ 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` - name: "Override bundled GAP" run: | - julia --proj=override $GAPJLPATH/etc/setup_override_dir.jl /tmp/GAPROOT /tmp/gap_jll_override --enable-Werror + julia --project=$GAPJLPATH $GAPJLPATH/etc/setup_override_dir.jl /tmp/GAPROOT /tmp/gap_jll_override --enable-Werror - name: "Run tests" run: | - julia --proj=override $GAPJLPATH/etc/run_with_override.jl /tmp/gap_jll_override --depwarn=error -e "using Pkg; Pkg.test(\"GAP\")" + julia --project=$GAPJLPATH $GAPJLPATH/etc/run_with_override.jl /tmp/gap_jll_override --depwarn=error -e "using Pkg; Pkg.test(\"GAP\")" 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/package-distro-trigger.yml b/.github/workflows/package-distro-trigger.yml new file mode 100644 index 0000000000..615d6fda0e --- /dev/null +++ b/.github/workflows/package-distro-trigger.yml @@ -0,0 +1,193 @@ +# +# This workflow lets GAP collaborators request a full PackageDistro test run +# from a GAP pull request comment. +# +# Usage: +# 1. Open a pull request on gap-system/gap. +# 2. Comment exactly: +# @gap-package-distribution-bot test +# 3. The workflow checks that the commenter has at least triage permission, +# creates or updates a marker comment on the PR, and dispatches the +# PackageDistro `test-gap-pr.yml` workflow. +# 4. PackageDistro tests the current PR head against all packages and updates +# the same marker comment with the result. +# +# The GAP comments and the dispatch to PackageDistro use GitHub App tokens: +# configure `APP_CLIENT_ID` as an organization or repository variable (or +# secret) and `APP_PRIVATE_KEY` as a secret available to this repository. The +# app must be installed on both `gap-system/gap` and +# `gap-system/PackageDistro`. +# +name: PackageDistro PR trigger + +on: + issue_comment: + types: [created] + +permissions: + contents: read + issues: write + pull-requests: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.issue.number }} + cancel-in-progress: false + +jobs: + dispatch-package-distro: + name: Dispatch PackageDistro test + if: ${{ github.event.issue.pull_request != null }} + runs-on: ubuntu-latest + steps: + - name: Check command + id: command + env: + COMMENT_BODY: ${{ github.event.comment.body }} + run: | + expected='@gap-package-distribution-bot test' + if [[ "${COMMENT_BODY}" == "${expected}" ]]; then + echo "matches=true" >> "$GITHUB_OUTPUT" + else + echo "matches=false" >> "$GITHUB_OUTPUT" + fi + + - uses: actions/create-github-app-token@v3 + id: gap-token + if: ${{ steps.command.outputs.matches == 'true' }} + with: + client-id: ${{ vars.APP_CLIENT_ID || secrets.APP_CLIENT_ID || secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: gap-system + repositories: gap + + - name: Check commenter permission + id: permission + if: ${{ steps.command.outputs.matches == 'true' }} + env: + GH_TOKEN: ${{ steps.gap-token.outputs.token }} + REPO: ${{ github.repository }} + ACTOR: ${{ github.event.comment.user.login }} + run: | + api_url="https://api.github.com/repos/${REPO}/collaborators/${ACTOR}/permission" + http_code=$( + curl -sSL \ + -H "Authorization: Bearer ${GH_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + -o permission.json \ + -w '%{http_code}' \ + "${api_url}" + ) + if [[ "${http_code}" == "200" ]]; then + permission=$(jq -r '.permission // "none"' permission.json) + else + permission="none" + fi + echo "permission=${permission}" >> "$GITHUB_OUTPUT" + case "${permission}" in + admin|maintain|write|triage) + echo "authorized=true" >> "$GITHUB_OUTPUT" + ;; + *) + echo "authorized=false" >> "$GITHUB_OUTPUT" + ;; + esac + + - name: Find prior bot comment + id: find-comment + if: ${{ steps.command.outputs.matches == 'true' }} + uses: peter-evans/find-comment@v4 + with: + token: ${{ steps.gap-token.outputs.token }} + issue-number: ${{ github.event.issue.number }} + body-includes: "" + + - name: Reply to unauthorized request + if: >- + ${{ + steps.command.outputs.matches == 'true' && + steps.permission.outputs.authorized != 'true' + }} + uses: peter-evans/create-or-update-comment@v5 + with: + token: ${{ steps.gap-token.outputs.token }} + comment-id: ${{ steps.find-comment.outputs.comment-id }} + issue-number: ${{ github.event.issue.number }} + edit-mode: replace + body: | + + `@gap-package-distribution-bot test` may only be used by GAP collaborators with at least triage access. + + - uses: actions/create-github-app-token@v3 + id: pkgdistro-token + if: >- + ${{ + steps.command.outputs.matches == 'true' && + steps.permission.outputs.authorized == 'true' + }} + with: + client-id: ${{ vars.APP_CLIENT_ID || secrets.APP_CLIENT_ID || secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: gap-system + repositories: PackageDistro + + - name: Acknowledge accepted request + id: acknowledge-request + if: >- + ${{ + steps.command.outputs.matches == 'true' && + steps.permission.outputs.authorized == 'true' + }} + uses: peter-evans/create-or-update-comment@v5 + with: + token: ${{ steps.gap-token.outputs.token }} + comment-id: ${{ steps.find-comment.outputs.comment-id }} + issue-number: ${{ github.event.issue.number }} + edit-mode: replace + body: | + + Accepted `@gap-package-distribution-bot test`. + + PackageDistro was asked to run the full package test suite against the current head of this pull request. This comment will be updated with the result. + + - name: Dispatch PackageDistro workflow + if: >- + ${{ + steps.command.outputs.matches == 'true' && + steps.permission.outputs.authorized == 'true' + }} + env: + GH_TOKEN: ${{ steps.pkgdistro-token.outputs.token }} + PR_URL: ${{ github.event.issue.html_url }} + COMMENT_ID: ${{ steps.acknowledge-request.outputs.comment-id }} + REQUESTER: ${{ github.event.comment.user.login }} + COMMAND: ${{ github.event.comment.body }} + run: | + comment_id_json=null + if [[ -n "${COMMENT_ID}" ]]; then + comment_id_json=${COMMENT_ID} + fi + jq -n \ + --arg ref main \ + --arg pr_url "${PR_URL}" \ + --arg requester "${REQUESTER}" \ + --arg command "${COMMAND}" \ + --arg callback_repo "${GITHUB_REPOSITORY}" \ + --arg callback_pr_number "${{ github.event.issue.number }}" \ + --argjson callback_comment_id "${comment_id_json}" \ + '({ + "gap-pr-url": $pr_url, + "callback-repo": $callback_repo, + "callback-pr-number": $callback_pr_number, + requester: $requester, + command: $command + } + (if $callback_comment_id == null then {} else {"callback-comment-id": ($callback_comment_id | tostring)} end)) as $inputs + | { + ref: $ref, + inputs: $inputs + }' > payload.json + curl -fsSL \ + -X POST \ + -H "Authorization: Bearer ${GH_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + https://api.github.com/repos/gap-system/PackageDistro/actions/workflows/test-gap-pr.yml/dispatches \ + -d @payload.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c8de8a0b1e..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 @@ -56,8 +56,8 @@ jobs: #- name: "Validate types" # run: python -m mypy --disallow-untyped-calls --disallow-untyped-defs dev/releases/*.py - #- name: "Run tests" - # run: python -m pytest tools/tests/dev/releases*.py -vv + - name: "Run tests" + 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 @@ -94,7 +94,7 @@ jobs: - name: "Install autoconf 2.72" # for compatibility with GCC 14 & clang versions run: | - wget https://ftp.gnu.org/gnu/autoconf/autoconf-2.72.tar.xz + wget https://ftpmirror.gnu.org/gnu/autoconf/autoconf-2.72.tar.xz tar xvf autoconf-2.72.tar.xz cd autoconf-2.72 ./configure @@ -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 1aec140fdd..e2512739ec 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -21,6 +21,17 @@ default: all .PHONY: default +######################################################################## +# Developer helper targets +######################################################################## +test_release_scripts: + cd dev/releases && python3 -m pytest +.PHONY: test_release_scripts + +test_release_notes: test_release_scripts +.PHONY: test_release_notes + + ######################################################################## # Source files # @@ -584,9 +595,13 @@ clean: rm -rf .libs rm -f doc/wsp.g rm -f cnf/GAP-* + rm -f configure~ src/config.h.in~ rmdir bin cnf dev doc extern src 2>/dev/null || : # remove dirs if they are now empty -.PHONY: clean distclean +cleanall: clean distclean clean-doc + rm -f src/config.h.in + +.PHONY: clean distclean cleanall ######################################################################## @@ -976,6 +991,7 @@ clean-doc: rm -f doc/*/chooser.html doc/*/manual*.pdf rm -f doc/*/*.{aux,bbl,blg,brf,idx,ilg,ind,lab,log,out,pnr,six,tex,toc} rm -f doc/manualbib.xml.bib + rm -f doc/ref/user_pref_list.xml # FIXME: we currently build the manual inside $srcdir; so we don't want "make clean" # to remove it, as other builds might share the manual. @@ -1007,6 +1023,7 @@ tst/testlibgap/%: build/obj/tst/testlibgap/%.c.o build/obj/tst/testlibgap/common clean: clean-testlibgap clean-testlibgap: rm -f ${LIBGAPTESTS} + rm -f $(addsuffix .out,$(LIBGAPTESTS)) # run all the tests in tst/testlibgap testlibgap: ${LIBGAPTESTS} @@ -1048,6 +1065,7 @@ tst/testkernel/%: build/obj/tst/testkernel/%.c.o libgap$(SHLIB_EXT) clean: clean-testkernel clean-testkernel: rm -f ${KERNELTESTS} + rm -f $(addsuffix .out,$(KERNELTESTS)) # run all the tests in tst/testkernel testkernel: ${KERNELTESTS} diff --git a/benchmark/matobj/bench-matelm-access.g b/benchmark/matobj/bench-matelm-access.g index 889ba71801..f58d365830 100644 --- a/benchmark/matobj/bench-matelm-access.g +++ b/benchmark/matobj/bench-matelm-access.g @@ -136,17 +136,23 @@ RunMatTest := function(desc, m) TestWritingMatrix(m); end; -m:=IdentityMat(10);; -RunMatTest("integer matrix", m); +m:=IdentityMat(10,GF(257));; # plain list of plain lists +RunMatTest("GF(257) plist-of-plist matrix", m); -m:=IdentityMat(10,GF(2));; +m:=IdentityMatrix(GF(257), 10); # IsPlistMatrixRep +RunMatTest("GF(257) IsPlistMatrixRep", m); + +m:=IdentityMatrix(GF(257), 10); # IsGenericMatrixRep +RunMatTest("GF(257) IsGenericMatrixRep", m); + +m:=IdentityMat(10,GF(2));; # plain list of IsGF2VectorRep RunMatTest("GF(2) rowlist", m); -m:=IdentityMat(10,GF(2));; ConvertToMatrixRep(m);; +m:=IdentityMatrix(GF(2), 10); # IsGF2MatrixRep RunMatTest("GF(2) compressed matrix", m); -m:=IdentityMat(10,GF(7));; +m:=IdentityMat(10,GF(7));; # plain list of Is8BitVectorRep RunMatTest("GF(7) rowlist", m); -m:=IdentityMat(10,GF(7));; ConvertToMatrixRep(m);; +m:=IdentityMatrix(GF(7), 10); # Is8BitMatrixRep RunMatTest("GF(7) compressed matrix", m); diff --git a/benchmark/matobj/bench-matobj-creation.g b/benchmark/matobj/bench-matobj-creation.g index d74e5f040e..fdf568d716 100644 --- a/benchmark/matobj/bench-matobj-creation.g +++ b/benchmark/matobj/bench-matobj-creation.g @@ -91,18 +91,23 @@ RunMatTest := function(desc, ring) TestCreatingMatrix(ring); end; -RunMatTest("GF(2)", GF(2)); -RunMatTest("Rationals", Rationals); - RunMatObjTest := function(desc, filter, ring) Print("\n"); PrintBoxed(Concatenation("Testing ", desc)); TestCreatingMatrixObj(filter, ring); end; -RunMatObjTest("GF(2) IsPlistMatrixRep", IsPlistMatrixRep, GF(2)); +RunMatTest("GF(257)", GF(257)); +RunMatObjTest("GF(257) IsPlistMatrixRep", IsPlistMatrixRep, GF(257)); +RunMatObjTest("GF(257) IsGenericMatrixRep", IsGenericMatrixRep, GF(257)); + +RunMatTest("Integers", Integers); RunMatObjTest("integer IsPlistMatrixRep", IsPlistMatrixRep, Integers); +RunMatObjTest("integer IsGenericMatrixRep", IsGenericMatrixRep, Integers); + +RunMatTest("Rationals", Rationals); RunMatObjTest("rational IsPlistMatrixRep", IsPlistMatrixRep, Rationals); +RunMatObjTest("rational IsGenericMatrixRep", IsGenericMatrixRep, Rationals); # TODO: other reps # TODO: other compare with creating plist-of-plist diff --git a/benchmark/transgrp/examine4 b/benchmark/transgrp/examine4 index d1f4d7258d..808ce0eb63 100755 --- a/benchmark/transgrp/examine4 +++ b/benchmark/transgrp/examine4 @@ -39,15 +39,15 @@ WR_POOL:=[[4,3,2,2],[6,11,2,3],[6,13,3,2],[8,44,2,4], [14,57,2,7],[14,61,7,2],[15,93,3,5],[15,102,5,3], [ 16, 1948, 2, 8 ], [ 16, 1947, 4, 4 ], [ 16, 1952, 8, 2 ], [ 18, 968, 2, 9 ], [ 18, 962, 3, 6 ], [ 18, 977, 6, 3 ], -[ 18, 981, 9, 2 ], [ 20, 1110, 2, 10 ], [ 20, 1101, 4, 5 ], -[ 20, 1111, 5, 4 ], [ 20, 1115, 10, 2 ], [ 21, 152, 3, 7 ], -[ 21, 162, 7, 3 ], [ 22, 53, 2, 11 ], [ 22, 57, 11, 2 ], -[ 24, 24979, 2, 12 ], [ 24, 24932, 3, 8 ], [ 24, 24944, 4, 6 ], -[ 24, 24984, 6, 4 ], [ 24, 24994, 8, 3 ], [ 24, 24998, 12, 2 ], +[ 18, 981, 9, 2 ], [ 20, 1110, 2, 10 ], [ 20, 1101, 4, 5 ], +[ 20, 1111, 5, 4 ], [ 20, 1115, 10, 2 ], [ 21, 152, 3, 7 ], +[ 21, 162, 7, 3 ], [ 22, 53, 2, 11 ], [ 22, 57, 11, 2 ], +[ 24, 24979, 2, 12 ], [ 24, 24932, 3, 8 ], [ 24, 24944, 4, 6 ], +[ 24, 24984, 6, 4 ], [ 24, 24994, 8, 3 ], [ 24, 24998, 12, 2 ], [ 25, 209, 5, 5 ], [ 26, 90, 2, 13 ], [ 26, 94, 13, 2 ], [ 27, 2380, 3, 9 ], -[ 27, 2390, 9, 3 ], [ 28, 1834, 2, 14 ], [ 28, 1798, 4, 7 ], -[ 28, 1848, 7, 4 ], [ 28, 1852, 14, 2 ], [ 30, 5696, 2, 15 ], -[ 30, 5666, 3, 10 ], [ 30, 5685, 5, 6 ], [ 30, 5695, 6, 5 ], +[ 27, 2390, 9, 3 ], [ 28, 1834, 2, 14 ], [ 28, 1798, 4, 7 ], +[ 28, 1848, 7, 4 ], [ 28, 1852, 14, 2 ], [ 30, 5696, 2, 15 ], +[ 30, 5666, 3, 10 ], [ 30, 5685, 5, 6 ], [ 30, 5695, 6, 5 ], [ 30, 5706, 10, 3 ], [ 30, 5710, 15, 2 ] ]; @@ -79,7 +79,7 @@ local m,o,i,s,no,te; if Number(l{[2..Length(l)]},i->Size(i)=s)>0 then no:=Normalizer(G,l[1]); if Index(G,no)>500 then - o:=GroupOnSubgroupsOrbit(G,l[1]); + o:=GroupOnSubgroupsOrbit(G,l[1]); else o:=List(RightTransversal(G,no),i->ConjugateGroup(l[1],i)); #o:=[]; @@ -165,7 +165,7 @@ local fun; if IsInt(gens) then return gens; fi; - + pnt:=[1..Minimum(Length(gens),Length(gl))]; if gl{pnt}<>gens then # then we have a difference @@ -361,7 +361,7 @@ Signatures:=function(sys,grp) local l,m,mm,i; m:=ShallowCopy(UnorderedSignatures(sys,grp)); l:=[1..Length(m)]; - for i in l do + for i in l do mm:=m[i]; mm:=mm{Difference(l,[i])}; Sort(mm); @@ -435,7 +435,7 @@ local mm,sign,z,p,m,l,d,i,s,r,j,k,freedom,f,b,Setze,Close; f:=Position(p,f[1]); flag:=false; # we know how to fill - for j in [1..d] do + for j in [1..d] do if m[j][i]=0 then Setze(i,j,f); fi; @@ -475,7 +475,7 @@ local mm,sign,z,p,m,l,d,i,s,r,j,k,freedom,f,b,Setze,Close; # if we force further entries if Length(arg)>2 then for i in arg[3] do - Setze(i[1],i[2],Position(z,i[3])); + Setze(i[1],i[2],Position(z,i[3])); od; fi; @@ -488,7 +488,7 @@ local mm,sign,z,p,m,l,d,i,s,r,j,k,freedom,f,b,Setze,Close; # fix numbers as long as this serves to select the additional rows/columns freedom:=l+1; - + while freedom1 and IsBound(sys.noouts) and sys.noouts and Size(g)=Size(anfst) then - p:=DiagonalGroup(sys,g,step); + p:=DiagonalGroup(sys,g,step); min:=First([1..Length(conj)],i->ConjugateGroup(anfst,conj[i])=p); min:=[min,p]; else @@ -943,7 +943,7 @@ local cand,ncand, # candidates in orbit fmin:=ClosureGroup(fmin,ConjugateGroup(Mno,rt)); #Print("|fg|=",Size(fg)," ind:",Index(cno,fmin),"\n"); - + conj:=Concatenation(conj,List( RightTransversalOp(cno,fmin),i->rt*i)); @@ -966,7 +966,7 @@ local cand,ncand, # candidates in orbit Info(InfoAli,3,Length(cand),"->",Length(ncand)); - Assert(1,not (typ=1 and not repres in ncand)); + Assert(1,not (typ=1 and not repres in ncand)); cand:=ncand; #"andere auf Set? #disabled duplicate removal -- too expensive @@ -1021,7 +1021,7 @@ local cand,ncand, # candidates in orbit if typ=1 then return true; else - #return MinGrpInd(sys.parent,cand,false)[2][1]; + #return MinGrpInd(sys.parent,cand,false)[2][1]; return Minimum(cand); fi; end; @@ -1200,16 +1200,16 @@ local asys,bsys,n,nest,i,l,z,u; fi; if typ=1 and Length(nest[2][1])Concatenation(asys.blocks{j})), - bsys,asys); + bsys,asys); u:=ker^z; u:=Canonize(u,bsys,bsys.wrg,bsys.b,allsdps[nest[1]],2); Add(l,u); @@ -1294,7 +1294,7 @@ local anz,g,d,no,s,o, Print("Warning: Bad luck\n"); fi; - else + else eastep:=false; dag:=false; isopc:=false; @@ -1407,12 +1407,12 @@ local anz,g,d,no,s,o, # At the moment we just recognize an outer group of size 2 if the # whole group is large - if Size(i)=1 and istrans and Size(fa)>20000 and Size(s)=Size(fa) + if Size(i)=1 and istrans and Size(fa)>20000 and Size(s)=Size(fa) and Length(out)=1 and ForAll(GeneratorsOfGroup(s), i->RepresentativeAction(fa,GeneratorsOfGroup(fa), List(GeneratorsOfGroup(fa),j->j^i),OnTuples)<>false) then - + out:=out[1]; # find the power of out that is inner aut:=2; @@ -1642,7 +1642,7 @@ local anz,g,d,no,s,o, for k in fid do fhom:=IsomorphismGroups(Image(j),f[k]); if fhom<>fail then - Add(l,[k,fhom]); + Add(l,[k,fhom]); fi; od; if Length(l)>0 then @@ -1662,7 +1662,7 @@ local anz,g,d,no,s,o, # all possible correspondents for k in faid[j] do - # we will need a further loop for automorphisms + # we will need a further loop for automorphisms for l in fsg[k[1]] do # the glueing homomorphism hom:=k[2]*l; @@ -1690,7 +1690,7 @@ fi; # check, whether necessary properties are fulfilled (if we want # this) if transflag=false - or (NewTransKgVLength(sys,gens,ntsiz,anz)<=anz + or (NewTransKgVLength(sys,gens,ntsiz,anz)<=anz and (levfalse then @@ -1736,7 +1736,7 @@ fi; if levLength(i)>=sys.globalsys.a) and @@ -1763,16 +1763,16 @@ fi; fi; - if - # we take it if: lower level + if + # we take it if: lower level levfalse and Set(MovedPoints(gens))<>[1..sys.a*lev] then Error("unmoved3!"); fi; - od; + od; od; Info(InfoAli,2,"|prae|=",Length(prae)); od; @@ -2032,7 +2032,7 @@ local g,b,i,bs,op,s,x,y,sx,sy,p,g2,xt,yt,t,bp,dom,r,u,v,pairs; if Length(arg)<3 then if x<15 then xt:=TransitiveGroup(x,TransitiveIdentification(t)); - else + else xt:=t; fi; if y<15 then @@ -2108,7 +2108,7 @@ local b,x,y,sx,sy,w,l,hom1,hom2,p,p1,q,m,r,ce,cx,cy,id,ie,u,v,op, l:=Length(GeneratorsOfGroup(sx)); for i in [1..y] do hom2:=GroupHomomorphismByImagesNC(sx,w,GeneratorsOfGroup(sx), - GeneratorsOfGroup(w){[l*(i-1)+1..l*i]}); + GeneratorsOfGroup(w){[l*(i-1)+1..l*i]}); Add(hom1,hom2); od; hom2:=GroupHomomorphismByImagesNC(sy,w,GeneratorsOfGroup(sy), @@ -2159,7 +2159,7 @@ local b,x,y,sx,sy,w,l,hom1,hom2,p,p1,q,m,r,ce,cx,cy,id,ie,u,v,op, # now get the classes of subgroups of w t:=TransitiveSubgroupsWreathProductSymm(w,x,y); - + l:=[]; for i in t do @@ -2173,7 +2173,7 @@ local b,x,y,sx,sy,w,l,hom1,hom2,p,p1,q,m,r,ce,cx,cy,id,ie,u,v,op, pq:=Filtered([1..Length(ie)],x->ie[x]=tx); if Length(pq)>0 then for p in pp do - for q in pq do + for q in pq do # it might embed, so take the 'clean' version r:=KuK(i,b,v[q],u[p]); r:=Subgroup(w,List(GeneratorsOfGroup(i),j->j^r)); @@ -2190,7 +2190,7 @@ local b,x,y,sx,sy,w,l,hom1,hom2,p,p1,q,m,r,ce,cx,cy,id,ie,u,v,op, else ce:=[()]; fi; - + if Length(cy[p])>0 then ce:=List(Cartesian(ce,cy[p]),i->i[1]*Image(hom2,i[2])); fi; @@ -2205,7 +2205,7 @@ local b,x,y,sx,sy,w,l,hom1,hom2,p,p1,q,m,r,ce,cx,cy,id,ie,u,v,op, fi; od; fi; - + m:=List(m,i->ConjugacyClassSubgroups(g,i)); r:=[]; for j in m do @@ -2274,7 +2274,7 @@ local pmp,b,s,u,w,n,g,op,oh,hom,omp,k,f,v,co,i,j,jj,new,cl,sug,nsug,fg,pi, Info(InfoAli,3,"reducing normalizer generators"); fi; g:=Group(op); #always make a new group to permit throwing away all permrep. - # information + # information oh:=ActionHomomorphism(g,b,OnSets,"surjective"); op:=Image(oh); @@ -2327,9 +2327,9 @@ local pmp,b,s,u,w,n,g,op,oh,hom,omp,k,f,v,co,i,j,jj,new,cl,sug,nsug,fg,pi, # A_n Error("A_n"); # special case: full wreath products - elif ForAny(WR_POOL,i->i[1]=dop and + elif ForAny(WR_POOL,i->i[1]=dop and i[2]=TransitiveIdentification(op)) then - u:=First(WR_POOL,i->i[1]=dop and + u:=First(WR_POOL,i->i[1]=dop and i[2]=TransitiveIdentification(op)); Info(InfoAli,2,"transitive subgroups of S(",u[3],") wr S(",u[4],")"); u:=TransitiveSubgroupsWreathProductSymm(op,u[3],u[4]); @@ -2351,7 +2351,7 @@ local pmp,b,s,u,w,n,g,op,oh,hom,omp,k,f,v,co,i,j,jj,new,cl,sug,nsug,fg,pi, #pi:=AsSubgroup(MySymmetricGroup(dop),op); pi:=op; v:=Normalizer(MySymmetricGroup(dop),pi); - if Index(v,pi)=2 and ForAny(WR_POOL,i->i[1]=dop and + if Index(v,pi)=2 and ForAny(WR_POOL,i->i[1]=dop and i[2]=TransitiveIdentification(v)) then u:=First(WR_POOL,i->i[1]=dop and i[2]=TransitiveIdentification(v)); Info(InfoAli,2,"transitive subgroups of NT of S(",u[3],") wr S(", @@ -2420,7 +2420,7 @@ local pmp,b,s,u,w,n,g,op,oh,hom,omp,k,f,v,co,i,j,jj,new,cl,sug,nsug,fg,pi, ino:=Normalizer(ino,co[j]); j:=j-1; od; - + else ino:=Normalizer(op,i); fi; @@ -2508,14 +2508,14 @@ local pmp,b,s,u,w,n,g,op,oh,hom,omp,k,f,v,co,i,j,jj,new,cl,sug,nsug,fg,pi, # # fusion only takes place in the normalizer (as k\lhd f) -# +# # if IsPcGroup(ino) then # # elif largedeg=true then # # else -# +# # else # for j in co do # cl:=ConjugacyClassSubgroups(ino,j); @@ -2610,7 +2610,7 @@ local el,oldnorm,cen,to,erg,Recurse; # now collect fusion classes orcl:=[]; while Length(o)>0 do - if true or Size(cen)/Size(o[1][1])<30000 + if true or Size(cen)/Size(o[1][1])<30000 or Index(cen,Centralizer(cen,o[1][1]))<30000 then bahn:=Orbit(cen,o[1][1]); cen2:=Filtered([2..Length(o)],i->ForAny(o[i],j->j in bahn)); @@ -2714,7 +2714,7 @@ local el,oldnorm,cen,to,erg,Recurse; Recurse(no,cen,to,el,oldnorm); - if Length(erg)>1 then + if Length(erg)>1 then erg:=[Minimum(erg)]; fi; return erg[1];; @@ -2769,7 +2769,7 @@ local no,grp,sys,v,nopa; # it's cheaper to take the transversal return MinimumGroupOnSubgroupsOrbit(grp,v,no); else - nopa:=SmallSubgroupCanonizer(sys,no,v); + nopa:=SmallSubgroupCanonizer(sys,no,v); if nopa=fail then if ForAny(AllBlocks(no),i->Length(i)RepresentativeAction(sys.kr,i,a)=fail) then @@ -3127,7 +3127,7 @@ local d,u,i,ii,homs,v,o,j,sz,a,sym,dd,prms,p,weg,itra,abi,jind,abig,ag; fi; od; - + #Exec("cp sdpstmp1 sdpstmp1.bak"); #PrintTo("sdpstmp1",u,"\n",weg,"\n"); @@ -3202,7 +3202,7 @@ local n,o,bl,i,b,flag,nt,op,fil,z,id,bo; #nt:=Subgroup(sys.parent,List(GeneratorsOfGroup(nt),i->i^z)); nt:=ConjugateGroup(nt,z); - + # and canonize Info(InfoAli,2,"Block canonizing"); TIMING.canon:=Runtime()-TIMING.canon; @@ -3228,7 +3228,7 @@ local n,o,bl,i,b,flag,nt,op,fil,z,id,bo; nt:=Subgroup(sys.parent,List(GeneratorsOfGroup(grp),i->i^z)); TIMING.ctest:=Runtime()-TIMING.ctest; Info(InfoAli,2,"Conj. test, "); - + # special case: regular groups (for which the conj. test # is extremely expensive) if IsRegular(nt,[1..sys.a*sys.b]) then @@ -3395,7 +3395,7 @@ local i,j,l,p,sup,dom,use,lcl; od; p:=List(p,i->TransitiveIdentification(Representative(lcl[i]))); - return p; + return p; end; # get the minimal transitive groups whose point stabilizer is divides by siz @@ -3483,12 +3483,12 @@ local bls, # block size for i in p do Add(n,TransitiveGroup(bls,TransitiveIdentification(i))); if Size(i)IsTransitive(j,[1..bls]) and not IsPrimitive(j,[1..bls])); for j in nt do id:=TransitiveIdentification(j); - if not id in nids and + if not id in nids and # index divides one stab size ForAny(indices,x->x mod Index(i,j)=0) then Add(nids,id); @@ -3532,7 +3532,7 @@ local bls, # block size Info(InfoAli,1,"not primitive, actions changed from ",MINTRANSIND[bla], " to ",minops); minops:=List(minops,i->TransitiveGroup(bla,i)); - + else # test, whether it is sufficient to use for invariants: minops:=trueminops; @@ -3596,7 +3596,7 @@ local bls, # block size # get all characteristic subgroups which are transitive and index # coprime to sizes of minimal transitive factor groups nt:=NormalSubgroups(i); - nt:=Filtered(nt,j->IsAbelian(j) and Index(i,j)>1 + nt:=Filtered(nt,j->IsAbelian(j) and Index(i,j)>1 and IsTransitive(j,MovedPoints(i)) and ForAll(minops,k->Gcd(Index(i,j),Size(k))=1)); nt:=Filtered(nt,j->IsCharacteristicSubgroup(i,j)); @@ -3612,7 +3612,7 @@ local bls, # block size Info(InfoAli,1,"Get actgroups bottom"); nt:=nt[1]; # will give the smallest number of sdps # construct the sdp's for nt - actgroups:=TGInvariantSubgroups(sys,GeneratorsOfGroup(nt),trueminops); + actgroups:=TGInvariantSubgroups(sys,GeneratorsOfGroup(nt),trueminops); Info(InfoAli,1,"Get actgroups top"); # get the groups which act on them, select those whose block # action is small @@ -3694,7 +3694,7 @@ TIMING.sdp:=Runtime()-TIMING.sdp; #Auskommentiert, da: tests already for no smaller local operation !!!! #Print("TRANSFLAG!\n"); #gsys.transflag:=true; - neu:=ConstructSubdirectProducts(gsys,lplbs[j]); + neu:=ConstructSubdirectProducts(gsys,lplbs[j]); Info(InfoAli,3,"supos=",neu); # remember all for future tests @@ -3827,7 +3827,7 @@ TIMING.cheat:=Runtime()-TIMING.cheat; # test, whether we might need automorphism fuse if ForAny(blopid,i->i=j) then flag:=1; - fi; + fi; else Info(InfoAli,2,"inappropriate operation"); fi; @@ -3853,7 +3853,7 @@ TIMING.cheat:=Runtime()-TIMING.cheat; # we have to test g^(an)=u, i.e. a has to be determined only up to # right multiplication by the normalizer -- that is left coset # representatives of the normalizer - l:=RightTransversal(au,l); + l:=RightTransversal(au,l); l:=List(l,Inverse); s:=[]; @@ -3867,7 +3867,7 @@ TIMING.cheat:=Runtime()-TIMING.cheat; Info(InfoAli,1,"old 'cheating' group"); fi; od; - else + else if Length(r)=0 then Info(InfoAli,1,"no blow-ups"); elif Length(r)=1 then diff --git a/configure.ac b/configure.ac index 6d1531a3ca..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]) @@ -23,7 +23,7 @@ dnl 2. Otherwise (i.e., if no interfaces have been removed or changed), dnl if any interfaces have been added since the last public release, then dnl increment minor. dnl -m4_define([kernel_major_version], [10]) +m4_define([kernel_major_version], [11]) m4_define([kernel_minor_version], [0]) m4_define([GAP_DEFINE], [GAP_DEFINES="$GAP_DEFINES -D$1"]) @@ -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/gapmacro2gapdoc.g b/dev/gapmacro2gapdoc.g index 512d15d091..3219338205 100755 --- a/dev/gapmacro2gapdoc.g +++ b/dev/gapmacro2gapdoc.g @@ -65,13 +65,13 @@ ## (:digraph in vi). ## ## These are the proposed steps for translating a manual. -## +## ## 1. By hand: ## Copy the old style `doc/manual.six' file to `doc/manual.six.old' ## (Note that processing the GAPDoc format manual will create ## `doc/manual.six' but in GAPDoc format, which is not supported by ## the functions for switching to GAPDoc.) -## +## ## 2. By hand: ## Create a new main file `main.xml' that will replace ## the old main file `manual.tex'. @@ -81,16 +81,16 @@ ## \FrontMatter -> ## for chapters: \Input -> <#Include> ## etc.) -## +## ## 3. By hand: ## Create `makedocrel.g' that will replace `buildman.config'. ## (Copy it from an existing package that uses GAPDoc; ## the call to `MakeGAPDocDoc' is the main ingredient.) -## +## ## 4. Semi-automatically: ## Create `doc/*.xml' files from the corresponding `doc/*.msk' files, ## by calling the function `TranslateMSK2XML' for each `doc/*.msk' file. -## +## ## 5. Semi-automatically: ## Create `lib/*.g*.new' files corresponding to `lib/*.g*' files, ## by calling the function `TranslateLib2XML' for each relevant @@ -99,13 +99,13 @@ ## The code in the old and the new file should be unchanged, ## just the documentation is rewritten. ## (Test this!) -## +## ## 6. Read the file `makedocrel.g', in order to process the documentation ## with GAPDoc, and correct the errors reported by GAPDoc. ## (Since the main manuals were translated, GAPDoc was improved a lot ## w.r.t. debugging, so this should be much easier than it was at the ## beginning of 2007.) -## +## ## 7. By hand: ## Edit the new files, in order to ## - improve formulations around @@ -114,7 +114,7 @@ ## - reformat the paragraphs, ## - fix places that were not handled optimally. ## Check for `???' in html files, which indicate broken references. -## +## ## 8. By hand: ## Start using GAPDoc's facilities: ## - insert "Where" in , @@ -123,7 +123,7 @@ ## - change the bibliography to the XML based format, ## - introduce subsections (beyond ) for structuring purposes, ## - ... -## +## ## 9. By hand: ## - Convince yourself that GAP code was not changed by the conversions. ## - Convince yourself that nothing from the old version of the manual @@ -340,7 +340,7 @@ RewriteText:= function( str ) [ [ "\\Declaration{", "}" ], [ "<#Include Label=", ">" ] ], [ [ "\\Mailto{", "}" ], [ "", "" ] ], [ [ "\n#T", "\n" ], [ "\n\n" ] ], - ]; + ]; for pair in replacementpairs do newstr:= ""; @@ -413,7 +413,7 @@ RewriteText:= function( str ) [ "for", "for" ], [ "while", "while" ], # [ "%\n", "\n" ], - ]; + ]; for pair in replacements do str:= ReplacedString( str, pair[1], pair[2] ); @@ -531,7 +531,7 @@ SplitLibFile:= function( filename ) code:= not code; else Add( partlines, line ); - fi; + fi; od; return parts; end; @@ -554,10 +554,10 @@ TranslatedIndentedText:= function( str ) Append( newstr, pair[2][1] ); for i in [ 2 .. Length( pair[2] ) ] do Append( newstr, cand[3] ); - Append( newstr, pair[2][i] ); + Append( newstr, pair[2][i] ); od; str:= Concatenation( newstr, cand[4] ); - fi; + fi; until cand = fail; od; @@ -565,7 +565,7 @@ TranslatedIndentedText:= function( str ) str:= ReplacedString( str, "\n## ", "\n" ); str:= ReplacedString( str, "\n## \n", "\n\n" ); str:= ReplacedString( str, "\n##\n", "\n\n" ); - + # translate str:= str{ [ 2 .. Length( str )-1 ] }; str:= Concatenation( "\n", TranslateText( str ), "\n" ); @@ -638,7 +638,7 @@ RewriteNonCodePart:= function( str, filename ) "\n##\n", "## <#GAPDoc Label=\"", name, "\">\n", "## \n" ); - fi; + fi; Append( declstr, Concatenation( "## \n" ) ); startpos:= pos2-1; @@ -922,7 +922,7 @@ end; TranslateLib2XML:= function( filename ) local str, entry, size, target; - + str:= ""; for entry in SplitLibFile( filename ) do if str <> "" then diff --git a/dev/manualutils.g b/dev/manualutils.g index 04d034f1d3..5a76c830f8 100644 --- a/dev/manualutils.g +++ b/dev/manualutils.g @@ -181,7 +181,7 @@ PrintInfoAboutManualChapters:= function( pathtodoc, main, files, chapnrs ) ", line ", pos[2], "\n" ); od; fi; - + # Compute the subset of elements whose contents are keywords, # and which should probably (but not necessarily!) be replaced by # the corresponding elements. @@ -197,7 +197,7 @@ PrintInfoAboutManualChapters:= function( pathtodoc, main, files, chapnrs ) ", line ", pos[2], "\n" ); od; fi; - + od; #T perhaps return all the computed information? end; @@ -219,7 +219,7 @@ OverviewOfChaptersForProofreadingForm:= function( pathtodoc, main, files ) str:= ComposedDocument( "GAPDoc", Directory( pathtodoc ), main, files, true ); xmltree:= ParseTreeXMLString( str[1], str[2] ); - elms:= List( XMLElements( xmltree, "Chapter" ), + elms:= List( XMLElements( xmltree, "Chapter" ), x -> XMLElements( x, [ "Heading" ] )[1] ); filecontents:= ""; @@ -299,7 +299,7 @@ ChainedExamples:= function( pathtodoc, main, files ) end; # finds the following occurrences in the ref. manual: -# +# # [ [ "\n

\n", [ "./mloop.xml", 231 ] ], # done # [ "\n

\n", [ "./streams.xml", 131 ] ], # done # [ "\n

\n", [ "./word.xml", 117 ] ], # done @@ -321,9 +321,9 @@ end; # [ "\n

\n", [ "./algebra.xml", 331 ] ], # done # [ "\n

\n", [ "./ctbl.xml", 1241 ] ], # done # [ "\n

\n", [ "./ctbl.xml", 1275 ] ], # done -# [ "\n

\n", [ "./mloop.xml", 423 ] ], -# [ "\n

\n", [ "./lists.xml", 708 ] ], -# [ "\n

\n", [ "./grplib.xml", 673 ] ], +# [ "\n

\n", [ "./mloop.xml", 423 ] ], +# [ "\n

\n", [ "./lists.xml", 708 ] ], +# [ "\n

\n", [ "./grplib.xml", 673 ] ], # [ "\n

\n", [ "./../../lib/process.gd", 82 ] ], # done # [ "\n

\n", [ "./../../lib/process.gd", 89 ] ] ] # done 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/release_notes.py b/dev/releases/release_notes.py index 58e7119bb9..9d7eaf9cac 100755 --- a/dev/releases/release_notes.py +++ b/dev/releases/release_notes.py @@ -221,7 +221,7 @@ def get_pr_list(date: str, extra: str) -> List[Dict[str, Any]]: "--search", query, "--json", - "number,title,closedAt,labels,mergedAt", + "number,title,closedAt,labels,mergedAt,author", "--limit", "200", ], @@ -245,6 +245,14 @@ def has_label(pr: Dict[str, Any], label: str) -> bool: return any(x["name"] == label for x in pr["labels"]) +def is_dependabot_pr(pr: Dict[str, Any]) -> bool: + author = pr.get("author") or {} + login = author.get("login") + if login in ("app/dependabot", "dependabot[bot]"): + return True + return author.get("is_bot", False) and has_label(pr, "dependencies") + + def changes_overview( prs: List[Dict[str, Any]], startdate: str, new_version: str ) -> None: @@ -361,6 +369,7 @@ def main(new_version: str) -> None: print("Downloading filtered PR list") prs = get_pr_list(startdate, extra) + prs = [pr for pr in prs if not is_dependabot_pr(pr)] # print(json.dumps(prs, sort_keys=True, indent=4)) changes_overview(prs, startdate, new_version) 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/test_release_notes.py b/dev/releases/test_release_notes.py new file mode 100644 index 0000000000..a06161afed --- /dev/null +++ b/dev/releases/test_release_notes.py @@ -0,0 +1,107 @@ +import release_notes + + +def test_is_dependabot_pr_detects_dependabot_author(): + pr = { + "author": {"is_bot": True, "login": "app/dependabot"}, + "labels": [ + {"name": "dependencies"}, + {"name": "github_actions"}, + ], + } + + assert release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"is_bot": True, "login": "app/notdependabot"}, + "labels": [ + {"name": "dependencies"}, + {"name": "github_actions"}, + ], + } + + assert release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"is_bot": False, "login": "app/dependabot"}, + "labels": [ + {"name": "dependencies"}, + {"name": "github_actions"}, + ], + } + + assert release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"is_bot": False, "login": "app/notdependabot"}, + "labels": [ + {"name": "dependencies"}, + {"name": "github_actions"}, + ], + } + + assert not release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"is_bot": False, "login": "app/dependabot"}, + "labels": [ + {"name": "github_actions"}, + ], + } + + assert release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"is_bot": False, "login": "app/notdependabot"}, + "labels": [ + {"name": "github_actions"}, + ], + } + + assert not release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"is_bot": True, "login": "app/notdependabot"}, + "labels": [ + {"name": "github_actions"}, + ], + } + + assert not release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"is_bot": False, "login": "dependabot[bot]"}, + "labels": [ + {"name": "github_actions"}, + ], + } + + assert release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"login": "dependabot[bot]"}, + "labels": [ + {"name": "github_actions"}, + ], + } + + assert release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"login": "app/notdependabot"}, + "labels": [ + {"name": "github_actions"}, + ], + } + + assert not release_notes.is_dependabot_pr(pr) + + pr = { + "author": {"login": "app/notdependabot"}, + "labels": [ + {"name": "dependencies"}, + {"name": "github_actions"}, + ], + } + + assert not release_notes.is_dependabot_pr(pr) 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/makedocreldata.g b/doc/ref/makedocreldata.g index f2f1697bed..22993e3497 100644 --- a/doc/ref/makedocreldata.g +++ b/doc/ref/makedocreldata.g @@ -119,6 +119,7 @@ GAPInfo.ManualDataRef:= rec( "../../lib/matobj2.gd", "../../lib/matobjnz.gd", "../../lib/matobjplist.gd", + "../../lib/matobjgeneric.gd", "../../lib/matrix.gd", "../../lib/meataxe.gi", "../../lib/memory.gd", diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index ddbaa2871d..d07e883708 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -21,6 +21,63 @@ cf. Chapters and . + +

+Some Elementary Examples +Just to give a flavour of these new objects, we construct here two vectors +and matrices in these new forms. +The elements should all belong to a semiring R +(the BaseDomain). +To construct these objects we use the operations +Vector and Matrix which are described in Section +. +

+Basic arithmetic operations for vectors and matrices are available: +see Sections and +. +

+Note that if m2, like m2, had been defined over the integers +then attempting to have displayed its inverse would have thrown an error. +

+ dom := Integers;; +gap> v1 := Vector( dom, [3,4,7,8] );; +gap> Print( v1 ); +NewVector(IsPlistVectorRep,Integers,[ 3, 4, 7, 8 ]) +gap> m1 := Matrix( dom, [ [1,2,3,4], [6,7,8,9] ] );; +gap> Display( m1 ); +<2x4-matrix over Integers: +[[ 1, 2, 3, 4 ] + [ 6, 7, 8, 9 ] +]> +gap> v2 := Vector( [-7..-4], v1 ); + +gap> Print( v1 + v2 ); +NewVector(IsPlistVectorRep,Integers,[ -4, -2, 2, 4 ]) +gap> Display( (v1+v2) * TransposedMat( m1 ) ); + +gap> m2 := Matrix( Rationals, [ [8,5], [7,4] ] );; +gap> Display( m2^(-1) ); +<2x2-matrix over Rationals: +[[ -4/3, 5/3 ] + [ 7/3, -8/3 ] +]> +]]> + +These objects need to know their type, or filter. +The simplest of these use plain lists, namely +and , +which &GAP; chooses automatically for v1 and M. +Note that v2 acquires its type by being defined relative to v1. +Other available types are listed in Sections + and +. + +

+ +
Categories of Vector and Matrix Objects @@ -55,13 +112,13 @@ More can be added as soon as there is need for them.
Constructing Vector and Matrix Objects -<#Include Label="NewVector"> <#Include Label="Vector"> <#Include Label="VectorObj_ZeroVector"> -<#Include Label="NewMatrix"> +<#Include Label="NewVector"> <#Include Label="MatObj_Matrix"> <#Include Label="MatObj_ZeroMatrix"> <#Include Label="MatObj_IdentityMatrix"> +<#Include Label="NewMatrix">
@@ -374,6 +431,7 @@ described in this chapter is supported. <#Include Label="IsGF2MatrixRep"> <#Include Label="Is8BitMatrixRep"> <#Include Label="IsPlistMatrixRep"> +<#Include Label="IsGenericMatrixRep"> <#Include Label="IsZmodnZMatrixRep">
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/hpcgap/lib/helpbase.gi b/hpcgap/lib/helpbase.gi index 921d65a236..2599559156 100644 --- a/hpcgap/lib/helpbase.gi +++ b/hpcgap/lib/helpbase.gi @@ -752,9 +752,9 @@ end); ############################################################################# ## -#F HELP_SHOW_BOOKS( ignored... ) . . . . . . . . . . . show available books +#F HELP_SHOW_BOOKS() . . . . . . . . . . . . . . . . . show available books ## -InstallGlobalFunction(HELP_SHOW_BOOKS, function( arg ) +InstallGlobalFunction(HELP_SHOW_BOOKS, function() local books; atomic readonly HELP_REGION do diff --git a/hpcgap/lib/primality.gi b/hpcgap/lib/primality.gi index f7ee40ad25..16294ad5ee 100644 --- a/hpcgap/lib/primality.gi +++ b/hpcgap/lib/primality.gi @@ -347,71 +347,6 @@ end); # while Jacobi( P^2-4, N ) <> -1 do P:=(P+1) mod N; if P = 2 then return fail; fi; od; # return [ (P^2-4) mod N, P, 1 ]; #end; -#InstallGlobalFunction(IsBPSWLucasPseudoPrime, -#function(N) -# local params, func, lucas; -# if N = 2 then return true; fi; -# if IsSquareInt(N) or IsEvenInt(N) then return false; fi; -# if ValueOption("BPSWLucasParameters") = fail -# then func:=BPSWLucasParameters_GAP; -# else func:=ValueOption("BPSWLucasParameters"); -# fi; -# if ValueOption("BPSWLucasTest") = fail then -# if func = BPSWLucasParameters_GAP -# then lucas:=function(N,D,P) return TraceModQF(P,N+1,N) = [2,P]; end; -# else lucas:=IsLucasPseudoPrimeDP; -# fi; -# else lucas:=ValueOption("BPSWLucasTest"); -# fi; -# params := CALL_FUNC_LIST(func,[N]); -# if Jacobi(params[1],N) = 0 and params[1] < N and 0 < params[1] then return false; fi; -# return CALL_FUNC_LIST(lucas,[N, params[1], params[2]]); -#end); - -############################################################################## -## -#F IsLucasPseudoPrimeDP(N,D,P) - Check if N is a Lucas pseudoprime for -## x^2+P*x+(P^2-D)/4. D must be a nonsquare mod N, and N must be odd or prime. -## -############################################################################## -InstallGlobalFunction(IsLucasPseudoPrimeDP, -function(N,D,P) - local Q; - if N = 2 then return true; fi; - Q := (P^2-D)/4 mod N; - if not ( IsOddInt(N) and 0 <> Q mod N and Jacobi(D,N) = -1 ) then Error(); fi; - return IsOddInt(N) and 0 <> Q mod N and Jacobi(D,N) = -1 and 0 = LucasMod(P,Q,N,N+1)[1]; -end); - -############################################################################## -## -#F IsStrongLucasPseudoPrimeDP(N,D,P) - Check if N is a strong Lucas -## pseudoprime for x^2+P*x+(P^2-D)/4. N must be odd or prime. -## -############################################################################## -InstallGlobalFunction(IsStrongLucasPseudoPrimeDP, -function(N,D,P) - local Q,d,s,J,L,r,Qi; - if N = 2 then return true; fi; - if N in [-1,0,1] then return false; fi; - if not ( IsOddInt(N) and GcdInt(N,D)=1 ) then return false; fi; - Q := (P^2-D)/4 mod N; - J := Jacobi(D,N); - d := N - J; s:=0; while IsEvenInt(d) do s:=s+1; d:=d/2; od; # Now N-(D/N) = 2^s * d, d odd - L := LucasMod(P,Q,N,d); - # Does n divide U_d ? - if L[1] = 0 then return true; fi; - # Does n divide V_{2^r d} for some r=0,1,...,s-1 ? - Qi := PowerModInt(Q,d,N); - for r in [0..s-1] do - if L[2] = 0 then return true; fi; - # L is [Ui,Vi], make it [U2i,V2i] = [ Ui*Vi, Vi^2 - 2Q^i], where i=2^s d - L[1] := L[1]*L[2] mod N; - L[2] := (L[2]^2 - 2*Qi) mod N; - Qi := Qi*Qi mod N; - od; - return false; -end); ############################################################################## ## diff --git a/hpcgap/lib/vec8bit.gi b/hpcgap/lib/vec8bit.gi index 31af64cad8..02154628bb 100644 --- a/hpcgap/lib/vec8bit.gi +++ b/hpcgap/lib/vec8bit.gi @@ -1030,7 +1030,7 @@ InstallMethodWithRandomSource( Randomize, for i in [1..Length(v)] do v[i] := Random(rs,l); od; return v; end ); -InstallMethod( MutableCopyMatrix, "for an 8bit matrix", +InstallOtherMethod( MutableCopyMatrix, "for an 8bit matrix", [ Is8BitMatrixRep ], function( m ) local mm; @@ -1133,10 +1133,16 @@ InstallMethod( BaseField, "for a compressed 8bit vector", InstallTagBasedMethod( NewVector, Is8BitVectorRep, function( filter, f, l ) - if ValueOption( "check" ) <> false and not Size(f) in [3..256] then + local check, res; + check:= ValueOption( "check" ) <> false; + if check and not Size(f) in [3..256] then Error("Is8BitVectorRep only supports base fields with 3 to 256 elements"); fi; - return CopyToVectorRep(l,Size(f)); + res:= CopyToVectorRep( l, Size( f ) ); + if check and res = fail then + Error( "cannot copy to 'Is8BitVectorRep'" ); + fi; + return res; end ); # This is faster than the default method. @@ -1170,7 +1176,9 @@ InstallTagBasedMethod( NewMatrix, else m := List(l,ShallowCopy); fi; - ConvertToMatrixRep(m,Size(f)); + if ConvertToMatrixRep( m, Size( f ) ) = fail then + Error( "cannot convert to 'Is8BitMatrixRep'" ); + fi; return m; end ); diff --git a/hpcgap/lib/vecmat.gi b/hpcgap/lib/vecmat.gi index e582db8b0f..121736776e 100644 --- a/hpcgap/lib/vecmat.gi +++ b/hpcgap/lib/vecmat.gi @@ -2436,7 +2436,7 @@ InstallMethodWithRandomSource( Randomize, return v; end ); -InstallMethod( MutableCopyMatrix, "for a gf2 matrix", +InstallOtherMethod( MutableCopyMatrix, "for a gf2 matrix", [ IsGF2MatrixRep ], function( m ) local mm; @@ -2555,8 +2555,13 @@ InstallMethod( BaseField, "for a compressed gf2 vector", InstallTagBasedMethod( NewVector, IsGF2VectorRep, function( filter, f, l ) + local res; if Size(f) <> 2 then Error("IsGF2VectorRep only supported over GF(2)"); fi; - return CopyToVectorRep(l,2); + res:= CopyToVectorRep( l, 2 ); + if res = fail then + Error( "cannot copy to 'IsGF2VectorRep'" ); + fi; + return res; end ); InstallTagBasedMethod( NewZeroVector, @@ -2583,7 +2588,9 @@ InstallTagBasedMethod( NewMatrix, else m := List(l,ShallowCopy); fi; - ConvertToMatrixRep(m,2); + if ConvertToMatrixRep( m, 2 ) = fail then + Error( "cannot convert to 'IsGF2MatrixRep'" ); + fi; return m; 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/clas.gi b/lib/clas.gi index 864fdea22c..b933b7d50b 100644 --- a/lib/clas.gi +++ b/lib/clas.gi @@ -116,7 +116,7 @@ local fam, filter, cl; fi; filter:=filter and HasActingDomain and HasRepresentative and HasFunctionAction; - fam!.defaultClassType:=NewType( FamilyObj( G ), filter ); + fam!.defaultClassType:=NewType( fam, filter ); fi; cl:=rec( start := [ g ] ); @@ -141,7 +141,7 @@ local fam, filter, cl; fi; filter:=filter and HasActingDomain and HasRepresentative and HasFunctionAction and HasStabilizerOfExternalSet; - fam!.defaultClassCentType:=NewType( FamilyObj( G ), filter ); + fam!.defaultClassCentType:=NewType( fam, filter ); fi; cl:=rec( start := [ g ]); diff --git a/lib/combinat.gd b/lib/combinat.gd index f89bbc550a..38a2abfaf8 100644 --- a/lib/combinat.gd +++ b/lib/combinat.gd @@ -1169,14 +1169,16 @@ DeclareGlobalFunction("NrRestrictedPartitions"); ## DeclareGlobalFunction( "IteratorOfPartitions" ); - ############################################################################# ## -#F IteratorOfPartitionsSet( [, [ ] ] ) +#F IteratorOfPartitionsSet( [, [, ] ] ) +#F EnumeratorOfPartitionsSet( [, [, ] ] ) ## ## <#GAPDoc Label="IteratorOfPartitionsSet"> ## -## +## Iterator and enumerator of unordered set partitions +## +## ## ## ## returns an iterator @@ -1187,12 +1189,33 @@ DeclareGlobalFunction( "IteratorOfPartitions" ); ## then only partitions of size k are computed. ## If k is given and flag is equal to true, ## then only partitions of size at most k are computed. +##

+## returns an enumerator +## (see ) for all unordered partitions of the +## set set. The arguments k and flag function in the +## same manner as for the iterator. +##

+## The ordering of the partitions from these functions can be different and +## also different from the list returned by . +##

+## +## gap> m:=[1..9];; +## gap> Bell(9); +## 21147 +## gap> Length(PartitionsSet(m)); +## 21147 +## gap> cm := EnumeratorOfPartitionsSet(m);; +## gap> cm[1000]; +## [ [ 1, 2, 4, 9 ], [ 3, 6, 8 ], [ 5, 7 ] ] +## gap> Position(cm, last); +## 1000 +## ## ## ## <#/GAPDoc> ## DeclareGlobalFunction( "IteratorOfPartitionsSet" ); - +DeclareGlobalFunction( "EnumeratorOfPartitionsSet" ); ############################################################################# ## diff --git a/lib/combinat.gi b/lib/combinat.gi index 672992d0d5..0dad5dcfe5 100644 --- a/lib/combinat.gi +++ b/lib/combinat.gi @@ -2429,6 +2429,191 @@ InstallGlobalFunction( "IteratorOfPartitions", function( n ) next := 0 * [ 1 .. n ] + 1 ) ); end ); +############################################################################# +## +#F EnumeratorOfPartitionsSet( [, [, ] ] ) +## + + +InstallGlobalFunction(EnumeratorOfPartitionsSet , function(s, arg...) + local k, r, l, j, cumulative_stirling, ElementNumber, NumberElement; + + if not IsSet(s) then + Error( "EnumeratorOfPartitionsSet: must be a set" ); + fi; + + l := Length(s); + + # Method for finding n-th k-partition of s, does not + # do argument checking, this is done further down when + # instantiating the enumerators. + ElementNumber := function(enu, n, k) + local res, j, kp, np, t, i; + if l = 0 and n = 0 and k = 0 then + return []; + fi; + + res := List([1 .. k], x -> []); + # kp is the largest index of still active parts. + # Every time kp is decremented, we guarantee that + # res[kp + 1] will not be changed anymore. + kp := k; + # np keeps track of the part of n that we still need + # to process. Use it to avoid recursive calls. + np := n; + for j in [l, l - 1 .. 1] do + # Intuitively, we use identity + # Stirling2(j, k') = Stirling2(j-1, k'-1) + k' * Stirling2(j-1, k') + # to recursively encode partitions in the following manner: + # If n < Stirling2(j-1, k'-1), then we recursively construct + # the (k'-1)-partition corresponding to n and add a new singleton part + # consisting solely of s[j] to it. + # Otherwise, we can write n = Stirling2(j-1, k'-1) + i * Stirling(j-1, k') + n' + # for some numbers i and n' such that + # i < k' and n' < Stirling2(j-1, k'). + # We then recursively construct the k'-partition corresponding to n' and + # add s[j] to the i-th part. + t := Stirling2(j - 1, kp - 1); + if np <= t then + # Add last element to part kp, and + # decrement kp to mark res[kp] as complete. + Add(res[kp], s[j]); + kp := kp - 1; + else + # np and i are the numbers n' and i described above. + np := np - t; + t := Stirling2(j - 1, kp); + i := QuoInt(np - 1, t) + 1; + Add(res[i], s[j]); + np := ((np - 1) mod t) + 1; + fi; + od; + return List(res, Reversed); + end; + + NumberElement := function(enu, p, k) + local res, kp, ks, sp, perm, i, j, jp; + + if not IsSet(p) or Length(p) <> k then + return fail; + fi; + + if Length(p) = 0 then + if l = 0 and k = 0 then + return 1; + fi; + return fail; + fi; + + # ks[i] is the index corresponding to the + # end of the i-th part of p in the flattened + # version of p (stored as sp) + ks := []; + sp := []; + for kp in [1 .. k] do + if not IsSet(p[kp]) then + return fail; + fi; + if kp = 1 then + Add(ks, Length(p[kp])); + else + Add(ks, ks[Length(ks)] + Length(p[kp])); + fi; + Append(sp, p[kp]); + od; + + # Every partition of s must store all of the same elements as s. + perm := PermListList(sp, s); + if perm = fail then + return fail; + fi; + + res := 1; + kp := k; + for j in [l, l - 1 .. 1] do + jp := j^perm; + # i is the part of p that s[j] is in + i := PositionSorted(ks, jp); + + # Check passes if and only if s[j] is the first element of the i-th + # part of p. According to our encoding convention in ElementNumber, + # this means that the remaining partition is a (kp-1)-partition. + if jp = 1 or (i > 1 and ks[i - 1] + 1 = jp) then + kp := kp - 1; + else + # Otherwise, we perform the reverse manipulation to the one + # modifying np in ElementNumber + res := res + (i-1) * Stirling2(j-1, kp) + Stirling2(j-1, kp-1); + fi; + od; + + return res; + end; + + r := rec(s := s, l := l); + if Length(arg) = 1 or Length(arg) = 2 then + k := arg[1]; + if not IsInt(k) then + Error("EnumeratorOfPartitionsSet: must be an integer"); + fi; + fi; + + if (Length(arg) = 2 and arg[2] = true) or (Length(arg) = 0) then + # k parts or less, also handles all partition case. + if Length(arg) = 0 then + k := l; + else + k := Minimum(k, l); + fi; + + cumulative_stirling := [Stirling2(l, 0)]; + for j in [1 .. k] do + Add(cumulative_stirling, cumulative_stirling[j] + Stirling2(l, j)); + od; + r.cumulative_stirling := cumulative_stirling; + r.ElementNumber := function(enu, n) + local kp; + if n > cumulative_stirling[k + 1] then + Error("Index ", n, " not bound."); + fi; + kp := PositionSorted(cumulative_stirling, n) - 1; + if kp = 0 then + return ElementNumber(enu, n, kp); + fi; + return ElementNumber(enu, n - cumulative_stirling[kp], kp); + end; + r.NumberElement := function(enu, p) + local t; + if not IsSet(p) or Length(p) > k then + return fail; + fi; + t := NumberElement(enu, p, Length(p)); + if t = fail then + return fail; + fi; + return cumulative_stirling[Length(p)] + t; + end; + r.Length := x -> cumulative_stirling[k + 1]; + elif (Length(arg) = 2 and arg[2] = false) or (Length(arg) = 1) then + r.ElementNumber := function(enu, n) + if n > Stirling2(l, k) then + Error("Index ", n, " not bound."); + fi; + return ElementNumber(enu, n, k); + end; + r.NumberElement := function(enu, p) + return NumberElement(enu, p, k); + end; + r.Length := x -> Stirling2(l, k); + elif Length(arg) = 2 then + Error("EnumeratorOfPartitionsSet: must be true or false"); + else + Error( "usage: EnumeratorOfPartitionsSet( [, [, ] ] )" ); + fi; + + r.k := k; + return EnumeratorByFunctions(ListsFamily, r); +end); ############################################################################# ## diff --git a/lib/ctblsymm.gi b/lib/ctblsymm.gi index 74230ddc77..a15ca95f5b 100644 --- a/lib/ctblsymm.gi +++ b/lib/ctblsymm.gi @@ -1232,7 +1232,7 @@ InstallMethod( Irr, # Compute the correspondence of classes. cp:= gentbl.classparam[1]( deg ); perm:= []; - for i in ConjugacyClasses( G ) do + for i in ConjugacyClasses( cG ) do i:= List( Orbits( SubgroupNC( G, [ Representative(i) ] ), dom ), Length ); Sort( i ); 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/fitfree.gi b/lib/fitfree.gi index d68681ea93..2e549bf08f 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); @@ -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, @@ -919,10 +919,10 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs,gens; sf:=List(GeneratorsOfGroup(Image(fphom)),x->PreImagesRepresentative(fphom,x)); sg:=List(sf,x->PreImagesRepresentative(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 +939,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 +953,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; @@ -1240,11 +1240,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 +1256,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]; @@ -1325,12 +1325,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); @@ -1411,10 +1411,10 @@ local ser,hom,s,fphom,sf,sg,sp,fp,d,head,mran,nran,mpcgs,ocr,len,pcgs, sf:=List(GeneratorsOfGroup(Image(fphom)),x->PreImagesRepresentative(fphom,x)); sg:=List(sf,x->PreImagesRepresentative(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 +1429,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 +1443,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/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/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..ceac830d16 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -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; @@ -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; diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 5766951a76..86dcc4a815 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. @@ -1341,7 +1339,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 32aa8f6368..fe363a7b07 100644 --- a/lib/grpnames.gi +++ b/lib/grpnames.gi @@ -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,18 +1279,31 @@ 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; fi; + # the derived subgroup must be alternating and have index 2 G1 := DerivedSubgroup(G); - if not (IsAlternatingGroup(G1) and Index(G,G1) = 2) - # this requires deg>=4 - or not IsTrivial(Centralizer(G,G1)) - or Size(G) = 720 and IdGroup(G) <> [ 720, 763 ] - then return false; fi; + if not (IsAlternatingGroup(G1) and Index(G,G1) = 2) then + return false; + fi; + # the derived subgroup must have trivial centralizer (since degree >= 4) + if not IsTrivial(Centralizer(G,G1)) then + return false; + fi; + # one more special case: there are three groups of order 720 which satisfy + # the above (those with small group ids 763, 764, 765). So here we need + # extra work to pick the correct one: it is only one in which all elements + # have order <= 6. Conversely, the other two groups contain elements of + # order 8 or 10, but none of order 6 + if Size(G) = 720 and Order(First(G,x->Order(x)>=6)) > 6 then + return false; + fi; SetSymmetricDegree(G,AlternatingDegree(G1)); return true; end ); @@ -1396,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 ); @@ -1459,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]; @@ -1472,24 +1493,25 @@ 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) + # PSL(3, 4) / PSL(4, 2) \cong A_8 elif npes = [ [ 4, 2, 1 ], [ 3, 2, 2 ] ] then - if IdGroup(SylowSubgroup(G,2)) = [64,138] then npe := npes[1]; - elif IdGroup(SylowSubgroup(G,2)) = [64,242] then npe := npes[2]; fi; - SetParametersOfGroupViewedAsPSL(G,npe); return true; + if IsAlternatingGroup(G) then + npe := npes[1]; + else + npe := npes[2]; + fi; # 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 ); ############################################################################# @@ -1549,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 @@ -1569,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 ); ############################################################################# @@ -1635,12 +1656,24 @@ 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 - if IdGroup(G) <> [48,29] then return false; fi; - SetParametersOfGroupViewedAsGL(G,npes); return true; + # necessary condition: must have derived subgroup of index 2 (i.e., SL(2,3)) + if AbelianInvariants(G) <> [2] then return false; fi; + + # there are two groups order 48 with derived subgroup of index 2: + # - SmallGroup(48,28) is C2 . S4 = SL(2,3) . C2 + # - SmallGroup(48,29) is GL(2,3) + # These two groups are quite similar: they have + # - isomorphic centers (C2), + # - isomorphic derived subgroups (SL(2,3)), + # - same number of conjugacy classes (8), + # - same conjugacy class sizes ([ 1, 12, 8, 6, 1, 6, 8, 6 ]) + # One difference is that the conjugacy class of size 12 consists of + # 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; # other cases, in which contained PSL is simple else @@ -1659,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 ); ############################################################################# @@ -1700,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); @@ -1731,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); @@ -1782,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 @@ -1885,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 @@ -1947,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 ",":."); @@ -2021,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..c813ee5f63 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 diff --git a/lib/grpnice.gi b/lib/grpnice.gi index f72d348e81..c7ed3a5a34 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -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,18 +962,20 @@ 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); ############################################################################# @@ -979,12 +987,11 @@ InstallMethod( PreImagesRepresentative, "for PBG-Niceo", [ 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; + PushOptions( rec( Run_In_GGMBI:= true ) ); p:=PreImagesRepresentative( AsGroupGeneralMappingByImages( hom ), elm ); - RUN_IN_GGMBI:=tmp; + PopOptions(); return p; end ); diff --git a/lib/grpperm.gd b/lib/grpperm.gd index 86e2ccc7e9..50e2f16ac4 100644 --- a/lib/grpperm.gd +++ b/lib/grpperm.gd @@ -301,7 +301,7 @@ DeclareAttribute( "AllBlocks", IsPermGroup ); ## ## ## -DeclareGlobalFunction( "TransitiveGroupsAvailable" ); +BindGlobal( "TransitiveGroupsAvailable", ReturnFalse ); # dummy declarations to satisfy library references to transitive groups # library @@ -356,7 +356,7 @@ DeclareAttribute( "TransitiveIdentification", IsPermGroup ); ## ## ## -DeclareGlobalFunction( "PrimitiveGroupsAvailable" ); +BindGlobal( "PrimitiveGroupsAvailable", ReturnFalse ); ############################################################################# ## diff --git a/lib/helpbase.gi b/lib/helpbase.gi index f3cf5a8f04..15dcd0edad 100644 --- a/lib/helpbase.gi +++ b/lib/helpbase.gi @@ -738,9 +738,9 @@ end); ############################################################################# ## -#F HELP_SHOW_BOOKS( ignored... ) . . . . . . . . . . . show available books +#F HELP_SHOW_BOOKS() . . . . . . . . . . . . . . . . . show available books ## -InstallGlobalFunction(HELP_SHOW_BOOKS, function( arg ) +InstallGlobalFunction(HELP_SHOW_BOOKS, function() local books; books := [" Table of currently available help books", 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/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/mat8bit.gd b/lib/mat8bit.gd index 2e8279f9bd..abde8e342c 100644 --- a/lib/mat8bit.gd +++ b/lib/mat8bit.gd @@ -45,7 +45,7 @@ ## but is determined by the common base domain of the rows of the matrix. ## DeclareRepresentation( "Is8BitMatrixRep", - IsPositionalObjectRep and IsRowListMatrix + IsPositionalObjectRep and IsRowListMatrix and IsMatrix and IsCopyable and IsNoImmediateMethodsObject and HasNumberRows and HasNumberColumns diff --git a/lib/mat8bit.gi b/lib/mat8bit.gi index 34ad8180a9..591b28951f 100644 --- a/lib/mat8bit.gi +++ b/lib/mat8bit.gi @@ -269,7 +269,7 @@ InstallMethod( \-, "for two 8 bit matrices in same characteristic", InstallGlobalFunction(ConvertToMatrixRep, function( arg ) - local m,qs, v, q, givenq, q1, LeastCommonPower, lens; + local m,qs, v, q, givenq, q1, LeastCommonPower, lens, d; LeastCommonPower := function(qs) local p, d, x, i; @@ -389,19 +389,32 @@ InstallGlobalFunction(ConvertToMatrixRep, fi; if givenq and q1 <> q then - Error("ConvertToMatrixRep( , ): not all entries of written over "); - fi; - - # - # Now try and rewrite all the rows over this field - # this may fail if some rows are locked over a smaller field - # + # It may be possible to write the matrix over the field + # with 'q1' elements. + # We are not allowed to call 'ConvertToVectorRep( v, q1 )' + # in order to *test* whether the row 'v' lives over the desired + # field, but we may call it once we *know* that this is the case. + d:= Length( Factors( q1 ) ); + for v in m do + if d mod DegreeFFE( v ) <> 0 then + Error("ConvertToMatrixRep( , ): not all entries of written over "); + elif q1 <> ConvertToVectorRep( v, q1 ) then + return fail; + fi; + od; + q:= q1; + else + # + # Now try and rewrite all the rows over this field + # this may fail if some rows are locked over a smaller field + # - for v in m do + for v in m do if q <> ConvertToVectorRepNC(v,q) then return fail; fi; - od; + od; + fi; fi; if q <= 256 then diff --git a/lib/matobj.gi b/lib/matobj.gi index 35ae1ccbe0..c2302ec5bf 100644 --- a/lib/matobj.gi +++ b/lib/matobj.gi @@ -885,6 +885,23 @@ end ); ## otherwise it is not specified what happens. ## If the result is a vector object then it has the same representation and ## the same base domain as the given vector object(s). +##

+## v1 := Vector( Rationals, [-1,-1/2,0,1/2,1] );; Print( v1 ); +## NewVector(IsPlistVectorRep,Rationals,[ -1, -1/2, 0, 1/2, 1 ]) +## gap> v2 := Vector( [0,1,2,4,8], v1 );; Print( v2 ); +## NewVector(IsPlistVectorRep,Rationals,[ 0, 1, 2, 4, 8 ]) +## gap> Print( v1 + v2 ); +## NewVector(IsPlistVectorRep,Rationals,[ -1, 1/2, 2, 9/2, 9 ]) +## gap> Unpack( v2 - v1 ); +## [ 1, 3/2, 2, 7/2, 7 ] +## gap> Unpack( 2 * v1 ); Unpack( v1 * 4 ); Unpack( v2 / 4 ); +## [ -2, -1, 0, 1, 2 ] +## [ -4, -2, 0, 2, 4 ] +## [ 0, 1/4, 1/2, 1, 2 ] +## gap> v1 * v2; +## 19/2 +## ]]> ## ## ## <#/GAPDoc> @@ -1123,6 +1140,27 @@ InstallMethod( MultVectorRight, ## otherwise it is not specified what happens. ## If the result is a matrix object then it has the same representation and ## the same base domain as the given matrix object(s). +##

+## m1 := Matrix( Rationals, [ [3,4,5], [6,7,8] ] );; +## gap> m2 := Matrix( [ [1,0,1], [0,1,0] ], m1 );; +## gap> Print( m1 + m2, "\n", m1 - m2 ); +## NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 4, 4, 6 ], [ 6, 8, 8 ] ]) +## NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 2, 4, 4 ], [ 6, 6, 8 ] ]) +## gap> Unpack( 3 * m2 ); Unpack( m2 * 5 ); Unpack( m2 / 2 ); +## [ [ 3, 0, 3 ], [ 0, 3, 0 ] ] +## [ [ 5, 0, 5 ], [ 0, 5, 0 ] ] +## [ [ 1/2, 0, 1/2 ], [ 0, 1/2, 0 ] ] +## gap> m3 := Matrix( Integers, [ [1,1], [0,1] ] );; +## gap> m4 := Matrix( Integers, [ [3,5], [4,7] ] );; +## gap> Print( m3 * m4 ); +## NewMatrix(IsPlistMatrixRep,Integers,2,[ [ 7, 12 ], [ 4, 7 ] ]) +## gap> Unpack( m3 * m4 ); +## [ [ 7, 12 ], [ 4, 7 ] ] +## gap> Unpack( m3^6 ); Unpack( m4^-1 ); +## [ [ 1, 6 ], [ 0, 1 ] ] +## [ [ 7, -5 ], [ -4, 3 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1404,7 +1442,7 @@ InstallMethod( Characteristic, ## ## a matrix object ## -## For a vector object M, +## For a matrix object M, ## the operations for computing the additive inverse with prescribed ## mutability return a matrix object with the same ## and @@ -1476,7 +1514,14 @@ InstallMethod( ZeroSameMutability, InstallMethod( OneMutable, [ IsMatrixObj ], - M -> IdentityMatrix( NumberRows( M ), M ) ); + function( M ) + local nrows; + nrows:= NrRows( M ); + if nrows <> NrCols( M ) then + Error( " must be square (not ", nrows, " by ", NrCols( M ), ")" ); + fi; + return IdentityMatrix( nrows, M ); + end ); InstallMethod( OneSameMutability, [ IsMatrixOrMatrixObj ], diff --git a/lib/matobj1.gd b/lib/matobj1.gd index ff53201b9c..c19130890f 100644 --- a/lib/matobj1.gd +++ b/lib/matobj1.gd @@ -110,16 +110,12 @@ DeclareCategory( "IsVectorObj", IsVector and IsVecOrMatObj and IsRowVectorOrVect ## argument. ##

## m:= IdentityMat( 2, GF(2) );; -## gap> IsMatrix( m ); IsMatrixObj( m ); IsMatrixOrMatrixObj( m ); -## true -## false -## true -## gap> m:= NewIdentityMatrix( IsPlistMatrixRep, GF(2), 2 );; -## gap> IsMatrix( m ); IsMatrixObj( m ); IsMatrixOrMatrixObj( m ); -## false -## true -## true +## gap> m := [ [1,2,3,4], [6,7,8,9] ];; +## gap> [ IsMatrix( m ), IsMatrixObj( m ), IsMatrixOrMatrixObj( m ) ]; +## [ true, false, true ] +## gap> m1 := Matrix( Integers, [ [1,2,3,4], [6,7,8,9] ] );; +## gap> [ IsMatrix( m1 ), IsMatrixObj( m1 ), IsMatrixOrMatrixObj( m1 ) ]; +## [ false, true, true ] ## ]]> ## ## @@ -246,7 +242,7 @@ DeclareCategory( "IsMatrixObj", IsMatrixOrMatrixObj ); ## the i-th row of M, ## for 1 \leq i \leq NumberRows( M ). ##

-## All rows are objects in the same +## All rows are objects in the compatible ## representation. ## Several rows of a row list matrix object can be identical objects, ## and different row list matrices may share rows. @@ -256,6 +252,14 @@ DeclareCategory( "IsMatrixObj", IsMatrixOrMatrixObj ); ## Matrix objects in are not ## necessarily in , ## and then they need not obey the general rules for lists. +##

+## m1 := Matrix( Integers, [ [1,2,3,4], [6,7,8,9] ] );; +## gap> IsRowListMatrix( m1 ); +## true +## gap> Print( m1[2] ); +## NewVector(IsPlistVectorRep,Integers,[ 6, 7, 8, 9 ]) +## ]]> ## ## ## <#/GAPDoc> @@ -283,6 +287,12 @@ DeclareCategory( "IsRowListMatrix", IsMatrixObj ); ## its base domain with respect to ## , see Section ## . +##

+## v := Vector( Rationals, [ 3, 4, 7, 8 ] );; +## gap> BaseDomain( v ); +## Rationals +## ]]> ## ## ## <#/GAPDoc> @@ -292,44 +302,6 @@ DeclareAttribute( "BaseDomain", IsVecOrMatObj ); #DeclareAttribute( "BaseDomain", IsMatrixOrMatrixObj ); -############################################################################# -## -#A NumberRows( ) -#A NrRows( ) -#A NumberColumns( ) -#A NrCols( ) -## -## <#GAPDoc Label="NumberRowsNumberColumns"> -## -## NumberRows and NumberColumns -## -## -## -## -## -## -## For a matrix object M, -## and -## store the -## number of rows and columns of M, respectively. -##

-## and -## are synonyms of -## and -## , respectively. -## -## -## <#/GAPDoc> -## -DeclareAttributeKernel( "NumberRows", IsMatrixOrMatrixObj, NUMBER_ROWS ); -DeclareSynonymAttr( "NrRows", NumberRows ); -InstallTrueMethod( HasNumberRows, IsMatrixOrMatrixObj and IsPlistRep); - -DeclareAttributeKernel( "NumberColumns", IsMatrixOrMatrixObj, NUMBER_COLUMNS ); -DeclareSynonymAttr( "NrCols", NumberColumns ); -InstallTrueMethod( HasNumberColumns, IsMatrixOrMatrixObj and IsPlistRep ); - - ############################################################################# ## #A OneOfBaseDomain( ) @@ -374,6 +346,52 @@ DeclareAttribute( "ZeroOfBaseDomain", IsVecOrMatObj ); #DeclareAttribute( "ZeroOfBaseDomain", IsMatrixOrMatrixObj ); +############################################################################# +## +#A NumberRows( ) +#A NrRows( ) +#A NumberColumns( ) +#A NrCols( ) +## +## <#GAPDoc Label="NumberRowsNumberColumns"> +## +## NumberRows and NumberColumns +## +## +## +## +## +## +## For a matrix object M, +## and +## store the +## number of rows and columns of M, respectively. +##

+## and +## are synonyms of +## and +## , respectively. +##

+## m1 := Matrix( Integers, [ [1,2,3,4], [6,7,8,9] ] );; +## gap> NumberRows( m1 ); +## 2 +## gap> NrCols( m1 ); +## 4 +## ]]> +## +## +## <#/GAPDoc> +## +DeclareAttributeKernel( "NumberRows", IsMatrixOrMatrixObj, NUMBER_ROWS ); +DeclareSynonymAttr( "NrRows", NumberRows ); +InstallTrueMethod( HasNumberRows, IsMatrixOrMatrixObj and IsPlistRep); + +DeclareAttributeKernel( "NumberColumns", IsMatrixOrMatrixObj, NUMBER_COLUMNS ); +DeclareSynonymAttr( "NrCols", NumberColumns ); +InstallTrueMethod( HasNumberColumns, IsMatrixOrMatrixObj and IsPlistRep ); + + ############################################################################# ## #V ConstructingFiltersForMatrixGroupElements diff --git a/lib/matobj2.gd b/lib/matobj2.gd index e2f457d734..6ff3dee12f 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -155,24 +155,6 @@ ## -############################################################################# -## -#A Length( ) -## -## <#GAPDoc Label="Length_IsVectorObj"> -## -## -## -## -## returns the length of the vector object v, -## which is defined to be the number of entries of v. -## -## -## <#/GAPDoc> -## -DeclareAttribute( "Length", IsVectorObj ); - - ############################################################################# ## #A ConstructingFilter( ) @@ -198,6 +180,12 @@ DeclareAttribute( "Length", IsVectorObj ); ## value of v or M implies then ## mutable versions of v or M can be created, ## otherwise all vector or matrix objects with this filter are immutable. +##

+## v := Vector( Rationals, [3,4,7,8] );; +## gap> ConstructingFilter( v ); +## +## ]]> ## ## ## <#/GAPDoc> @@ -222,6 +210,14 @@ DeclareAttribute( "ConstructingFilter", IsVecOrMatObj ); ## value ## f are compatible in the sense that M can be multiplied with ## these vector objects, of fail if no such filter is known. +##

+## m1 := Matrix( Integers, [ [1,2,3,4], [6,7,8,9] ] );; +## gap> ConstructingFilter( m1 ); +## +## gap> CompatibleVectorFilter( m1 ); +## +## ]]> ## ## ## <#/GAPDoc> @@ -231,211 +227,886 @@ DeclareAttribute( "CompatibleVectorFilter", IsMatrixOrMatrixObj ); ############################################################################# ## -## List Like Operations for Vector Objects +#A Length( ) +## +## <#GAPDoc Label="Length_IsVectorObj"> +## +## +## +## +## returns the length of the vector object v, +## which is defined to be the number of entries of v. +## +## +## <#/GAPDoc> ## +DeclareAttribute( "Length", IsVectorObj ); ############################################################################# ## -#O \[\]( , ) -#O \[\]\:\=( , , ) -#O \{\}( , ) +#O Vector( , , ) +#O Vector( , ) +#O Vector( , , ) +#O Vector( , ) +#O Vector( , ) +#O Vector( , ) ## -## <#GAPDoc Label="ElementAccessVectorObj"> +## <#GAPDoc Label="Vector"> ## -## Element Access and Assignment for Vector Objects -## -## -## -## +## Vector +## +## +## +## +## ## +## a vector object ## -## For a vector object v and a positive integer i that is -## not larger than the length of v -## (see ), -## v[i] is the entry at position i. +## If a filter filt is given as the first argument then +## a vector object is returned that has +## +## value filt, is defined over the base domain R, +## and has the entries given by the list list or the vector object +## vecobj, respectively. ##

-## If v is mutable, i is as above, and obj is an object -## from the base domain of v then -## v[i]:= obj assigns obj to the -## i-th position of v. +## If a semiring R is given as the first argument then +## a vector object is returned whose +## +## value is guessed from R, again with base domain R +## and entries given by the last argument. ##

-## If list is a list of positive integers that are not larger than -## the length of v then -## v{list} returns a new mutable vector object -## in the same representation as v -## (see ) -## that contains the list[ k ]-th entry of v at -## position k. +## In the remaining cases with two arguments, +## the first argument is a list or a vector object +## that defines the entries of the result, +## and the second argument is a vector object whose +## and +## are taken for the +## result. +##

+## The variant +## Vector( vecobj, vecobj_example ) +## is supported also for the case that vecobj is a row vector +## but not a vector object. +## In this situation, the result is a row vector that is equal to +## vecobj and whose +## and +## +## are taken from the example. +##

+## If only a list list is given then both the +## and the +## are guessed from +## this list. ##

## If the global option check is set to false then -## +## ## need not perform consistency checks. ##

-## Note that the sublist assignment operation -## is left out here since it tempts the programmer to use constructions like -## v{ [ 1 .. 3 ] }:= w{ [ 4 .. 6 ] } -## which produces an unnecessary intermediate object; -## one should use instead. +## If the +## value of the result implies then the result is +## mutable if and only if the argument that determines the entries of the +## result (list, v, v1) is mutable. +##

+## In the case of a mutable result, it is not guaranteed that +## the given list of entries is copied. +##

+## Default methods for +## +## delegate to . +##

+## v1 := Vector( Integers, [3,4,7,8] );; Print( v1 ); +## NewVector(IsPlistVectorRep,Integers,[ 3, 4, 7, 8 ]) +## gap> v2 := Vector( Rationals, v1 );; Print( v2 ); +## NewVector(IsPlistVectorRep,Rationals,[ 3, 4, 7, 8 ]) +## gap> v3 := Vector( [ 11..13], v1) ;; Print( v3 ); +## NewVector(IsPlistVectorRep,Integers,[ 11, 12, 13 ]) +## gap> v0 := [6..9];; IsVector( v0 ); +## true +## gap> Print( Vector( v0, v1 ) ); +## NewVector(IsPlistVectorRep,Integers,[ 6, 7, 8, 9 ]) +## gap> v4 := Vector( [ 2, 5/2, 7/3, 3 ] );; Print( v4 ); +## NewVector(IsPlistVectorRep,Rationals,[ 2, 5/2, 7/3, 3 ]) +## gap> v5 := Vector( IsGF2VectorRep, GF(2), [ 0, 1, 2 ]*Z(2)^0 );; +## gap> Print( v5 ); +## [ 0*Z(2), Z(2)^0, 0*Z(2) ] +## gap> v6 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 ); +## +## gap> BaseDomain( v6 ); +## (Integers mod 8) +## gap> v7 := Vector( IsZmodnZVectorRep, ZmodnZ(12), v0 ); +## +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "[]", [ IsVectorObj, IsPosInt ] ); - -DeclareOperation( "[]:=", [ IsVectorObj, IsPosInt, IsObject ] ); - -DeclareOperation( "{}", [ IsVectorObj, IsList ] ); +DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsList ] ); +DeclareOperation( "Vector", [ IsSemiring, IsList ] ); +DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsVectorObj ] ); +DeclareOperation( "Vector", [ IsSemiring, IsVectorObj ] ); +DeclareOperation( "Vector", [ IsList, IsVectorObj ] ); +DeclareOperation( "Vector", [ IsVectorObj, IsVectorObj ] ); +DeclareOperation( "Vector", [ IsList ] ); ############################################################################# ## -## <#GAPDoc Label="MatObj_PositionNonZero"> +#O ZeroVector( , ) +#O ZeroVector( , ) +#O ZeroVector( , ) +#O ZeroVector( , , ) +## +## <#GAPDoc Label="VectorObj_ZeroVector"> ## -## +## ZeroVector +## +## +## +## ## -## An integer +## a vector object ## -## Returns the index of the first entry in the vector object v -## that is not zero. -## If all entries are zero, -## the function returns Length(v) + 1. +## For a semiring R and a nonnegative integer len, +## this operation returns a new vector object of length len +## over R in the representation filt containing only zeros. +## &GAP; guesses a suitable representation. +##

+## For a vector object v and a nonnegative integer len, +## this operation returns a new vector object of length len +## in the same representation as v containing only zeros. +##

+## For a matrix object M and a nonnegative integer len, +## this operation returns a new zero vector object of length +## len in the representation given by the +## value +## of M, provided that such a representation exists. +##

+## For a filter filt, a semiring R and a nonnegative integer +## len, this operation returns a new vector object of length +## len over R in the representation filt +## containing only zeros. +##

+## If the +## value of the result implies then the result is +## mutable. +##

+## Default methods for +## +## delegate to . +##

+## z1 := ZeroVector( Rationals, 4 );; Print( z1 ); +## NewVector(IsPlistVectorRep,Rationals,[ 0, 0, 0, 0 ]) +## gap> v5 := Vector( GF(5), [3,4]*Z(5) );; z5 := ZeroVector(3,v5);; Print(z5); +## [ 0*Z(5), 0*Z(5), 0*Z(5) ] +## gap> m6:=Matrix(Integers,[[1,3],[5,7]]);; z6:=ZeroVector(6,m6);; Print(z6); +## NewVector(IsPlistVectorRep,Integers,[ 0, 0, 0, 0, 0, 0 ]) +## gap> z8 := ZeroVector( IsZmodnZVectorRep, ZmodnZ(8), 4 );; Print( z8 ); +## NewVector(IsZmodnZVectorRep,Monoid( ... ),[ 0, 0, 0, 0 ]) +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "PositionNonZero", [ IsVectorObj ] ); +DeclareOperation( "ZeroVector", [ IsSemiring, IsInt ] ); +DeclareOperation( "ZeroVector", [ IsInt, IsVecOrMatObj ] ); +DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); +#DeclareOperation( "ZeroVector", [ IsInt, IsVectorObj ] ); +#DeclareOperation( "ZeroVector", [ IsInt, IsMatrixOrMatrixObj ] ); ############################################################################# ## -## <#GAPDoc Label="MatObj_PositionLastNonZero"> +#O NewVector( , , ) +#O NewZeroVector( , , ) +## +## <#GAPDoc Label="NewVector"> ## -## +## NewVector and NewZeroVector +## +## ## -## An integer ## -## Returns the index of the last entry in the vector object v -## that is not zero. -## If all entries are zero, the function returns 0. +## These two operations are constructors, and should only be used +## when or +## +## do not give the desired result. +##

+## For a filter filt, a semiring R, and a list list +## of elements that belong to R, +## returns a vector object which has +## the +## filt, +## the R, +## and the entries in list. +## The list list is guaranteed not to be changed by this operation. +##

+## If the global option check is set to false then +## need not perform consistency checks. +##

+## Similarly, returns a vector object +## of length n which has filt and R as +## and +## values, +## and contains the zero of R in each position. +##

+## The returned object is mutable if and only if filt implies +## . +##

+## v := NewVector( IsGF2VectorRep, GF(2), [1,0,1,0,1]*Z(2) ); +## +## gap> Print(v); +## [ Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0 ] +## gap> NewZeroVector( IsZmodnZVectorRep, ZmodnZ(7), 5 ); +## +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "PositionLastNonZero", [ IsVectorObj ] ); +DeclareTagBasedOperation( "NewVector", [ IsOperation, IsSemiring, IsList ] ); + +DeclareTagBasedOperation( "NewZeroVector", + [ IsOperation, IsSemiring, IsInt ] ); ############################################################################# ## -#O ListOp( [, ] ) +#O Matrix( , , , ) +#O Matrix( , , ) +#O Matrix( , , ) +#O Matrix( , ) +#O Matrix( , , ) +#O Matrix( , ) +#O Matrix( , , ) +#O Matrix( , ) +#O Matrix( , ) +#O Matrix( , ) +#O Matrix( ) ## -## <#GAPDoc Label="MatObj_ListOp"> +## <#GAPDoc Label="MatObj_Matrix"> ## -## +## Matrix +## +## +## +## +## ## -## A plain list +## a matrix object ## -## Applies the function func to each entry of the vector object -## v and returns the results as a mutable plain list. -## This allows for calling -## on vector objects. +## If a filter filt is given as the first argument +## then a matrix object is returned that has +## +## value filt, is defined over the base domain R, +## and has the entries given by the list list +## or the matrix object matobj, respectively. +## Here list can be either a list of plain lists that describe the +## entries of the rows, or a flat list of the entries in row major order, +## where ncols defines the number of columns. +##

+## If a semiring R is given as the first argument then +## a matrix object is returned whose +## +## value filt is guessed from R, +## again with base domain R and entries given by the last argument. +##

+## In those cases where the last argument is a matrix object, +## the first argument is a list or a matrix object +## that defines the entries of the result, then the +## and +## +## of the last argument are taken for the result. +##

+## Finally, if only a list list and perhaps ncols is given +## then both the +## and the +## are guessed from +## the list. +##

+## If the global option check is set to false then +## +## need not perform consistency checks. +##

+## If the +## value of the result implies then the result is +## mutable if and only if the argument that determines the entries of the +## result (list or matobj) is mutable. +##

+## In the case of a mutable result, it is guaranteed that the given list +## list is copied in the sense of , +## and if list is a nested list then it is not guaranteed +## that also the entries of list are copied. +##

+## Default methods for +## +## delegate to . +##

+## m1 := Matrix( Integers, [ [3,4,5], [6,7,8] ] );; Print( m1 ); +## NewMatrix(IsPlistMatrixRep,Integers,3,[ [ 3, 4, 5 ], [ 6, 7, 8 ] ]) +## gap> m2 := Matrix( Rationals, [10..30], 7 );; Display( m2 ); +## <3x7-matrix over Rationals: +## [[ 10 .. 16 ] +## [ 17 .. 23 ] +## [ 24 .. 30 ] +## ]> +## gap> Print( Matrix( Integers, m2 ) ); +## NewMatrix(IsPlistMatrixRep,Integers,7, +## [ [ 10 .. 16 ], [ 17 .. 23 ], [ 24 .. 30 ] ]) +## gap> m3 := Matrix( [[7,6],[4,3]], m2 );; Print(m3); +## NewMatrix(IsPlistMatrixRep,Rationals,2,[ [ 7, 6 ], [ 4, 3 ] ]) +## gap> m4 := Matrix( [-7..-2], 3, m2 );; Print(m4); +## NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ -7, -6, -5 ], [ -4, -3, -2 ] ]) +## gap> m0 := [[-1,-2],[-3,-4]];; IsMatrix(m0); +## true +## gap> Print( Matrix( m0, m1 ) ); +## NewMatrix(IsPlistMatrixRep,Integers,2,[ [ -1, -2 ], [ -3, -4 ] ]) +## gap> m5 := Matrix( [ [0,1,2], [7,8,9] ] );; Print( m5 ); +## NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 0, 1, 2 ], [ 7, 8, 9 ] ]) +## gap> Print( Matrix( [-9..-4], 3, m1 ) ); +## NewMatrix(IsPlistMatrixRep,Integers,3,[ [ -9, -8, -7 ], [ -6, -5, -4 ] ]) +## gap> m6 := Matrix( IsGF2MatrixRep, GF(2), [[1,0,1],[0,1,0]]*Z(2)^0 );; +## gap> Display( m6 ); +## 1 . 1 +## . 1 . +## gap> m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 ); +## +## gap> m8 := Matrix( IsZmodnZMatrixRep, ZmodnZ(12), m0 ); +## +## ]]> +## +## +## <#/GAPDoc> +## +DeclareOperation( "Matrix", [ IsOperation, IsSemiring, IsList, IsInt ] ); +DeclareOperation( "Matrix", [ IsOperation, IsSemiring, IsList ] ); +DeclareOperation( "Matrix", [ IsOperation, IsSemiring, IsMatrixOrMatrixObj ] ); +DeclareOperation( "Matrix", [ IsSemiring, IsList, IsInt ] ); +DeclareOperation( "Matrix", [ IsSemiring, IsList ] ); +DeclareOperation( "Matrix", [ IsSemiring, IsMatrixOrMatrixObj ] ); +DeclareOperation( "Matrix", [ IsList, IsInt, IsMatrixOrMatrixObj ] ); +DeclareOperation( "Matrix", [ IsList, IsMatrixOrMatrixObj ] ); +DeclareOperation( "Matrix", [ IsMatrixOrMatrixObj, IsMatrixOrMatrixObj ] ); +DeclareOperation( "Matrix", [ IsList, IsInt ] ); +DeclareOperation( "Matrix", [ IsList ]); + + +############################################################################# +## +#O ZeroMatrix( , , ) +#O ZeroMatrix( , , ) +#O ZeroMatrix( , , , ) +## +## <#GAPDoc Label="MatObj_ZeroMatrix"> +## +## ZeroMatrix +## +## +## +## +## a matrix object +## +## For a matrix object M and two nonnegative integers m +## and n, this operation returns a new matrix object +## with m rows and n columns +## in the same representation and over the same base domain as M +## containing only zeros. +##

+## If a semiring R and two nonnegative integers m and +## n are given, +## the representation of the result is guessed from R. +##

+## If a filter filt and a semiring R are given as the first +## and second argument, they are taken as the values of +## and +## of the result. +##

+## If the +## value of the result implies then the result is +## fully mutable. +##

+## Default methods for +## +## delegate to . +##

+## m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 );; +## gap> z7 := ZeroMatrix( 2, 2, m7 );; Print( z7 ); +## NewMatrix(IsZmodnZMatrixRep,Monoid( ... ),2, +## [ [ ZmodnZObj( 0, 8 ), ZmodnZObj( 0, 8 ) ], +## [ ZmodnZObj( 0, 8 ), ZmodnZObj( 0, 8 ) ] ]) +## gap> z23 := ZeroMatrix( Rationals, 2, 3 );; Print( z23 ); +## NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 0, 0, 0 ], [ 0, 0, 0 ] ]) +## gap> z5 := ZeroMatrix( IsGF2MatrixRep, GF(2), 2, 5 );; Display( z5 ); +## . . . . . +## . . . . . +## ]]> +## +## +## <#/GAPDoc> +## +DeclareOperation( "ZeroMatrix", [ IsInt, IsInt, IsMatrixOrMatrixObj ] ); +DeclareOperation( "ZeroMatrix", [ IsSemiring, IsInt, IsInt ] ); +DeclareOperation( "ZeroMatrix", [ IsOperation, IsSemiring, IsInt, IsInt ] ); + + +############################################################################# +## +#O IdentityMatrix( , ) +#O IdentityMatrix( , ) +#O IdentityMatrix( , , ) +## +## <#GAPDoc Label="MatObj_IdentityMatrix"> +## +## IdentityMatrix +## +## +## +## +## a matrix object +## +## For a matrix object M and a nonnegative integer n, +## this operation returns a new identity matrix object +## with n rows and columns +## in the same representation and over the same base domain as M. +##

+## If a semiring R and a nonnegative integer n is given, +## the representation of the result is guessed from R. +##

+## If a filter filt and a semiring R are given as the first +## and second argument, they are taken as the values of +## and +## of the result. +##

+## If the +## value of the result implies then the result is +## fully mutable. +##

+## Default methods for +## +## delegate to . +##

+## m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 );; +## gap> id7 := IdentityMatrix( 2, m7 );; Print( id7 ); +## NewMatrix(IsZmodnZMatrixRep,Monoid( ... ),2, +## [ [ ZmodnZObj( 1, 8 ), ZmodnZObj( 0, 8 ) ], +## [ ZmodnZObj( 0, 8 ), ZmodnZObj( 1, 8 ) ] ]) +## gap> id2 := IdentityMatrix( Rationals, 2 );; Print( id2 ); +## NewMatrix(IsPlistMatrixRep,Rationals,2,[ [ 1, 0 ], [ 0, 1 ] ]) +## gap> id3 := IdentityMatrix( IsGF2MatrixRep, GF(2), 3 );; Display( id3 ); +## 1 . . +## . 1 . +## . . 1 +## ]]> +## +## +## <#/GAPDoc> +## +DeclareOperation( "IdentityMatrix", [ IsInt, IsMatrixOrMatrixObj ] ); +DeclareOperation( "IdentityMatrix", [ IsSemiring, IsInt ] ); +DeclareOperation( "IdentityMatrix", [ IsOperation, IsSemiring, IsInt ] ); + + +############################################################################# +## +#O NewMatrix( , , , ) +#O NewMatrix( , , , ) +#O NewMatrix( , , ) +#O NewZeroMatrix( , , , ) +#O NewIdentityMatrix( , , ) +## +## <#GAPDoc Label="NewMatrix"> +## +## NewMatrix, NewZeroMatrix, NewIdentityMatrix +## +## +## +## +## +## +## +## These three operations are constructors, and should only be used +## by those implementing new material for matrix objects. +## Most users should find +## , +## or +## +## sufficient for their requirements. +##

+## For a filter filt, a semiring R, +## a positive integer ncols, and a list list, +## returns a matrix object which has +## the +## filt, +## the R, +## n columns +## (see ), +## and the entries described by list, +## which can be either a plain list of vector objects of length ncols +## or a plain list of plain lists of length ncols +## or a plain list of length a multiple of ncols containing the +## entries in row major order. +## The list list is guaranteed not to be changed by this operation. +##

+## The corresponding entries must be in or compatible with R. +## If list already contains vector objects, they are copied. +##

+## The second and third alternatives for NewMatrix have been added +## for consistency with the corresponding versions of Matrix. +## They just call the first version. +##

+## If the global option check is set to false then +## need not perform consistency checks. +##

+## Similarly, returns a zero matrix +## object with m rows and n columns +## which has filt and R as +## and +## values. +##

+## Similarly, returns an identity +## matrix object with n rows and columns +## which has filt and R as +## and +## values, +## and contains the identity element of R in the diagonal +## and the zero of R in each off-diagonal position. +##

+## The returned object is mutable if and only if filt implies +## . +##

+## m1 := NewMatrix( IsPlistMatrixRep, Integers, 3, [ [4,5,6], [7,8,9] ] );; +## gap> Display( m1 ); +## <2x3-matrix over Integers: +## [[ 4, 5, 6 ] +## [ 7, 8, 9 ] +## ]> +## gap> NewZeroMatrix( IsPlistMatrixRep, Rationals, 5, 3 ); +## <5x3-matrix over Rationals> +## gap> NewIdentityMatrix( IsGF2MatrixRep, GF(2), 4 ); +## +## ]]> +## +## +## <#/GAPDoc> +## +DeclareTagBasedOperation( "NewMatrix", + [ IsOperation, IsSemiring, IsInt, IsList] ); + +DeclareOperation( "NewMatrix", + [ IsOperation, IsSemiring, IsList, IsInt] ); + +DeclareOperation( "NewMatrix", + [ IsOperation, IsSemiring, IsList] ); + +DeclareTagBasedOperation( "NewZeroMatrix", + [ IsOperation, IsSemiring, IsInt, IsInt ] ); + +DeclareTagBasedOperation( "NewIdentityMatrix", + [ IsOperation, IsSemiring, IsInt ] ); + + +############################################################################# +## +## Operations for Vector and Matrix Objects +## + + +############################################################################# +## +#O Unpack( ) +#O Unpack( ) +## +## <#GAPDoc Label="Unpack"> +## +## Unpack +## +## +## +## A plain list +## +## Returns a new mutable plain list (see ) +## containing the entries of the vector object v or the matrix object +## M, respectively. +## In the case of a matrix object, +## the result is a plain list of plain lists. +##

+## Changing the result does not change v or M, respectively. +## The entries themselves are not copied. +##

+## m1 := Matrix( Integers, [ [1,2,3,4], [6,7,8,9] ] );; +## gap> Unpack( m1 ); +## [ [ 1, 2, 3, 4 ], [ 6, 7, 8, 9 ] ] +## ]]> +## +## +## <#/GAPDoc> +## +## Note that 'AsList' would not be suitable in the case of vector objects +## because its result would be immutable. +## +DeclareOperation( "Unpack", [ IsVecOrMatObj ] ); +#DeclareOperation( "Unpack", [ IsVectorObj ] ); +#DeclareOperation( "Unpack", [ IsMatrixOrMatrixObj ] ); + + +############################################################################# +## +#O ChangedBaseDomain( , ) +#O ChangedBaseDomain( , ) +## +## <#GAPDoc Label="ChangedBaseDomain"> +## +## ChangedBaseDomain +## +## +## +## +## For a vector object v (a matrix object M) +## and a semiring R, +## returns +## a new vector object (matrix object) +## with value R, +## value +## equal to that of v (M), +## and the same entries as v (M). +##

+## The result is mutable if and only if v (M) is mutable. +##

+## For example, one can create a vector defined over GF(4) +## from a vector defined over GF(2) with this operation. +##

+## v1 := Vector( Integers, [ 3, 5, 7, 9 ] );; +## gap> ChangedBaseDomain( v1, Rationals ); +## +## gap> m6 := Matrix( IsGF2MatrixRep, GF(2), [[1,0,1],[0,1,0]]*Z(2)^0 );; +## gap> m64 := ChangedBaseDomain( m6, GF(4) ); +## [ [ Z(2)^0, 0*Z(2), Z(2)^0 ], [ 0*Z(2), Z(2)^0, 0*Z(2) ] ] +## gap> ConstructingFilter( m64 ); +## +## ]]> +## +## +## <#/GAPDoc> +## +DeclareOperation( "ChangedBaseDomain", [ IsVecOrMatObj, IsSemiring ] ); +#DeclareOperation( "ChangedBaseDomain", [ IsVectorObj, IsSemiring ] ); +#DeclareOperation( "ChangedBaseDomain", [ IsMatrixOrMatrixObj, IsSemiring ] ); + + +############################################################################ +## +#O Randomize( [Rs, ]v ) +#O Randomize( [Rs, ]M ) +## +## <#GAPDoc Label="Randomize"> +## +## Randomize +## +## +## +## Replaces every entry in the mutable vector object v +## or matrix object M, respectively, with +## a random one from the base domain of v or M, +## respectively, and returns the argument. ##

-## If the argument func is not given, -## applies to all entries. +## If given, the random source Rs is used to compute the +## random elements. +## Note that in this case, +## a +## method must be available that takes a random source as its first +## argument and the base domain as its second argument. +## m6 := ZeroMatrix( IsGF2MatrixRep, GF(2), 2, 10 );; +## gap> Randomize( m6 ); Display( m6 ); +## +## . 1 . . 1 . 1 . . . +## . . 1 . . . 1 1 . 1 +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "ListOp", [ IsVectorObj ] ); -DeclareOperation( "ListOp", [ IsVectorObj, IsFunction ] ); +DeclareOperation( "Randomize", [ IsVectorObj and IsMutable ] ); +DeclareOperation( "Randomize", [ IsRandomSource, IsVectorObj and IsMutable ] ); +DeclareOperation( "Randomize", [ IsMatrixOrMatrixObj and IsMutable ] ); +DeclareOperation( "Randomize", [ IsRandomSource, IsMatrixOrMatrixObj and IsMutable ] ); ############################################################################# ## -#O Unpack( ) -#O Unpack( ) +## List Like Operations for Vector Objects ## -## <#GAPDoc Label="Unpack"> + + +############################################################################# +## +#O \[\]( , ) +#O \[\]\:\=( , , ) +#O \{\}( , ) +## +## <#GAPDoc Label="ElementAccessVectorObj"> ## -## Unpack -## -## +## Element Access and Assignment for Vector Objects +## +## +## +## ## -## A plain list ## -## Returns a new mutable plain list (see ) -## containing the entries of the vector object v or the matrix object -## M, respectively. -## In the case of a matrix object, -## the result is a plain list of plain lists. +## For a vector object v and a positive integer i that is +## not larger than the length of v +## (see ), +## v[i] is the entry at position i. ##

-## Changing the result does not change v or M, respectively. -## The entries themselves are not copied. +## If v is mutable, i is as above, and obj is an object +## from the base domain of v then +## v[i]:= obj assigns obj to the +## i-th position of v. +##

+## If list is a list of positive integers that are not larger than +## the length of v then +## v{list} returns a new mutable vector object +## in the same representation as v +## (see ) +## that contains the list[ k ]-th entry of v at +## position k. +##

+## If the global option check is set to false then +## +## need not perform consistency checks. +##

+## Note that the sublist assignment operation +## is left out here since it tempts the programmer to use constructions like +## v{ [ 1 .. 3 ] }:= w{ [ 4 .. 6 ] } +## which produces an unnecessary intermediate object; +## one should use instead. +##

+## v1 := Vector( Integers, [3,4,7,8] );; +## gap> v1[4]; +## 8 +## gap> v1[2] := 6;; Print( v1 ); +## NewVector(IsPlistVectorRep,Integers,[ 3, 6, 7, 8 ]) +## gap> Print( v1{[2..3]} ); +## NewVector(IsPlistVectorRep,Integers,[ 6, 7 ]) +## ]]> ## ## ## <#/GAPDoc> ## -## Note that 'AsList' would not be suitable in the case of vector objects -## because its result would be immutable. -## -DeclareOperation( "Unpack", [ IsVecOrMatObj ] ); -#DeclareOperation( "Unpack", [ IsVectorObj ] ); -#DeclareOperation( "Unpack", [ IsMatrixOrMatrixObj ] ); +DeclareOperation( "[]", [ IsVectorObj, IsPosInt ] ); + +DeclareOperation( "[]:=", [ IsVectorObj, IsPosInt, IsObject ] ); + +DeclareOperation( "{}", [ IsVectorObj, IsList ] ); ############################################################################# ## -## <#GAPDoc Label="MatObj_ConcatenationOfVectors"> +## <#GAPDoc Label="MatObj_PositionNonZero"> ## -## ConcatenationOfVectors -## -## -## -## a vector object +## ## +## An integer ## -## Returns a new mutable vector object in the representation of v1 -## or the first entry of the nonempty list vlist of vector objects, -## respectively, -## such that the entries are the concatenation of the given vector objects. +## Returns the index of the first entry in the vector object v +## that is not zero. +## If all entries are zero, +## the function returns Length(v) + 1. ##

-## (Note that -## is a function for which no methods can be installed.) +## v := Vector( Integers, [0,0,1,1,2,2,0,0,0] );; Unpack( v ); +## [ 0, 0, 1, 1, 2, 2, 0, 0, 0 ] +## gap> PositionNonZero( v ); +## 3 +## ]]> ## ## ## <#/GAPDoc> ## -DeclareGlobalFunction( "ConcatenationOfVectors" ); +DeclareOperation( "PositionNonZero", [ IsVectorObj ] ); ############################################################################# ## -## <#GAPDoc Label="MatObj_ExtractSubVector"> +## <#GAPDoc Label="MatObj_PositionLastNonZero"> ## -## +## ## -## a vector object +## An integer +## +## Returns the index of the last entry in the vector object v +## that is not zero. +## If all entries are zero, the function returns 0. +##

+## v := Vector( Integers, [0,0,1,1,2,2,0,0,0] );; Unpack( v ); +## [ 0, 0, 1, 1, 2, 2, 0, 0, 0 ] +## gap> PositionLastNonZero( v ); +## 6 +## ]]> +## +## +## <#/GAPDoc> +## +DeclareOperation( "PositionLastNonZero", [ IsVectorObj ] ); + + +############################################################################# +## +#O ListOp( [, ] ) +## +## <#GAPDoc Label="MatObj_ListOp"> +## +## ## +## A plain list ## -## Returns a new mutable vector object of the same vector representation -## as v, containing the entries of v at the positions in -## the list l. +## Applies the function func to each entry of the vector object +## v and returns the results as a mutable plain list. +## This allows for calling +## on vector objects. ##

-## This is the same as v{l}, -## the name was introduced in analogy to -## , for which no equivalent syntax using -## curly brackets is available. +## If the argument func is not given, +## applies to all entries. +##

+## v := Vector( Integers, [0,0,1,1,2,2,0,0,0] );; Unpack( v ); +## [ 0, 0, 1, 1, 2, 2, 0, 0, 0 ] +## gap> List( v, x -> x-1 ); +## [ -1, -1, 0, 0, 1, 1, -1, -1, -1 ] +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperationKernel( "ExtractSubVector", - [ IsRowVectorOrVectorObj, IsList ], EXTRACT_SUB_VECTOR ); +DeclareOperation( "ListOp", [ IsVectorObj ] ); +DeclareOperation( "ListOp", [ IsVectorObj, IsFunction ] ); ############################################################################# @@ -443,7 +1114,6 @@ DeclareOperationKernel( "ExtractSubVector", ## Arithmetical operations for vector objects ## - ############################################################################# ## #O AddVector( , [, [, , ]] ) @@ -475,6 +1145,17 @@ DeclareOperationKernel( "ExtractSubVector", ## This can be helpful if entries of src are known to be zero. ##

## If from is bigger than to, the operation does nothing. +##

+## v1 := Vector( Integers, [0,1,2,4,8] );; Print( v1 ); +## NewVector(IsPlistVectorRep,Integers,[ 0, 1, 2, 4, 8 ]) +## gap> v2 := Vector( [1,0,1,0,1], v1 );; Print( v2 ); +## NewVector(IsPlistVectorRep,Integers,[ 1, 0, 1, 0, 1 ]) +## gap> AddVector( v1, v2 ); Unpack( v1 ); +## [ 1, 1, 3, 4, 9 ] +## gap> AddVector( v1, v2, -2 ); Unpack( v1 ); +## [ -1, 1, 1, 4, 7 ] +## ]]> ## ## ## <#/GAPDoc> @@ -530,6 +1211,11 @@ DeclareOperation( "AddVector", ## This can be helpful if entries of v are known to be zero. ## If from is bigger than to, the operation does nothing. ##

+## v1 := Vector( Integers, [0,1,2,4,8] );; +## gap> MultVector( v1, 2 ); Unpack( v1 ); +## [ 0, 2, 4, 8, 16 ] +## ]]> ## ## ## <#/GAPDoc> @@ -544,7 +1230,6 @@ DeclareOperation( "MultVectorRight", DeclareOperation( "MultVectorRight", [ IsVectorObj and IsMutable, IsObject, IsInt, IsInt ] ); - # This is defined for two vectors of equal length, # it returns the standard scalar product. # (The documentation is in the section about arithm. operations.) @@ -553,97 +1238,70 @@ DeclareOperation( "ScalarProduct", [ IsVectorObj, IsVectorObj ] ); ############################################################################# ## -#O ZeroVector( , , ) -#O ZeroVector( , ) -#O ZeroVector( , ) -#O ZeroVector( , ) +## Operations for Vector Objects ## -## <#GAPDoc Label="VectorObj_ZeroVector"> + +############################################################################# +## +## <#GAPDoc Label="MatObj_ConcatenationOfVectors"> ## -## ZeroVector -## -## -## -## +## ConcatenationOfVectors +## +## ## ## a vector object +## ## -## For a filter filt, a semiring R and a nonnegative integer len, -## this operation returns a new vector object of length len over R -## in the representation filt containing only zeros. -##

-## If only R and len are given, -## then &GAP; guesses a suitable representation. -##

-## For a vector object v and a nonnegative integer len, -## this operation returns a new vector object of length len -## in the same representation as v containing only zeros. -##

-## For a matrix object M and a nonnegative integer len, -## this operation returns a new zero vector object of length -## len in the representation given by the -## value -## of M, provided that such a representation exists. +## Returns a new mutable vector object in the representation of v1 +## or the first entry of the nonempty list vlist of vector objects, +## respectively, +## such that the entries are the concatenation of the given vector objects. ##

-## If the -## value of the result implies then the result is -## mutable. +## (Note that +## is a function for which no methods can be installed.) ##

-## Default methods for -## -## delegate to . +## v1 := Vector( Integers, [1,2,3] );; +## gap> v2 := Vector( Integers, [6,7,8,9] );; +## gap> Print( ConcatenationOfVectors( v1, v2 ) ); +## NewVector(IsPlistVectorRep,Integers,[ 1, 2, 3, 6, 7, 8, 9 ]) +## gap> Print( ConcatenationOfVectors( v2, [0,1] ) ); +## NewVector(IsPlistVectorRep,Integers,[ 6, 7, 8, 9, 0, 1 ]) +## gap> Print( ConcatenationOfVectors( [ v1, [0,0,0], v2 ] ) ); +## NewVector(IsPlistVectorRep,Integers,[ 1, 2, 3, 0, 0, 0, 6, 7, 8, 9 ]) +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); -DeclareOperation( "ZeroVector", [ IsSemiring, IsInt ] ); -DeclareOperation( "ZeroVector", [ IsInt, IsVecOrMatObj ] ); -#DeclareOperation( "ZeroVector", [ IsInt, IsVectorObj ] ); -#DeclareOperation( "ZeroVector", [ IsInt, IsMatrixOrMatrixObj ] ); +DeclareGlobalFunction( "ConcatenationOfVectors" ); ############################################################################# ## -#O Vector( , , ) -#O Vector( , , ) -#O Vector( , ) -#O Vector( , ) -#O Vector( , ) -#O Vector( , ) -## -## <#GAPDoc Label="Vector"> -## -## Vector -## -## -## -## -## -## -## +## <#GAPDoc Label="MatObj_ExtractSubVector"> +## +## ## ## a vector object +## ## -## If a filter filt is given as the first argument then -## a vector object is returned that has -## -## value filt, is defined over the base domain R, -## and has the entries given by the list list or the vector object -## v, respectively. +## Returns a new mutable vector object of the same vector representation +## as v, containing the entries of v at the positions in +## the list l. ##

-## If a semiring R is given as the first argument then -## a vector object is returned whose -## -## value is guessed from R, again with base domain R -## and entries given by the last argument. +## This is the same as v{l}, +## the name was introduced in analogy to +## , for which no equivalent syntax using +## curly brackets is available. +##

+## v1 := Vector( Rationals, [-5..5] );; +## gap> v2 := ExtractSubVector( v1, [1,3,5,7,9,11] );; Print( v2 ); +## NewVector(IsPlistVectorRep,Rationals,[ -5, -3, -1, 1, 3, 5 ]) +## ]]> ##

## In the remaining cases with two arguments, ## the first argument is a list or a vector object @@ -653,17 +1311,24 @@ DeclareOperation( "ZeroVector", [ IsInt, IsVecOrMatObj ] ); ## are taken for the ## result. ##

-## If only a list list is given then both the -## and the -## are guessed from -## this list. -##

## The variant Vector( v1, v2 ) ## is supported also for the case that v2 is a row vector but not ## a vector object. ## In this situation, the result is a row vector that is equal to ## v1 and whose internal representation fits to that of v2. ##

+## If only a list list is given then both the +## and the +## are guessed from +## this list. +##

+## If a filter filt is given as the first argument then +## a vector object is returned that has +## +## value filt, is defined over the base domain R, +## and has the entries given by the list list or the vector object +## v, respectively. +##

## If the global option check is set to false then ## ## need not perform consistency checks. @@ -679,261 +1344,215 @@ DeclareOperation( "ZeroVector", [ IsInt, IsVecOrMatObj ] ); ## Default methods for ## ## delegate to . -## -## -## <#/GAPDoc> -## -DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsList ] ); -DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsVectorObj ] ); -DeclareOperation( "Vector", [ IsSemiring, IsList ] ); -DeclareOperation( "Vector", [ IsSemiring, IsVectorObj ] ); -DeclareOperation( "Vector", [ IsList, IsVectorObj ] ); -DeclareOperation( "Vector", [ IsVectorObj, IsVectorObj ] ); -DeclareOperation( "Vector", [ IsList ] ); - - -############################################################################# -## -#O NewVector( , , ) -#O NewZeroVector( , , ) -## -## <#GAPDoc Label="NewVector"> -## -## NewVector and NewZeroVector -## -## -## -## -## For a filter filt, a semiring R, and a list list -## of elements that belong to R, -## returns a vector object which has -## the -## filt, -## the R, -## and the entries in list. -## The list list is guaranteed not to be changed by this operation. -##

-## If the global option check is set to false then -## need not perform consistency checks. -##

-## Similarly, returns a vector object -## of length n which has filt and R as -## and -## values, -## and contains the zero of R in each position. ##

-## The returned object is mutable if and only if filt implies -## . +## v1 := Vector( Integers, [3,4,7,8] );; Print( v1 ); +## NewVector(IsPlistVectorRep,Integers,[ 3, 4, 7, 8 ]) +## gap> v2 := Vector( Rationals, v1 );; Print( v2 ); +## NewVector(IsPlistVectorRep,Rationals,[ 3, 4, 7, 8 ]) +## gap> v3 := Vector( [ 11..13], v1) ;; Print( v3 ); +## NewVector(IsPlistVectorRep,Integers,[ 11, 12, 13 ]) +## gap> v0 := [6..9];; IsVector( v0 ); +## true +## gap> Print( Vector( v0, v1 ) ); +## NewVector(IsPlistVectorRep,Integers,[ 6, 7, 8, 9 ]) +## gap> v4 := Vector( [ 2, 5/2, 7/3, 3 ] );; Print( v4 ); +## NewVector(IsPlistVectorRep,Rationals,[ 2, 5/2, 7/3, 3 ]) +## gap> v5 := Vector( IsGF2VectorRep, GF(2), [ 0, 1, 2 ]*Z(2)^0 );; +## gap> Print( v5 ); +## [ 0*Z(2), Z(2)^0, 0*Z(2) ] +## gap> v6 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 ); +## +## gap> BaseDomain( v6 ); +## (Integers mod 8) +## gap> v7 := Vector( IsZmodnZVectorRep, ZmodnZ(12), v0 ); +## +## ]]> ## ## ## <#/GAPDoc> ## -DeclareTagBasedOperation( "NewVector", [ IsOperation, IsSemiring, IsList ] ); - -DeclareTagBasedOperation( "NewZeroVector", - [ IsOperation, IsSemiring, IsInt ] ); +DeclareOperationKernel( "ExtractSubVector", + [ IsRowVectorOrVectorObj, IsList ], EXTRACT_SUB_VECTOR ); ############################################################################# ## -#O NewMatrix( , , , ) -#O NewZeroMatrix( , , , ) -#O NewIdentityMatrix( , , ) +#O CopySubVector( , , , ) ## -## <#GAPDoc Label="NewMatrix"> +## <#GAPDoc Label="CopySubVector"> ## -## NewMatrix, NewZeroMatrix, NewIdentityMatrix -## -## -## +## +## +## nothing ## ## -## For a filter filt, a semiring R, -## a positive integer ncols, and a list list, -## returns a matrix object which has -## the -## filt, -## the R, -## n columns -## (see ), -## and the entries described by list, -## which can be either a plain list of vector objects of length ncols -## or a plain list of plain lists of length ncols -## or a plain list of length a multiple of ncols containing the -## entries in row major order. -## The list list is guaranteed not to be changed by this operation. +## For two row vectors or vector objects src and dst, +## such that dst is mutable, +## and two lists scols and dcols of positions, +## assigns the entries +## src{ scols } +## (see ) +## to the positions dcols in dst, +## but without creating an intermediate object and thus +## –at least in special cases– +## much more efficiently. ##

-## The corresponding entries must be in or compatible with R. -## If list already contains vector objects, they are copied. +## For certain objects like compressed vectors this might be significantly +## more efficient if scols and dcols are ranges +## with increment 1. ##

## If the global option check is set to false then -## need not perform consistency checks. -##

-## Similarly, returns a zero matrix -## object with m rows and n columns -## which has filt and R as -## and -## values. -##

-## Similarly, returns an identity -## matrix object with n rows and columns -## which has filt and R as -## and -## values, -## and contains the identity element of R in the diagonal -## and the zero of R in each off-diagonal position. +## need not perform consistency checks. ##

-## The returned object is mutable if and only if filt implies -## . +## v1 := Vector( Integers, [ 2,3,5,6,8,9 ] );; +## gap> v2 := Vector( Integers, [ 9,8,6,5,3,2 ] );; +## gap> CopySubVector( v1, v2, [2..4], [3..5] ); Print( v2 ); +## NewVector(IsPlistVectorRep,Integers,[ 9, 8, 3, 5, 6, 2 ]) +## ]]> ## ## ## <#/GAPDoc> ## -DeclareTagBasedOperation( "NewMatrix", - [ IsOperation, IsSemiring, IsInt, IsList] ); - -DeclareTagBasedOperation( "NewZeroMatrix", - [ IsOperation, IsSemiring, IsInt, IsInt ] ); - -DeclareTagBasedOperation( "NewIdentityMatrix", - [ IsOperation, IsSemiring, IsInt ] ); +DeclareOperationKernel( "CopySubVector", + [ IsRowVectorOrVectorObj, IsRowVectorOrVectorObj and IsMutable, + IsList, IsList ], COPY_SUB_VECTOR ); ############################################################################# ## -#O ChangedBaseDomain( , ) -#O ChangedBaseDomain( , ) -## -## <#GAPDoc Label="ChangedBaseDomain"> -## -## ChangedBaseDomain -## -## -## -## -## For a vector object v (a matrix object M) -## and a semiring R, -## returns -## a new vector object (matrix object) -## with value R, -## value -## equal to that of v (M), -## and the same entries as v (M). -##

-## The result is mutable if and only if v (M) is mutable. -##

-## For example, one can create a vector defined over GF(4) -## from a vector defined over GF(2) with this operation. -## -## -## <#/GAPDoc> -## -DeclareOperation( "ChangedBaseDomain", [ IsVecOrMatObj, IsSemiring ] ); -#DeclareOperation( "ChangedBaseDomain", [ IsVectorObj, IsSemiring ] ); -#DeclareOperation( "ChangedBaseDomain", [ IsMatrixOrMatrixObj, IsSemiring ] ); - - -############################################################################ -## -#O Randomize( [Rs, ]v ) -#O Randomize( [Rs, ]M ) -## -## <#GAPDoc Label="Randomize"> +## <#GAPDoc Label="MatObj_WeightOfVector"> ## -## Randomize -## -## +## +## an integer ## -## Replaces every entry in the mutable vector object v -## or matrix object M, respectively, with -## a random one from the base domain of v or M, -## respectively, and returns the argument. +## returns the Hamming weight of the vector object v, +## i.e., the number of nonzero entries in v. ##

-## If given, the random source Rs is used to compute the -## random elements. -## Note that in this case, -## a -## method must be available that takes a random source as its first -## argument and the base domain as its second argument. +## v1 := Vector( Integers, [2,3,5,6,8,9] );; +## gap> v2 := Vector( Integers, [2,3,0,0,8,9] );; +## gap> v3 := ZeroVector( Integers, 6 );; +## gap> [ WeightOfVector(v1), WeightOfVector(v2), WeightOfVector(v3) ]; +## [ 6, 4, 0 ] +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "Randomize", [ IsVectorObj and IsMutable ] ); -DeclareOperation( "Randomize", [ IsRandomSource, IsVectorObj and IsMutable ] ); -DeclareOperation( "Randomize", [ IsMatrixOrMatrixObj and IsMutable ] ); -DeclareOperation( "Randomize", [ IsRandomSource, IsMatrixOrMatrixObj and IsMutable ] ); +DeclareOperation( "WeightOfVector", [ IsVectorObj ] ); ############################################################################# ## -#O CopySubVector( , , , ) -## -## <#GAPDoc Label="CopySubVector"> +## <#GAPDoc Label="MatObj_DistanceOfVectors"> ## -## -## -## nothing -## +## +## an integer ## -## For two row vectors or vector objects src and dst, -## such that dst is mutable, -## and two lists scols and dcols of positions, -## assigns the entries -## src{ scols } -## (see ) -## to the positions dcols in dst, -## but without creating an intermediate object and thus -## –at least in special cases– -## much more efficiently. -##

-## For certain objects like compressed vectors this might be significantly -## more efficient if scols and dcols are ranges -## with increment 1. +## returns the Hamming distance of the vector objects v1 and +## v2, i.e., the number of entries in which the vectors differ. +## The vectors must have equal length. ##

-## If the global option check is set to false then -## need not perform consistency checks. +## v1 := Vector( Integers, [2,3,5,6,8,9] );; +## gap> v2 := Vector( Integers, [2,3,0,0,8,9] );; +## gap> v3 := ZeroVector( Integers, 6 );; +## gap> [ DistanceOfVectors( v1, v2 ), DistanceOfVectors( v2, v3 ) ]; +## [ 2, 4 ] +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperationKernel( "CopySubVector", - [ IsRowVectorOrVectorObj, IsRowVectorOrVectorObj and IsMutable, - IsList, IsList ], COPY_SUB_VECTOR ); +DeclareOperation( "DistanceOfVectors", [ IsVectorObj, IsVectorObj ] ); ############################################################################# ## -## <#GAPDoc Label="MatObj_WeightOfVector"> +#O MatElm( , , ) . . . . . . select an entry from a matrix +#O [ , ] . . . . . . . . . . select an entry from a matrix +## +## <#GAPDoc Label="MatObj_MatElm"> ## -## -## an integer +## +## +## an entry of the matrix object +## ## -## returns the Hamming weight of the vector object v, -## i.e., the number of nonzero entries in v. +## For a matrix object M, this operation returns the entry in +## row row and column col. +##

+## Also the syntax M[ row, col ] +## is supported. +##

+## Note that this is not equivalent to +## M[ row ][ col ], +## which would first try to access M[ row ], +## and this is in general not possible. +##

+## m1 := Matrix( Rationals, [ [3,4,5], [6,7,8] ] );; +## gap> [ MatElm( m1, 2, 2 ), m1[2,3] ]; +## [ 7, 8 ] +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "WeightOfVector", [ IsVectorObj ] ); +DeclareOperationKernel( "[,]", [ IsMatrixOrMatrixObj, IS_INT, IS_INT ], ELM_MAT ); +DeclareSynonym( "MatElm", ELM_MAT ); ############################################################################# ## -## <#GAPDoc Label="MatObj_DistanceOfVectors"> +#O SetMatElm( , , , ) . . . . set an entry in a matrix +#O [ , ]:= . . . . . . . . . set an entry in a matrix +## +## <#GAPDoc Label="MatObj_SetMatElm"> ## -## -## an integer +## +## +## nothing +## ## -## returns the Hamming distance of the vector objects v1 and -## v2, i.e., the number of entries in which the vectors differ. -## The vectors must have equal length. +## For a mutable matrix object M, this operation assigns the object +## obj to the position in row row and column col, +## provided that obj is compatible with the +## value of M. +##

+## Also the syntax +## M[ row, col ]:= obj +## is supported. +##

+## Note that this is not equivalent to +## M[ row ][ col ]:= obj, +## which would first try to access M[ row ], +## and this is in general not possible. +##

+## If the global option check is set to false then +## need not perform consistency checks. +##

+## m1 := Matrix( Rationals, [ [3,4,5], [6,7,8] ] );; +## gap> SetMatElm( m1, 1, 3, 0 ); +## gap> m1[2,1] := 0;; Unpack( m1 ); +## [ [ 3, 4, 0 ], [ 0, 7, 8 ] ] +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "DistanceOfVectors", [ IsVectorObj, IsVectorObj ] ); +DeclareOperationKernel( "[,]:=", [ IsMatrixOrMatrixObj, IsInt, IsInt, IsObject ], + ASS_MAT ); +#T We want to require also 'IsMutable' for the first argument, +#T but some package may have installed methods without this requirement. +#T Note that if we declare the operation twice, once with requirement +#T 'IsMutable' and once without, each method installation will show +#T a complaint that it matches more than one declaration. +DeclareSynonym( "SetMatElm", ASS_MAT ); ############################################################################# @@ -953,6 +1572,15 @@ DeclareOperation( "DistanceOfVectors", [ IsVectorObj, IsVectorObj ] ); ## If the ## value of the result implies then the result is ## fully mutable. +##

+## m1 := Matrix( Integers, [1..20], 5 );; Unpack( m1 ); +## [ [ 1 .. 5 ], [ 6 .. 10 ], [ 11 .. 15 ], [ 16 .. 20 ] ] +## gap> m2 := ExtractSubMatrix( m1, [2,3], [2..4] );; Unpack( m2 ); +## [ [ 7 .. 9 ], [ 12 .. 14 ] ] +## gap> m3 := ExtractSubMatrix( m1, [4,1], [5,1] );; Unpack( m3 ); +## [ [ 20, 16 ], [ 5, 1 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1003,6 +1631,16 @@ DeclareOperation( "MutableCopyMatrix", [ IsMatrixOrMatrixObj ] ); ##

## If the global option check is set to false then ## need not perform consistency checks. +##

+## m1 := Matrix( Integers, [1..20], 5 );; Unpack( m1 ); +## [ [ 1 .. 5 ], [ 6 .. 10 ], [ 11 .. 15 ], [ 16 .. 20 ] ] +## gap> m0 := ZeroMatrix( Integers, 2, 9 );; +## gap> CopySubMatrix( m1, m0, [2,3], [1,2], [2..4], [3..5] ); Unpack( m0 ); +## [ [ 0, 0, 7, 8, 9, 0, 0, 0, 0 ], [ 0, 0, 12, 13, 14, 0, 0, 0, 0 ] ] +## gap> CopySubMatrix( m1, m0, [4,1], [1,2], [5,1], [7,8] ); Unpack( m0 ); +## [ [ 0, 0, 7, 8, 9, 0, 20, 16, 0 ], [ 0, 0, 12, 13, 14, 0, 5, 1, 0 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1014,172 +1652,79 @@ DeclareOperationKernel( "CopySubMatrix", #T the pre-existing operation declaration for compatibility with packages. -############################################################################# +############################################################################ ## -#O MatElm( , , ) . . . . . . select an entry from a matrix -#O [ , ] . . . . . . . . . . select an entry from a matrix +#A CompatibleVector( ) ## -## <#GAPDoc Label="MatObj_MatElm"> +## <#GAPDoc Label="CompatibleVector"> ## -## +## ## -## an entry of the matrix object +## a vector object ## ## -## For a matrix object M, this operation returns the entry in -## row row and column col. +## Called with a matrix object M with m rows, +## this operation returns a mutable zero vector object v of length +## m and in the representation given by the +## value +## of M (provided that such a representation exists). ##

-## Also the syntax M[ row, col ] -## is supported. +## The idea is that there should be an efficient way to +## form the product vM. ##

-## Note that this is not equivalent to -## M[ row ][ col ], -## which would first try to access M[ row ], -## and this is in general not possible. +## m1 := Matrix( Integers, [ [2,3], [5,6], [8,9] ] );; +## gap> v1 := CompatibleVector( m1 );; Unpack( v1 ); +## [ 0, 0, 0 ] +## gap> v1[1] := -1;; v1[3] := -1;; Unpack( v1 ); +## [ -1, 0, -1 ] +## gap> Print( v1 * m1 ); +## NewVector(IsPlistVectorRep,Integers,[ -10, -12 ]) +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperationKernel( "[,]", [ IsMatrixOrMatrixObj, IS_INT, IS_INT ], ELM_MAT ); -DeclareSynonym( "MatElm", ELM_MAT ); +DeclareOperation( "CompatibleVector", [ IsMatrixOrMatrixObj ] ); -############################################################################# +############################################################################ ## -#O SetMatElm( , , , ) . . . . set an entry in a matrix -#O [ , ]:= . . . . . . . . . set an entry in a matrix +#A RowsOfMatrix( ) ## -## <#GAPDoc Label="MatObj_SetMatElm"> +## <#GAPDoc Label="RowsOfMatrix"> ## -## -## -## nothing -## -## -## For a mutable matrix object M, this operation assigns the object -## obj to the position in row row and column col, -## provided that obj is compatible with the -## value of M. -##

-## Also the syntax -## M[ row, col ]:= obj -## is supported. -##

-## Note that this is not equivalent to -## M[ row ][ col ]:= obj, -## which would first try to access M[ row ], -## and this is in general not possible. -##

-## If the global option check is set to false then -## need not perform consistency checks. -## -## -## <#/GAPDoc> -## -DeclareOperationKernel( "[,]:=", [ IsMatrixOrMatrixObj, IsInt, IsInt, IsObject ], - ASS_MAT ); -#T We want to require also 'IsMutable' for the first argument, -#T but some package may have installed methods without this requirement. -#T Note that if we declare the operation twice, once with requirement -#T 'IsMutable' and once without, each method installation will show -#T a complaint that it matches more than one declaration. -DeclareSynonym( "SetMatElm", ASS_MAT ); - - -############################################################################# -## -#O ZeroMatrix( , , ) -#O ZeroMatrix( , , ) -#O ZeroMatrix( , , , ) +## ## -## <#GAPDoc Label="MatObj_ZeroMatrix"> -## -## ZeroMatrix -## -## -## +## a plain list ## -## a matrix object ## -## For a matrix object M and two nonnegative integers m -## and n, this operation returns a new matrix object -## with m rows and n columns -## in the same representation and over the same base domain as M -## containing only zeros. -##

-## If a semiring R and two nonnegative integers m and -## n are given, -## the representation of the result is guessed from R. -##

-## If a filter filt and a semiring R are given as the first -## and second argument, they are taken as the values of -## and -## of the result. -##

-## If the -## value of the result implies then the result is -## fully mutable. +## Called with a matrix object M, this operation +## returns a plain list of objects in the representation given by the +## value +## of M (provided that such a representation exists), +## where the i-th entry describes the i-th row of the input. ##

-## Default methods for -## -## delegate to . +## m1 := Matrix( Integers, [ [3,4,5], [7,8,9] ] );; +## gap> Print( RowsOfMatrix( m1 ) ); +## [ NewVector(IsPlistVectorRep,Integers,[ 3, 4, 5 ]), +## NewVector(IsPlistVectorRep,Integers,[ 7, 8, 9 ]) ] +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "ZeroMatrix", [ IsInt, IsInt, IsMatrixOrMatrixObj ] ); -DeclareOperation( "ZeroMatrix", [ IsSemiring, IsInt, IsInt ] ); -DeclareOperation( "ZeroMatrix", [ IsOperation, IsSemiring, IsInt, IsInt ] ); - - -############################################################################# -## -#O IdentityMatrix( , ) -#O IdentityMatrix( , ) -#O IdentityMatrix( , , ) -## -## <#GAPDoc Label="MatObj_IdentityMatrix"> -## -## IdentityMatrix -## -## -## +## This function is used for creating an isomorphic permutation group +## of a matrix group that consists of matrix objects. +## ## -## a matrix object -## -## For a matrix object M and a nonnegative integer n, -## this operation returns a new identity matrix object -## with n rows and columns -## in the same representation and over the same base domain as M. -##

-## If a semiring R and a nonnegative integer n is given, -## the representation of the result is guessed from R. -##

-## If a filter filt and a semiring R are given as the first -## and second argument, they are taken as the values of -## and -## of the result. -##

-## If the -## value of the result implies then the result is -## fully mutable. -##

-## Default methods for -## -## delegate to . -## -## -## <#/GAPDoc> +## We assume that the matrix knows how to create suitable vector objects; +## entering a template vector as the second argument is not an option +## in this situation. ## -DeclareOperation( "IdentityMatrix", [ IsInt, IsMatrixOrMatrixObj ] ); -DeclareOperation( "IdentityMatrix", [ IsSemiring, IsInt ] ); -DeclareOperation( "IdentityMatrix", [ IsOperation, IsSemiring, IsInt ] ); +DeclareAttribute( "RowsOfMatrix", IsMatrixOrMatrixObj ); ############################################################################# @@ -1247,17 +1792,17 @@ DeclareOperation( "CompanionMatrix", ############################################################################# ## -#O Matrix( , , , ) -#O Matrix( , , ) -#O Matrix( , , ) -#O Matrix( , , ) #O Matrix( , ) +#O Matrix( , , ) #O Matrix( , ) -#O Matrix( , , ) #O Matrix( , ) +#O Matrix( , , ) #O Matrix( , ) -#O Matrix( , ) #O Matrix( ) +#O Matrix( , ) +#O Matrix( , , ) +#O Matrix( , , , ) +#O Matrix( , , ) ## ## <#GAPDoc Label="MatObj_Matrix"> ## @@ -1270,8 +1815,8 @@ DeclareOperation( "CompanionMatrix", ## ## a matrix object ## -## If a filter filt is given as the first argument then -## a matrix object is returned that has +## If a semiring R is given as the first argument then +## a matrix object is returned whose ## ## value filt, is defined over the base domain R, ## and has the entries given by the list list or the matrix object @@ -1280,13 +1825,7 @@ DeclareOperation( "CompanionMatrix", ## entries of the rows, or a flat list of the entries in row major order, ## where ncols defines the number of columns. ##

-## If a semiring R is given as the first argument then -## a matrix object is returned whose -## -## value is guessed from R, again with base domain R -## and entries given by the last argument. -##

-## In those remaining cases where the last argument is a matrix object, +## In those cases where the last argument is a matrix object, ## the first argument is a list or a matrix object ## that defines (together with ncols if applicable) the entries of ## the result, and the @@ -1294,12 +1833,19 @@ DeclareOperation( "CompanionMatrix", ## of the last argument ## are taken for the result. ##

-## Finally, if only a list list and perhaps ncols is given +## If only a list list and perhaps ncols is given ## then both the ## and the ## are guessed from ## the list. ##

+## In the remaining cases a filter filt is given as the +## first argument and a matrix object is returned that has +## +## value filt, is defined over the base domain R, +## and has the entries given by the list list or the matrix object +## M, respectively. +##

## If the global option check is set to false then ## ## need not perform consistency checks. @@ -1317,6 +1863,37 @@ DeclareOperation( "CompanionMatrix", ## Default methods for ## ## delegate to . +## m1 := Matrix( Integers, [ [3,4,5], [6,7,8] ] );; Print( m1 ); +## NewMatrix(IsPlistMatrixRep,Integers,3,[ [ 3, 4, 5 ], [ 6, 7, 8 ] ]) +## gap> m2 := Matrix( Rationals, [10..30], 7 );; Display( m2 ); +## <3x7-matrix over Rationals: +## [[ 10 .. 16 ] +## [ 17 .. 23 ] +## [ 24 .. 30 ] +## ]> +gap> Print( Matrix( Integers, m2 ) ); +NewMatrix(IsPlistMatrixRep,Integers,7, +[ [ 10 .. 16 ], [ 17 .. 23 ], [ 24 .. 30 ] ]) +gap> m3 := Matrix( [[7,6],[4,3]], m2 );; Print(m3); +NewMatrix(IsPlistMatrixRep,Rationals,2,[ [ 7, 6 ], [ 4, 3 ] ]) +gap> m4 := Matrix( [-7..-2], 3, m2 );; Print(m4); +NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ -7, -6, -5 ], [ -4, -3, -2 ] ]) +gap> m0 := [[-1,-2],[-3,-4]];; IsMatrix(m0); +true +gap> Print( Matrix( m0, m1 ) ); +NewMatrix(IsPlistMatrixRep,Integers,2,[ [ -1, -2 ], [ -3, -4 ] ]) +gap> Print( Matrix( [-9..-4], 3, m1 ) ); +NewMatrix(IsPlistMatrixRep,Integers,3,[ [ -9, -8, -7 ], [ -6, -5, -4 ] ]) +gap> m5 := Matrix( [ [0,1,2], [7,8,9] ] );; Print( m5 ); +NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 0, 1, 2 ], [ 7, 8, 9 ] ]) +gap> m6 := Matrix( IsGF2MatrixRep, GF(2), [[1,0,1],[0,1,0]]*Z(2)^0 );; +gap> Display( m6 ); + 1 . 1 + . 1 . +gap> m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 ); + +## ]]> ## ## ## <#/GAPDoc> @@ -1408,7 +1985,6 @@ DeclareGlobalFunction( "DefaultMatrixRepForBaseDomain" ); ## Operations for Row List Matrix Objects ## - ############################################################################ ## #O [ ] @@ -1426,6 +2002,12 @@ DeclareGlobalFunction( "DefaultMatrixRepForBaseDomain" ); ## this operation returns the pos-th row of M. ##

## It is not specified what happens if pos is larger. +##

+## m1 := Matrix( Integers, [ [2,3], [5,6], [8,9] ] );; +## gap> Print( m1[2] ); +## NewVector(IsPlistVectorRep,Integers,[ 5, 6 ]) +## ]]> ## ## ## <#/GAPDoc> @@ -1456,6 +2038,13 @@ DeclareOperation( "[]", [ IsRowListMatrix, IsPosInt ] ); ## M. ##

## In all other situations, it is not specified what happens. +##

+## m1 := Matrix( Integers, [ [2,3], [5,6], [8,9] ] );; +## gap> v1 := ZeroVector( 2, m1 );; +## gap> m1[2] := v1;; Unpack( m1 ); +## [ [ 2, 3 ], [ 0, 0 ], [ 8, 9 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1480,6 +2069,12 @@ DeclareOperation( "[]:=", [ IsRowListMatrix, IsPosInt, IsVectorObj ] ); ## row list matrix with the same representation as M, ## whose rows are identical to the rows at the positions ## in the list poss in M. +##

+## m1 := Matrix( Integers, [ [0,1], [3,4], [6,7], [9,0] ] );; +## gap> m2 := m1{ [2..3] };; Print( m2 ); +## NewMatrix(IsPlistMatrixRep,Integers,2,[ [ 3, 4 ], [ 6, 7 ] ]) +## ]]> ## ## ## <#/GAPDoc> @@ -1508,6 +2103,13 @@ DeclareOperation( "{}", [IsRowListMatrix,IsList] ); ##

## It is not specified what happens if the resulting range of row positions ## is not dense. +##

+## m1 := Matrix( Integers, [ [1,1], [2,2], [3,3], [4,4], [5,5] ] );; +## gap> m2 := Matrix( [ [7,7], [8,8], [9,9] ], m1 );; +## gap> ## the following appears to fail at present +## gap> ## m1{ [2..4] } := m2; +## ]]> ## ## ## <#/GAPDoc> @@ -1530,6 +2132,12 @@ DeclareOperation( "{}:=", [IsRowListMatrix,IsList,IsRowListMatrix] ); ## IsBound( M[ pos ] ) returns ## true if pos is at most the number of rows of M, ## and false otherwise. +##

+## m1 := Matrix( Integers, [ [3,4,5], [7,8,9] ] );; +## gap> [ IsBound( m1[2] ), IsBound( m1[3] ) ]; +## [ true, false ] +## ]]> ## ## ## <#/GAPDoc> @@ -1552,6 +2160,12 @@ DeclareOperation( "IsBound[]", [ IsRowListMatrix, IsPosInt ] ); ## Unbind( M[ pos ] ) removes the last ## row. ## It is not specified what happens if pos has another value. +##

+## m1 := Matrix( Integers, [ [2,3], [5,6], [8,9] ] );; +## gap> Unbind( m1[3] ); Unpack( m1 ); +## [ [ 2, 3 ], [ 5, 6 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1578,6 +2192,14 @@ DeclareOperation( "Unbind[]", [ IsRowListMatrix, IsPosInt ] ); ##

## If a positive integer pos is given then v is added in ## position pos, and all later rows are shifted up by one position. +##

+## m1 := Matrix( Integers, [ [2,3], [5,6], [8,9] ] );; +## gap> Add( m1, v1 ); Unpack( m1 ); +## [ [ 2, 3 ], [ 5, 6 ], [ 8, 9 ], [ 0, 0 ] ] +## gap> Add( m1, v1, 2 ); Unpack( m1 ); +## [ [ 2, 3 ], [ 0, 0 ], [ 5, 6 ], [ 8, 9 ], [ 0, 0 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1600,243 +2222,115 @@ DeclareOperation( "Add", [ IsRowListMatrix, IsVectorObj, IsPosInt ] ); ## ## For a mutable row list matrix M, ## this operation removes the pos-th row and shifts the later rows -## down by one position. +## up by one position. ## The default for pos is the number of rows of M. ##

## If the pos-th row existed in M then it is returned, ## otherwise nothing is returned. -## -## -## <#/GAPDoc> -## -DeclareOperation( "Remove", [ IsRowListMatrix ] ); -DeclareOperation( "Remove", [ IsRowListMatrix, IsPosInt ] ); - - -############################################################################# -## -#O Append( , ) -## -## <#GAPDoc Label="RowListMatObj_Append"> -## -## -## -## nothing -## -## -## For two row list matrices M1, M2 -## such that M1 is mutable and such that the -## and -## values are equal, -## this operation appends the rows of M2 to the -## rows of M1. -## -## -## <#/GAPDoc> -## -DeclareOperation( "Append", [ IsRowListMatrix, IsRowListMatrix ] ); - - -############################################################################# -## -#O ShallowCopy( ) -## -## <#GAPDoc Label="RowListMatObj_ShallowCopy"> -## -## -## -## a matrix object -## -## -## For a row list matrix M, -## this operation returns a new mutable matrix with the same -## and -## values as M, -## which shares its rows with M. -## -## -## <#/GAPDoc> -## - - -############################################################################# -## -#O ListOp( [ ] ) -## -## <#GAPDoc Label="RowListMatObj_ListOp"> -## -## -## -## a plain list -## -## -## For a row list matrix M, -## the variant with one argument returns the plain list -## (see ) of its rows, -## and the variant with two arguments returns the plain list of values -## of these rows under the function func. -## -## -## <#/GAPDoc> -## -DeclareOperation( "ListOp", [ IsRowListMatrix ] ); -DeclareOperation( "ListOp", [ IsRowListMatrix, IsFunction ] ); - - -############################################################################# -## -## IsEmptyMatrix( ) -## -## <#GAPDoc Label="MatObj_IsEmptyMatrix"> -## -## -## A boolean -## -## Is true if the matrix object M either has zero columns -## or zero rows, and false otherwise. -## In other words, a matrix object is empty if it has no entries. -## -## -## <#/GAPDoc> -## -DeclareProperty( "IsEmptyMatrix", IsMatrixOrMatrixObj ); - - -############################################################################# -## -## TODO: -## -## Do we REALLY want to support and document the following feature? -## If yes then it is intended as permanent, -## although it contradicts the intended use of matrix objects. -## -## Is this a feature with a generic solution, -## such that the implementors of new kinds of matrix objects need not -## care about it? -## If not then it will be very annoying to be forced to support something -## which will not be used at all as long as the code is used as intended. -## (In particular, the documentation claims on the one hand that it is not -## compulsory to provide a compatible vector object representation for one's -## matrix object implementation, but the ``row access'' will force one to -## provide one.) - -############################################################################ -# In the following sense matrices behave like lists: -############################################################################ - -DeclareOperation( "[]", [IsMatrixOrMatrixObj,IsPosInt] ); # , -# This is guaranteed to return a vector object that has the property -# that changing it changes th row (?) of the matrix ! -# A matrix which is not a row-lists internally has to create an intermediate object that refers to some -# row within it to allow the old GAP syntax M[i][j] for read and write -# access to work. Note that this will never be particularly efficient -# for matrices which are not row-lists. Efficient code will have to use MatElm and -# SetMatElm instead. - -# TODO: ... resp. it will use use M[i,j] -# TODO: provide a default method which creates a proxy object for the given row -# and translates accesses to it to corresponding MatElm / SetMatElm calls; -# creating such a proxy object prints an InfoWarning; -# but for the method for plist matrices, no warning is shown, as it is efficient -# anyway - -# TODO: maybe also add GetRow(mat, i) and GetColumn(mat, i) ??? -# these return IsVectorObj objects. -# these again must be objects which are "linked" to the original matrix, as above... -# TODO: perhaps also have ExtractRow(mat, i) and ExtractColumn(mat, i) - - -############################################################################# -## -## Backwards compatibility -## -## We have to declare the operations/synonyms because otherwise -## the method installations in some packages may not work. -## We should remove them as soon as they are not used anymore. -## - -############################################################################# -## -#C IsRowVectorObj( ) -## -## Existing code which uses this name (most notably, the cvec package) -## should be supported for some time. -## -DeclareSynonym( "IsRowVectorObj", IsVectorObj ); - - -############################################################################# -## -#A DimensionsMat( ) -## -## only for backwards compatibility with existing code: -## -> [ NrRows( ), NrCols( ) ] -## -DeclareAttribute( "DimensionsMat", IsMatrixOrMatrixObj ); - - -############################################################################# -## -#A Length( ) -## -## They had been used in older versions. -## -DeclareAttribute( "Length", IsMatrixOrMatrixObj ); - - -############################################################################# -## -#O NewCompanionMatrix( , , ) -## -## This operation is intended for the installation of tag based methods for -## 'CompanionMatrix', such that 'CompanionMatrix' admits method dispatch -## based on . -## -## (Currently 'NewCompanionMatrix' is undocumented. -## Perhaps we can simply declare 'CompanionMatrix' itself as a tag based -## operation for the given requirement. -## This would work also for `DiagonalMatrix`, `RandomMatrix`, -## `ReflectionMatrix`, etc. -## We could even get rid of `NewMatrix`, `NewZeroMatrix`, -## `NewIdentityMatrix`, by declaring `Matrix`, `ZeroMatrix`, -## `IdentityMatrix` as tag based operations for the requirements in -## question, except that the ordering of the arguments for the four -## argument versions of `NewMatrix` and `Matrix` does not fit.) +##

+## m1 := Matrix( Integers, [ [1,1], [2,2], [3,3], [4,4], [5,5] ] );; +## gap> v1 := Remove( m1 );; Unpack( v1 ); +## [ 5, 5 ] +## gap> Unpack( m1 ); +## [ [ 1, 1 ], [ 2, 2 ], [ 3, 3 ], [ 4, 4 ] ] +## gap> Remove( m1, 2 );; Unpack( m1 ); +## [ [ 1, 1 ], [ 3, 3 ], [ 4, 4 ] ] +## ]]> +## +## +## <#/GAPDoc> ## -DeclareTagBasedOperation( "NewCompanionMatrix", - [ IsOperation, IsUnivariatePolynomial, IsSemiring ] ); +DeclareOperation( "Remove", [ IsRowListMatrix ] ); +DeclareOperation( "Remove", [ IsRowListMatrix, IsPosInt ] ); ############################################################################# ## -#O NewRowVector( ... ) +#O Append( , ) ## -DeclareSynonym( "NewRowVector", NewVector ); +## <#GAPDoc Label="RowListMatObj_Append"> +## +## +## +## nothing +## +## +## For two row list matrices M1, M2 +## such that M1 is mutable and such that the +## and +## values are equal, +## this operation appends the rows of M2 to the +## rows of M1. +##

+## m1 := Matrix( Integers, [ [3,4,5], [7,8,9] ] );; +## gap> m2 := Matrix( Integers, [ [1,0,1], [0,1,0] ] );; +## gap> Append( m1, m2 ); Unpack( m1 ); +## [ [ 3, 4, 5 ], [ 7, 8, 9 ], [ 1, 0, 1 ], [ 0, 1, 0 ] ] +## ]]> +## +## +## <#/GAPDoc> +## +DeclareOperation( "Append", [ IsRowListMatrix, IsRowListMatrix ] ); ############################################################################# ## -#O Randomize( ... ) +#O ShallowCopy( ) ## -## for backwards compatibility with the cvec package +## <#GAPDoc Label="RowListMatObj_ShallowCopy"> +## +## +## +## a matrix object +## +## +## For a row list matrix M, +## this operation returns a new mutable matrix with the same +## and +## values as M, +## which shares its rows with M. +## +## +## <#/GAPDoc> ## -DeclareOperation( "Randomize", [ IsVectorObj and IsMutable, IsRandomSource ] ); -DeclareOperation( "Randomize", [ IsMatrixOrMatrixObj and IsMutable, IsRandomSource ] ); ############################################################################# ## -#O [ , ] -#O [ , ]:= +#O ListOp( [ ] ) ## -DeclareOperation( "[]", [ IsMatrixOrMatrixObj, IsPosInt, IsPosInt ] ); -DeclareOperation( "[]:=", [ IsMatrixOrMatrixObj, IsPosInt, IsPosInt, IsObject ] ); +## <#GAPDoc Label="RowListMatObj_ListOp"> +## +## +## +## a plain list +## +## +## For a row list matrix M, +## the variant with one argument returns the plain list +## (see ) of its rows, +## and the variant with two arguments returns the plain list of values +## of these rows under the function func. +##

+## +## +## +## <#/GAPDoc> +## +DeclareOperation( "ListOp", [ IsRowListMatrix ] ); +DeclareOperation( "ListOp", [ IsRowListMatrix, IsFunction ] ); ############################################################################ # Elementary matrix operations ############################################################################ # + ############################################################################ ## ## <#GAPDoc Label="MultMatrixRow"> @@ -1848,12 +2342,19 @@ DeclareOperation( "[]:=", [ IsMatrixOrMatrixObj, IsPosInt, IsPosInt, IsObject ] ## ## ##

-## Multiplies the i-th row of the mutable matrix mat with the scalar -## elm from the left in-place. +## Multiplies the i-th row of the mutable matrix mat +## with the scalar elm from the left in-place. +##

+## is a synonym of . +## This was chosen because linear combinations of rows of matrices are usually +## written as v \cdot A = [v_1, ... ,v_n] \cdot A +## which multiplies scalars from the left. ##

-## is a synonym of . This was chosen -## because linear combinations of rows of matrices are usually written as -## v \cdot A = [v_1, ... ,v_n] \cdot A which multiplies scalars from the left. +## m1 := Matrix( Integers, [ [2,3], [5,6], [8,9] ] );; +## gap> MultMatrixRow( m1, 2, -10 ); Unpack( m1 ); +## [ [ 2, 3 ], [ -50, -60 ], [ 8, 9 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1890,12 +2391,20 @@ DeclareOperation( "MultMatrixRowRight", [ IsMatrixOrMatrixObj and IsMutable, IsI ## ## ##

-## Multiplies the i-th column of the mutable matrix M with the scalar -## elm from the right in-place. +## Multiplies the i-th column of the mutable matrix M +## with the scalar elm from the right in-place. +##

+## is a synonym of +## . +## This was chosen because linear combinations of columns of matrices +## are usually written as A \cdot v^T = A \cdot [v_1, ... ,v_n]^T +## which multiplies scalars from the right. ##

-## is a synonym of . This was -## chosen because linear combinations of columns of matrices are usually written as -## A \cdot v^T = A \cdot [v_1, ... ,v_n]^T which multiplies scalars from the right. +## m1 := Matrix( Integers, [ [3,4,5], [7,8,9] ] );; +## gap> MultMatrixColumn( m1, 2, -10 ); Unpack( m1 ); +## [ [ 3, -40, 5 ], [ 7, -80, 9 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1913,8 +2422,8 @@ DeclareSynonym( "MultMatrixColumn", MultMatrixColumnRight); ## ## ##

-## Multiplies the i-th column of the mutable matrix M with the scalar -## elm from the left in-place. +## Multiplies the i-th column of the mutable matrix M +## with the scalar elm from the left in-place. ## ## ## <#/GAPDoc> @@ -1932,12 +2441,20 @@ DeclareOperation( "MultMatrixColumnLeft", [ IsMatrixOrMatrixObj and IsMutable, I ## ## ##

-## Adds the product of elm with the j-th row of the mutable matrix M to its i-th -## row in-place. The j-th row is multiplied with elm from the left. +## Adds the product of elm with the j-th row of the mutable +## matrix M to its i-th row in-place. +## The j-th row is multiplied with elm from the left. ##

-## is a synonym of . This was chosen -## because linear combinations of rows of matrices are usually written as -## v \cdot A = [v_1, ... ,v_n] \cdot A which multiplies scalars from the left. +## is a synonym of . +## This was chosen because linear combinations of rows of matrices are usually +## written as v \cdot A = [v_1, ... ,v_n] \cdot A +## which multiplies scalars from the left. +##

+## m1 := Matrix( Integers, [ [1,1,1], [2,2,2], [3,3,3] ] );; +## gap> AddMatrixRows( m1, 1, 3, 10 ); Unpack( m1 ); +## [ [ 31, 31, 31 ], [ 2, 2, 2 ], [ 3, 3, 3 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1955,8 +2472,9 @@ DeclareSynonym( "AddMatrixRows", AddMatrixRowsLeft); ## ## ##

-## Adds the product of elm with the j-th row of the mutable matrix M to its i-th -## row in-place. The j-th row is multiplied with elm from the right. +## Adds the product of elm with the j-th row of the mutable +## matrix M to its i-th row in-place. +## The j-th row is multiplied with elm from the right. ## ## ## <#/GAPDoc> @@ -1974,12 +2492,21 @@ DeclareOperation( "AddMatrixRowsRight", [ IsMatrixOrMatrixObj and IsMutable, IsI ## ## ##

-## Adds the product of elm with the j-th column of the mutable matrix M to its i-th -## column in-place. The j-th column is multiplied with elm from the right. +## Adds the product of elm with the j-th column of the mutable +## matrix M to its i-th column in-place. +## The j-th column is multiplied with elm from the right. ##

-## is a synonym of . This was -## chosen because linear combinations of columns of matrices are usually written as -## A \cdot v^T = A \cdot [v_1, ... ,v_n]^T which multiplies scalars from the right. +## is a synonym of +## . +## This was chosen because linear combinations of columns of matrices are +## usually written as A \cdot v^T = A \cdot [v_1, ... ,v_n]^T +## which multiplies scalars from the right. +##

+## m1 := Matrix( Integers, [ [1,1,1], [2,2,2], [3,3,3] ] );; +## gap> AddMatrixColumns( m1, 1, 3, 10 ); Unpack( m1 ); +## [ [ 11, 1, 1 ], [ 22, 2, 2 ], [ 33, 3, 3 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -2019,6 +2546,12 @@ DeclareOperation( "AddMatrixColumnsLeft", [ IsMatrixOrMatrixObj and IsMutable, I ## the matrix M, or NrCols( M ) + 1 if the row is zero. ## If the optional argument from is given, the search starts after ## position from. +##

+## m1 := Matrix( Integers, [ [0,0,1,1,1], [1,0,0,1,1] ] );; +## gap> [ PositionNonZeroInRow( m1, 1 ), PositionNonZeroInRow( m1, 2, 2 ) ]; +## [ 3, 4 ] +## ]]> ## ## ## <#/GAPDoc> @@ -2037,6 +2570,12 @@ DeclareOperation( "PositionNonZeroInRow", [ IsMatrixOrMatrixObj, IsPosInt, IsInt ## ##

## Swaps the i-th row and j-th row of a mutable matrix M. +##

+## m1 := Matrix( Integers, [ [1,1], [2,2], [3,3], [4,4], [5,5] ] );; +## gap> SwapMatrixRows( m1, 2, 4 ); Unpack( m1 ); +## [ [ 1, 1 ], [ 4, 4 ], [ 3, 3 ], [ 2, 2 ], [ 5, 5 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -2054,6 +2593,12 @@ DeclareOperationKernel( "SwapMatrixRows", [ IsMatrixOrMatrixObj and IsMutable, I ## ##

## Swaps the i-th column and j-th column of a mutable matrix M. +##

+## m1 := Matrix( Integers, [ [1,2,3,4,5], [6,7,8,9,10] ] );; +## gap> SwapMatrixColumns( m1, 2, 4 ); Unpack( m1 ); +## [ [ 1, 4, 3, 2, 5 ], [ 6, 9, 8, 7, 10 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -2076,6 +2621,7 @@ DeclareOperationKernel( "SwapMatrixColumns", [ IsMatrixOrMatrixObj and IsMutable ## representation. ## If both of the matrices are lists-of-lists, then the operation is delegated ## row by row to . +##

## mat1 := [ [ 1, 2 ], [ 3, 4 ] ]; ## [ [ 1, 2 ], [ 3, 4 ] ] @@ -2115,13 +2661,15 @@ DeclareOperation( "AddMatrix", [ IsMatrixOrMatrixObj and IsMutable, IsMatrixOrMa ## In all of these, if the matrix mat is a lists-of-lists, then the ## operation is delegated row by row to and ## . +##

## mat1 := [ [ 1, 2 ], [ 3, 4 ] ]; ## [ [ 1, 2 ], [ 3, 4 ] ] ## gap> MultMatrixRight(mat1, -2); ## gap> mat1; ## [ [ -2, -4 ], [ -6, -8 ] ] -## gap> MultMatrix(mat1, -2); # Note that this is the same as calling MultMatrixLeft(mat1, -2) +## gap> MultMatrix(mat1, -2); +## gap> # Note that this is the same as calling MultMatrixLeft(mat1, -2) ## gap> mat1; ## [ [ 4, 8 ], [ 12, 16 ] ] ## gap> A := FreeAssociativeAlgebra(Rationals, 2); @@ -2144,3 +2692,155 @@ DeclareOperation( "AddMatrix", [ IsMatrixOrMatrixObj and IsMutable, IsMatrixOrMa DeclareOperation( "MultMatrixRight", [ IsMatrixOrMatrixObj and IsMutable, IsScalar ] ); DeclareOperation( "MultMatrixLeft", [ IsMatrixOrMatrixObj and IsMutable, IsScalar ] ); DeclareSynonym( "MultMatrix", MultMatrixLeft ); + + +############################################################################# +## +## IsEmptyMatrix( ) +## +## <#GAPDoc Label="MatObj_IsEmptyMatrix"> +## +## +## A boolean +## +## Is true if the matrix object M either has zero columns +## or zero rows, and false otherwise. +## In other words, a matrix object is empty if it has no entries. +## +## +## <#/GAPDoc> +## +DeclareProperty( "IsEmptyMatrix", IsMatrixOrMatrixObj ); + + +############################################################################# +## +## TODO: +## +## Do we REALLY want to support and document the following feature? +## If yes then it is intended as permanent, +## although it contradicts the intended use of matrix objects. +## +## Is this a feature with a generic solution, +## such that the implementors of new kinds of matrix objects need not +## care about it? +## If not then it will be very annoying to be forced to support something +## which will not be used at all as long as the code is used as intended. +## (In particular, the documentation claims on the one hand that it is not +## compulsory to provide a compatible vector object representation for one's +## matrix object implementation, but the ``row access'' will force one to +## provide one.) + +############################################################################ +# In the following sense matrices behave like lists: +############################################################################ + +DeclareOperation( "[]", [IsMatrixOrMatrixObj,IsPosInt] ); # , +# This is guaranteed to return a vector object that has the property +# that changing it changes th row (?) of the matrix ! +# A matrix which is not a row-lists internally has to create an intermediate object that refers to some +# row within it to allow the old GAP syntax M[i][j] for read and write +# access to work. Note that this will never be particularly efficient +# for matrices which are not row-lists. Efficient code will have to use MatElm and +# SetMatElm instead. + +# TODO: ... resp. it will use use M[i,j] +# TODO: provide a default method which creates a proxy object for the given row +# and translates accesses to it to corresponding MatElm / SetMatElm calls; +# creating such a proxy object prints an InfoWarning; +# but for the method for plist matrices, no warning is shown, as it is efficient +# anyway + +# TODO: maybe also add GetRow(mat, i) and GetColumn(mat, i) ??? +# these return IsVectorObj objects. +# these again must be objects which are "linked" to the original matrix, as above... +# TODO: perhaps also have ExtractRow(mat, i) and ExtractColumn(mat, i) + + +############################################################################# +## +## Backwards compatibility +## +## We have to declare the operations/synonyms because otherwise +## the method installations in some packages may not work. +## We should remove them as soon as they are not used anymore. +## + +############################################################################# +## +#C IsRowVectorObj( ) +## +## Existing code which uses this name (most notably, the cvec package) +## should be supported for some time. +## +DeclareSynonym( "IsRowVectorObj", IsVectorObj ); + + +############################################################################# +## +#A DimensionsMat( ) +## +## only for backwards compatibility with existing code: +## -> [ NrRows( ), NrCols( ) ] +## +DeclareAttribute( "DimensionsMat", IsMatrixOrMatrixObj ); + + +############################################################################# +## +#A Length( ) +## +## They had been used in older versions. +## +DeclareAttribute( "Length", IsMatrixOrMatrixObj ); + + +############################################################################# +## +#O NewCompanionMatrix( , , ) +## +## This operation is intended for the installation of tag based methods for +## 'CompanionMatrix', such that 'CompanionMatrix' admits method dispatch +## based on . +## +## (Currently 'NewCompanionMatrix' is undocumented. +## Perhaps we can simply declare 'CompanionMatrix' itself as a tag based +## operation for the given requirement. +## This would work also for `DiagonalMatrix`, `RandomMatrix`, +## `ReflectionMatrix`, etc. +## We could even get rid of `NewMatrix`, `NewZeroMatrix`, +## `NewIdentityMatrix`, by declaring `Matrix`, `ZeroMatrix`, +## `IdentityMatrix` as tag based operations for the requirements in +## question, except that the ordering of the arguments for the four +## argument versions of `NewMatrix` and `Matrix` does not fit.) +## +DeclareTagBasedOperation( "NewCompanionMatrix", + [ IsOperation, IsUnivariatePolynomial, IsSemiring ] ); + + +############################################################################# +## +#O NewRowVector( ... ) +## +DeclareSynonym( "NewRowVector", NewVector ); + + +############################################################################# +## +#O Randomize( ... ) +## +## for backwards compatibility with the cvec package +## +DeclareOperation( "Randomize", [ IsVectorObj and IsMutable, IsRandomSource ] ); +DeclareOperation( "Randomize", [ IsMatrixOrMatrixObj and IsMutable, IsRandomSource ] ); + + +############################################################################# +## +#O [ , ] +#O [ , ]:= +## +DeclareOperation( "[]", [ IsMatrixOrMatrixObj, IsPosInt, IsPosInt ] ); +DeclareOperation( "[]:=", [ IsMatrixOrMatrixObj, IsPosInt, IsPosInt, IsObject ] ); + + diff --git a/lib/matobjgeneric.gd b/lib/matobjgeneric.gd new file mode 100644 index 0000000000..d82837e91e --- /dev/null +++ b/lib/matobjgeneric.gd @@ -0,0 +1,55 @@ +############################################################################# +## +## This file is part of GAP, a system for computational discrete algebra. +## +## SPDX-License-Identifier: GPL-2.0-or-later +## +## Copyright of GAP belongs to its developers, whose names are too numerous +## to list here. Please refer to the COPYRIGHT file for details. +## + +############################################################################ +# +# Dense matrix objects backed by plain lists of plain row lists. +# + +############################################################################# +## +## <#GAPDoc Label="IsGenericMatrixRep"> +## +## +## +## +## An object obj in describes +## a matrix object (see ) whose entries are stored +## as a dense plain list of dense plain row lists. +##

+## Unlike , this representation is not a row +## list matrix, so direct row access via M[i] is not supported. +## Instead, it is intended as the general-purpose representation for +## matrix objects. +##

+## This representation supports the usual matrix operations and is often more +## efficient than . If existing code uses row +## access, it is often possible to replace this by the operations from +## Section . +##

+## Use instead if you need the rows to be +## available as vector objects in . +## +## +## <#/GAPDoc> +## +DeclareRepresentation( "IsGenericMatrixRep", + IsMatrixObj and IsPositionalObjectRep + and IsCopyable + and IsNoImmediateMethodsObject + and HasNumberRows and HasNumberColumns + and HasBaseDomain and HasOneOfBaseDomain and HasZeroOfBaseDomain, + [] ); + + +# Internal positions for IsGenericMatrixRep: +BindConstant( "GEN_MAT_REP_BASEDOMAIN_POS", 1 ); # BaseDomain +BindConstant( "GEN_MAT_REP_NCOLS_POS", 2 ); # number of columns (needed to represent 0 x m matrices) +BindConstant( "GEN_MAT_REP_ROWS_POS", 3 ); # "rows" as a plist-of-plists diff --git a/lib/matobjgeneric.gi b/lib/matobjgeneric.gi new file mode 100644 index 0000000000..c2aab52999 --- /dev/null +++ b/lib/matobjgeneric.gi @@ -0,0 +1,480 @@ +############################################################################# +## +## This file is part of GAP, a system for computational discrete algebra. +## +## SPDX-License-Identifier: GPL-2.0-or-later +## +## Copyright of GAP belongs to its developers, whose names are too numerous +## to list here. Please refer to the COPYRIGHT file for details. +## + +############################################################################ +# +# Dense matrix objects backed by plain lists of plain row lists. +# + +BindGlobal( "MakeIsGenericMatrixRep", + function( basedomain, ncols, list, check ) + local efam, fam, filter, typ, row; + efam := ElementsFamily( FamilyObj( basedomain ) ); + fam := CollectionsFamily( FamilyObj( basedomain ) ); + + # Currently there is no special handling depending on 'basedomain', + # the types are always cached in 'fam'. + if not IsBound( fam!.GenericMatrixRepTypes ) then + # initialize type cache + # TODO: make this thread safe for HPC-GAP + filter := IsGenericMatrixRep; + if CanEasilyCompareElementsFamily( efam ) then + filter := filter and CanEasilyCompareElements; + fi; + fam!.GenericMatrixRepTypes := [ + NewType( fam, filter ), + NewType( fam, filter and IsMutable ), + ]; + fi; + if IsMutable( list ) then + typ := fam!.GenericMatrixRepTypes[2]; + else + typ := fam!.GenericMatrixRepTypes[1]; + fi; + + if check and ValueOption( "check" ) <> false then + Assert( 0, IsPlistRep( list ) ); + for row in list do + if not IsPlistRep( row ) then + Error( "the entries of must be plain lists" ); + elif Length( row ) <> ncols then + Error( "the entries of must have length " ); + elif not IsSubset( basedomain, row ) then + Error( "the elements in must lie in " ); + fi; + od; + fi; + + return Objectify( typ, [ basedomain, ncols, list ] ); + end ); + + +InstallTagBasedMethod( NewMatrix, + IsGenericMatrixRep, + function( filter, basedomain, ncols, list ) + local nd, rows, i, row; + + if Length( list ) > 0 and not IsVectorObj( list[1] ) then + nd := NestingDepthA( list ); + if nd < 2 or nd mod 2 = 1 then + if Length( list ) mod ncols <> 0 then + Error( "NewMatrix: Length of is not a multiple of " ); + fi; + list := List( [ 0, ncols .. Length( list ) - ncols ], + i -> list{ [ i + 1 .. i + ncols ] } ); + fi; + fi; + + rows := EmptyPlist( Length( list ) ); + for i in [ 1 .. Length( list ) ] do + row := list[i]; + if IsVectorObj( row ) then + rows[i] := Unpack( row ); + else + rows[i] := PlainListCopy( row ); + fi; + od; + return MakeIsGenericMatrixRep( basedomain, ncols, rows, true ); + end ); + + +InstallTagBasedMethod( NewZeroMatrix, + IsGenericMatrixRep, + function( filter, basedomain, rows, cols ) + local list, row, i, z; + list := EmptyPlist( rows ); + z := Zero( basedomain ); + for i in [ 1 .. rows ] do + row := ListWithIdenticalEntries( cols, z ); + list[i] := row; + od; + return MakeIsGenericMatrixRep( basedomain, cols, list, false ); + end ); + + +InstallMethod( ConstructingFilter, + [ "IsGenericMatrixRep" ], + M -> IsGenericMatrixRep ); + +InstallMethod( CompatibleVectorFilter, + [ "IsGenericMatrixRep" ], + M -> IsPlistVectorRep ); + + +InstallMethod( BaseDomain, + [ "IsGenericMatrixRep" ], + M -> M![GEN_MAT_REP_BASEDOMAIN_POS] ); + +InstallMethod( NumberRows, + [ "IsGenericMatrixRep" ], + M -> Length( M![GEN_MAT_REP_ROWS_POS] ) ); + +InstallMethod( NumberColumns, + [ "IsGenericMatrixRep" ], + M -> M![GEN_MAT_REP_NCOLS_POS] ); + +InstallMethod( \[\], + [ "IsGenericMatrixRep", "IsPosInt" ], + function( M, pos ) + ErrorNoReturn( "row access unsupported; use M[i,j] or RowsOfMatrix(M)" ); + end ); + +InstallMethod( MatElm, + [ "IsGenericMatrixRep", "IsPosInt", "IsPosInt" ], + { M, row, col } -> M![GEN_MAT_REP_ROWS_POS][row,col] ); + +InstallMethod( SetMatElm, + [ "IsGenericMatrixRep and IsMutable", "IsPosInt", "IsPosInt", "IsObject" ], + function( M, row, col, val ) + if ValueOption( "check" ) <> false then + if not val in BaseDomain( M ) then + Error( " must lie in the base domain of " ); + elif not row in [ 1 .. NrRows( M ) ] then + Error( " is out of bounds" ); + elif not col in [ 1 .. NrCols( M ) ] then + Error( " is out of bounds" ); + fi; + fi; + M![GEN_MAT_REP_ROWS_POS][row,col] := val; + end ); + + +InstallMethod( Unpack, + [ "IsGenericMatrixRep" ], + M -> List( M![GEN_MAT_REP_ROWS_POS], ShallowCopy ) ); + +InstallMethod( ShallowCopy, + [ "IsGenericMatrixRep" ], + M -> MakeIsGenericMatrixRep( BaseDomain(M), NrCols(M), + List( M![GEN_MAT_REP_ROWS_POS], ShallowCopy ), false ) ); + +InstallMethod( MutableCopyMatrix, + [ "IsGenericMatrixRep" ], + M -> MakeIsGenericMatrixRep( BaseDomain(M), NrCols(M), + List( M![GEN_MAT_REP_ROWS_POS], ShallowCopy ), false ) ); + +InstallMethod( ExtractSubMatrix, + [ "IsGenericMatrixRep", "IsList", "IsList" ], + function( M, rowspos, colspos ) + local list; + list := M![GEN_MAT_REP_ROWS_POS]{ rowspos }{ colspos }; + return MakeIsGenericMatrixRep( BaseDomain(M), Length( colspos ), list, false ); + end ); + +InstallMethod( CopySubMatrix, + [ "IsGenericMatrixRep", "IsGenericMatrixRep and IsMutable", + "IsList", "IsList", "IsList", "IsList" ], + function( M, N, srcrows, dstrows, srccols, dstcols ) + if ValueOption( "check" ) <> false and + not IsIdenticalObj( BaseDomain(M), BaseDomain(N) ) then + Error( " and are not compatible" ); + fi; + N![GEN_MAT_REP_ROWS_POS]{dstrows}{dstcols} := M![GEN_MAT_REP_ROWS_POS]{srcrows}{srccols}; + end ); + +InstallMethod( TransposedMatMutable, + [ "IsGenericMatrixRep" ], + function( M ) + local list; + list := TransposedMatMutable(M![GEN_MAT_REP_ROWS_POS]); + return MakeIsGenericMatrixRep( BaseDomain(M), NrRows(M), list, false ); + end ); + +InstallMethod( \+, + [ "IsGenericMatrixRep", "IsGenericMatrixRep" ], + function( a, b ) + if ValueOption( "check" ) <> false and + ( not IsIdenticalObj( BaseDomain( a ), BaseDomain( b ) ) or + NrRows( a ) <> NrRows( b ) or + NrCols( a ) <> NrCols( b ) ) then + Error( " and are not compatible" ); + fi; + return MakeIsGenericMatrixRep( BaseDomain( a ), NrCols( a ), + a![GEN_MAT_REP_ROWS_POS] + b![GEN_MAT_REP_ROWS_POS], false ); + end ); + +InstallMethod( \-, + [ "IsGenericMatrixRep", "IsGenericMatrixRep" ], + function( a, b ) + if ValueOption( "check" ) <> false and + ( not IsIdenticalObj( BaseDomain( a ), BaseDomain( b ) ) or + NrRows( a ) <> NrRows( b ) or + NrCols( a ) <> NrCols( b ) ) then + Error( " and are not compatible" ); + fi; + return MakeIsGenericMatrixRep( BaseDomain( a ), NrCols( a ), + a![GEN_MAT_REP_ROWS_POS] - b![GEN_MAT_REP_ROWS_POS], false ); + end ); + +InstallMethod( AdditiveInverseMutable, + [ "IsGenericMatrixRep" ], + M -> MakeIsGenericMatrixRep( BaseDomain( M ), NrCols( M ), + AdditiveInverseMutable( M![GEN_MAT_REP_ROWS_POS] ), false ) ); + +InstallMethod( ZeroMutable, + [ "IsGenericMatrixRep" ], + function( M ) + local z; + z := MakeIsGenericMatrixRep( BaseDomain( M ), NrCols( M ), + ZeroMutable( M![GEN_MAT_REP_ROWS_POS] ), false ); + return z; + end ); + +InstallMethod( InverseMutable, + [ "IsGenericMatrixRep" ], + function( M ) + local bd, rows; + + bd := BaseDomain( M ); + if NrRows( M ) <> NrCols( M ) then + ErrorNoReturn( "InverseMutable: matrix must be square" ); + elif NrRows( M ) = 0 then + rows := []; + elif IsFinite( bd ) and IsField( bd ) then + rows := INV_MAT_DEFAULT_MUTABLE( M![GEN_MAT_REP_ROWS_POS] ); + else + rows := INV_MATRIX_MUTABLE( M![GEN_MAT_REP_ROWS_POS] ); + fi; + if rows = fail then + return fail; + fi; + return MakeIsGenericMatrixRep( bd, NrCols( M ), rows, false ); + end ); + +InstallMethod( \*, + [ "IsGenericMatrixRep", "IsGenericMatrixRep" ], + function( a, b ) + local rowsA, colsA, rowsB, colsB, bd, list, i; + + rowsA := NumberRows( a ); + colsA := NumberColumns( a ); + rowsB := NumberRows( b ); + colsB := NumberColumns( b ); + bd := BaseDomain( a ); + + if ValueOption( "check" ) <> false then + if colsA <> rowsB then + ErrorNoReturn( "\\*: Matrices do not fit together" ); + elif not IsIdenticalObj( bd, BaseDomain( b ) ) then + ErrorNoReturn( "\\*: Matrices not over same base domain" ); + fi; + fi; + + if rowsA = 0 or colsB = 0 then + list := []; + elif colsA = 0 then # colsA = rowsB + list := EmptyPlist( rowsA ); + for i in [ 1 .. rowsA ] do + list[i] := ListWithIdenticalEntries( colsB, Zero( bd ) ); + od; + else + list := a![GEN_MAT_REP_ROWS_POS] * b![GEN_MAT_REP_ROWS_POS]; + fi; + return MakeIsGenericMatrixRep( bd, colsB, list, false ); + end ); + +InstallOtherMethod( \*, + [ "IsGenericMatrixRep", "IsRowVectorOrVectorObj" ], + {} -> RankFilter(IsPlistVectorRep), # rank above method for [IsScalar, IsPlistVectorRep] + function( M, v ) + local rows, cols, bd, res; + + rows := NumberRows( M ); + cols := NumberColumns( M ); + bd := BaseDomain( M ); + + if ValueOption( "check" ) <> false then + if cols <> Length( v ) then + Error( " and are not compatible" ); + elif not IsIdenticalObj( bd, BaseDomain( v ) ) then + Error( " and are not compatible" ); + fi; + fi; + + # special case for empty matrices + if rows = 0 or cols = 0 then + return ZeroVector( rows, v ); + fi; + + # "unpack" cheaply and then delegate to kernel implementation + if IsPlistVectorRep(v) then + res := v![ELSPOS]; + elif IsList(v) then + res := v; + else + res := Unpack(v); + fi; + res := M![GEN_MAT_REP_ROWS_POS] * res; + return Vector( res, v ); + end ); + +InstallOtherMethod( \*, + [ "IsRowVectorOrVectorObj", "IsGenericMatrixRep" ], + {} -> RankFilter(IsPlistVectorRep), # rank above method for [IsPlistVectorRep, IsScalar] + function( v, M ) + local rows, cols, bd, res; + + rows := NumberRows( M ); + cols := NumberColumns( M ); + bd := BaseDomain( M ); + + if ValueOption( "check" ) <> false then + if Length( v ) <> rows then + Error( " and are not compatible" ); + elif not IsIdenticalObj( BaseDomain( v ), bd ) then + Error( " and are not compatible" ); + fi; + fi; + + # special case for empty matrices + if rows = 0 or cols = 0 then + return ZeroVector( cols, v ); + fi; + + # "unpack" cheaply and then delegate to kernel implementation + if IsPlistVectorRep(v) then + res := v![ELSPOS]; + elif IsList(v) then + res := v; + else + res := Unpack(v); + fi; + res := res * M![GEN_MAT_REP_ROWS_POS]; + return Vector( res, v ); + end ); + +InstallMethod( ChangedBaseDomain, + [ "IsGenericMatrixRep", "IsRing" ], + function( M, r ) + local A; + A := NewMatrix( IsGenericMatrixRep, r, NrCols(M), M![GEN_MAT_REP_ROWS_POS] ); + if not IsMutable( M ) then + MakeImmutable(A); + fi; + return A; + end ); + + +InstallMethod( MultMatrixRowLeft, + [ "IsGenericMatrixRep and IsMutable", "IsInt", "IsObject" ], + function( mat, row, scalar ) + MultMatrixRowLeft(mat![GEN_MAT_REP_ROWS_POS], row, scalar); + end ); + +InstallMethod( MultMatrixRowRight, + [ "IsGenericMatrixRep and IsMutable", "IsInt", "IsObject" ], + function( mat, row, scalar ) + MultMatrixRowRight(mat![GEN_MAT_REP_ROWS_POS], row, scalar); + end ); + +InstallMethod( AddMatrixRowsLeft, + [ "IsGenericMatrixRep and IsMutable", "IsInt", "IsInt", "IsObject" ], + function( mat, row1, row2, scalar ) + AddMatrixRowsLeft( mat![GEN_MAT_REP_ROWS_POS], row1, row2, scalar ); + end ); + +InstallMethod( AddMatrixRowsRight, + [ "IsGenericMatrixRep and IsMutable", "IsInt", "IsInt", "IsObject" ], + function( mat, row1, row2, scalar ) + AddMatrixRowsRight( mat![GEN_MAT_REP_ROWS_POS], row1, row2, scalar ); + end ); + +InstallMethod( PositionNonZeroInRow, + [ "IsGenericMatrixRep", "IsPosInt" ], + function( mat, row ) + return PositionNonZero( mat![GEN_MAT_REP_ROWS_POS][row] ); + end ); + +InstallMethod( PositionNonZeroInRow, + [ "IsGenericMatrixRep", "IsPosInt", "IsInt" ], + function( mat, row, from ) + return PositionNonZero( mat![GEN_MAT_REP_ROWS_POS][row], from ); + end ); + +InstallMethod( SwapMatrixRows, + [ "IsGenericMatrixRep and IsMutable", "IsInt", "IsInt" ], + function( mat, row1, row2 ) + SwapMatrixRows(mat![GEN_MAT_REP_ROWS_POS], row1, row2); + end ); + +InstallMethod( SwapMatrixColumns, + [ "IsGenericMatrixRep and IsMutable", "IsInt", "IsInt" ], + function( mat, col1, col2 ) + SwapMatrixColumns(mat![GEN_MAT_REP_ROWS_POS], col1, col2); + end ); + + +InstallMethod( PostMakeImmutable, + [ "IsGenericMatrixRep" ], + function( M ) + MakeImmutable( M![GEN_MAT_REP_ROWS_POS] ); + end ); + + +InstallMethod( ViewObj, [ "IsGenericMatrixRep" ], + function( M ) + Print( "<" ); + if not IsMutable( M ) then + Print( "immutable " ); + fi; + Print( NrRows(M), "x", NrCols(M), + "-matrix over ", BaseDomain(M), ">" ); + end ); + +InstallMethod( PrintObj, [ "IsGenericMatrixRep" ], + function( M ) + Print( "NewMatrix(IsGenericMatrixRep" ); + if IsFinite( BaseDomain(M) ) and IsField( BaseDomain(M) ) then + Print( ",GF(", Size( BaseDomain(M) ), ")," ); + else + Print( ",", String( BaseDomain(M) ), "," ); + fi; + Print( NumberColumns( M ), ",", Unpack( M ), ")" ); + end ); + +InstallMethod( Display, [ "IsGenericMatrixRep" ], + function( M ) + local i; + Print( "<" ); + if not IsMutable( M ) then + Print( "immutable " ); + fi; + Print( NrRows(M), "x", NrCols(M), + "-matrix over ", BaseDomain(M), ":\n" ); + for i in [ 1 .. NrRows(M) ] do + if i = 1 then + Print( "[" ); + else + Print( " " ); + fi; + Print( M![GEN_MAT_REP_ROWS_POS][i], "\n" ); + od; + Print( "]>\n" ); + end ); + +InstallMethod( String, [ "IsGenericMatrixRep" ], + function( M ) + local st; + st := "NewMatrix(IsGenericMatrixRep"; + Add( st, ',' ); + if IsFinite( BaseDomain(M) ) and IsField( BaseDomain(M) ) then + Append( st, "GF(" ); + Append( st, String( Size( BaseDomain(M) ) ) ); + Append( st, ")," ); + else + Append( st, String( BaseDomain(M) ) ); + Append( st, "," ); + fi; + Append( st, String( NumberColumns( M ) ) ); + Add( st, ',' ); + Append( st, String( Unpack( M ) ) ); + Add( st, ')' ); + return st; + 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/matobjplist.gd b/lib/matobjplist.gd index 087d5b0330..93bf879dd1 100644 --- a/lib/matobjplist.gd +++ b/lib/matobjplist.gd @@ -71,6 +71,16 @@ DeclareRepresentation( "IsPlistVectorRep", ## a matrix object (see ) that behaves similar to ## a list of its rows, in the sense of . ##

+## In particular, the rows can be accessed via M[i], +## and they are vector objects in . +## This representation is useful if one wants to work explicitly with +## such row objects. +##

+## For most purposes, is the better choice. +## Unlike , it does not support direct row +## access, but it is intended as the general-purpose representation for +## matrix objects. +##

## implies , ## thus matrix objects in this representation can be mutable. ## @@ -126,4 +136,3 @@ BindConstant( "ELSPOS", 2 ); # Two filters to speed up some methods: DeclareFilter( "IsIntVector" ); DeclareFilter( "IsFFEVector" ); - diff --git a/lib/matobjplist.gi b/lib/matobjplist.gi index 69a5106d54..138d6ebfc0 100644 --- a/lib/matobjplist.gi +++ b/lib/matobjplist.gi @@ -34,60 +34,50 @@ ## BindGlobal( "MakeIsPlistVectorRep", function( basedomain, list, check ) - local fam, types, typ; - fam := FamilyObj(basedomain); - #types := _PlistVectorRepTypeCache(basedomain); - - # special case: integers - if IsIntegers(basedomain) then - if not IsBound(basedomain!.PlistVectorRepTypes) then - # initialize type cache - # TODO: make this thread safe for HPC-GAP - basedomain!.PlistVectorRepTypes := [ - NewType(fam, IsPlistVectorRep and IsIntVector and CanEasilyCompareElements), - NewType(fam, IsPlistVectorRep and IsIntVector and CanEasilyCompareElements and IsMutable), - ]; - fi; - types := basedomain!.PlistVectorRepTypes; - elif IsFFECollection(basedomain) then - if not IsBound(basedomain!.PlistVectorRepTypes) then - # initialize type cache - # TODO: make this thread safe for HPC-GAP - basedomain!.PlistVectorRepTypes := [ - NewType(fam, IsPlistVectorRep and IsFFEVector and CanEasilyCompareElements), - NewType(fam, IsPlistVectorRep and IsFFEVector and CanEasilyCompareElements and IsMutable), - ]; - fi; - types := basedomain!.PlistVectorRepTypes; + local efam, fam, filter, types, typ; + + efam := ElementsFamily( FamilyObj( basedomain ) ); + fam := FamilyObj( basedomain ); + + # we store the types in the base domain if the filter carries + # information specific to it + if IsBound( basedomain!.PlistVectorRepTypes ) then + types := basedomain!.PlistVectorRepTypes; + elif IsBound( fam!.PlistVectorRepTypes ) and not IsIntegers(basedomain) then + types := fam!.PlistVectorRepTypes; else - if not IsBound(fam!.PlistVectorRepTypes) then - # initialize type cache - # TODO: make this thread safe for HPC-GAP - fam!.PlistVectorRepTypes := [ - NewType(fam, IsPlistVectorRep), - NewType(fam, IsPlistVectorRep and IsMutable), - ]; - fam!.PlistVectorRepTypesEasyCompare := [ - NewType(fam, IsPlistVectorRep and CanEasilyCompareElements), - NewType(fam, IsPlistVectorRep and CanEasilyCompareElements and IsMutable), - ]; - fi; - if HasCanEasilyCompareElements(Representative(basedomain)) and - CanEasilyCompareElements(Representative(basedomain)) then - types := fam!.PlistVectorRepTypesEasyCompare; - else - types := fam!.PlistVectorRepTypes; - fi; + # initialize type cache + # TODO: make this thread safe for HPC-GAP + filter := IsPlistVectorRep; + if CanEasilyCompareElementsFamily( efam ) then + filter := filter and CanEasilyCompareElements; + fi; + if IsIntegers(basedomain) then + filter := filter and IsIntVector; + elif IsFFECollection(basedomain) then + filter := filter and IsFFEVector; + fi; + types := [ + NewType( fam, filter ), + NewType( fam, filter and IsMutable ), + ]; + if IsIntegers(basedomain) then + basedomain!.PlistVectorRepTypes := types; + else + fam!.PlistVectorRepTypes := types; + fi; fi; - if IsMutable(list) then - typ := types[2]; + if IsMutable( list ) then + typ := types[2]; else - typ := types[1]; + typ := types[1]; fi; if check and ValueOption( "check" ) <> false then if not IsSubset( basedomain, list ) then Error( "the elements in must lie in " ); + elif not IsPlistRep( list ) then + Error( " must be in 'IsPlistRep'" ); fi; fi; @@ -120,33 +110,29 @@ BindGlobal( "MakeIsPlistVectorRep", ## BindGlobal( "MakeIsPlistMatrixRep", function( basedomain, emptyvector, ncols, list, check ) - local fam, types, typ, row; - fam:= CollectionsFamily( FamilyObj( basedomain ) ); + local efam, fam, filter, typ, row; + + efam := ElementsFamily( FamilyObj( basedomain ) ); + fam := CollectionsFamily( FamilyObj( basedomain ) ); # Currently there is no special handling depending on 'basedomain', # the types are always cached in 'fam'. if not IsBound( fam!.PlistMatrixRepTypes ) then # initialize type cache # TODO: make this thread safe for HPC-GAP - fam!.PlistMatrixRepTypes:= [ - NewType( fam, IsPlistMatrixRep ), - NewType( fam, IsPlistMatrixRep and IsMutable ), - ]; - fam!.PlistMatrixRepTypesEasyCompare:= [ - NewType( fam, IsPlistMatrixRep and CanEasilyCompareElements ), - NewType( fam, IsPlistMatrixRep and CanEasilyCompareElements and IsMutable ), + filter := IsPlistMatrixRep; + if CanEasilyCompareElementsFamily( efam ) then + filter := filter and CanEasilyCompareElements; + fi; + fam!.PlistMatrixRepTypes := [ + NewType( fam, filter ), + NewType( fam, filter and IsMutable ), ]; fi; - if HasCanEasilyCompareElements( Representative( basedomain ) ) and - CanEasilyCompareElements( Representative( basedomain ) ) then - types:= fam!.PlistMatrixRepTypesEasyCompare; - else - types:= fam!.PlistMatrixRepTypes; - fi; if IsMutable( list ) then - typ:= types[2]; + typ := fam!.PlistMatrixRepTypes[2]; else - typ:= types[1]; + typ := fam!.PlistMatrixRepTypes[1]; fi; if check and ValueOption( "check" ) <> false then @@ -158,10 +144,10 @@ BindGlobal( "MakeIsPlistMatrixRep", for row in list do if not IsPlistVectorRep( row ) then Error( "the entries of must be in 'IsPlistVectorRep'" ); - elif not IsIdenticalObj( basedomain, row![BDPOS] ) then - Error( "the entries of must have the given base domain" ); elif Length( row![ELSPOS] ) <> ncols then Error( "the entries of must have length " ); + elif not IsIdenticalObj( basedomain, row![BDPOS] ) then + Error( "the entries of must have the given base domain" ); fi; od; fi; @@ -177,7 +163,7 @@ BindGlobal( "MakeIsPlistMatrixRep", InstallTagBasedMethod( NewVector, IsPlistVectorRep, function( filter, basedomain, list ) - return MakeIsPlistVectorRep(basedomain, ShallowCopy(list), true); + return MakeIsPlistVectorRep(basedomain, PlainListCopy( list ), true); end ); InstallTagBasedMethod( NewZeroVector, @@ -188,6 +174,17 @@ InstallTagBasedMethod( NewZeroVector, return MakeIsPlistVectorRep(basedomain, list, false); end ); +# these two methods align NewMatrix with Matrix +InstallMethod( NewMatrix, [ IsOperation, IsSemiring, IsList, IsInt ], + function( filter, basedomain, list, ncols ) + return NewMatrix( filter, basedomain, ncols, list ); + end); + +InstallMethod( NewMatrix, [ IsOperation, IsSemiring, IsList ], + function( filter, basedomain, list ) + return NewMatrix( filter, basedomain, Length( list[1] ), list ); + end); + InstallTagBasedMethod( NewMatrix, IsPlistMatrixRep, function( filter, basedomain, ncols, list ) @@ -343,6 +340,9 @@ InstallMethod( \[\], InstallMethod( \[\]\:\=, [ "IsPlistVectorRep", "IsPosInt", "IsObject" ], function( v, p, ob ) + if ValueOption( "check" ) <> false and Length( v![ELSPOS] ) < p then + Error( "

is out of bounds" ); + fi; v![ELSPOS][p] := ob; end ); @@ -699,7 +699,7 @@ InstallMethod( Matrix, else l := []; fi; - # The result shall be mutable iff 'rows' is mutable. + # The result shall be mutable iff 'list' is mutable. if not IsMutable( list ) then MakeImmutable( l ); fi; 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 b5780f80f4..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, @@ -1456,6 +1456,15 @@ InstallMethod( RowsOfMatrix, [ IsMatrix and IsPlistRep ], Immutable ); +# The following should be better than the generic method for +# matrix objects for 'IsMatrixOrMatrixObj', +# which first 'Unpack's the matrix and then +# creates new vector objects from the rows of the result. +InstallMethod( RowsOfMatrix, + "generic method for a matrix that is a list", + [ IsMatrix ], + PlainListCopy ); + InstallMethod( NumberRows, "generic method for a (perhaps empty) matrix", [ IsMatrix ], @@ -1588,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; @@ -1659,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; @@ -1734,7 +1743,7 @@ InstallMethod( DeterminantMat, end ); InstallMethod( DeterminantMatDestructive,"nonprime residue rings", - [ IsOrdinaryMatrix and + [ IsMatrixOrMatrixObj and CategoryCollections(CategoryCollections(IsZmodnZObjNonprime)) and IsMutable], DeterminantMatDivFree); @@ -1770,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 @@ -2326,7 +2335,7 @@ end ); ## InstallMethod( NullspaceMat, "generic method for ordinary matrices", - [ IsOrdinaryMatrix ], + [ IsMatrixOrMatrixObj ], mat -> SemiEchelonMatTransformation(mat).relations ); InstallOtherMethod(NullspaceMat,"matrix objects",[IsMatrixObj], @@ -2347,7 +2356,7 @@ end); InstallMethod( NullspaceMatDestructive, "generic method for ordinary matrices", - [ IsOrdinaryMatrix and IsMutable], + [ IsMatrixOrMatrixObj and IsMutable], mat -> SemiEchelonMatTransformationDestructive(mat).relations ); InstallOtherMethod( TriangulizedNullspaceMat, @@ -2372,7 +2381,7 @@ end ); InstallMethod( TriangulizedNullspaceMatNT, "generic method", - [ IsOrdinaryMatrix ], + [ IsMatrixOrMatrixObj ], function( mat ) local nullspace, n, empty, i, k, row, zero, one;# @@ -2416,7 +2425,7 @@ InstallMethod( TriangulizedNullspaceMatNT, end ); #InstallMethod(TriangulizedNullspaceMat,"generic method", -# [IsOrdinaryMatrix], +# [IsMatrixOrMatrixObj], # function ( mat ) # # triangulize the transposed of the matrix # return TriangulizedNullspaceMatNT( @@ -2424,7 +2433,7 @@ end ); #end ); #InstallMethod(TriangulizedNullspaceMatDestructive,"generic method", -# [IsOrdinaryMatrix], +# [IsMatrixOrMatrixObj], # function ( mat ) # # triangulize the transposed of the matrix # return TriangulizedNullspaceMatNT( @@ -2536,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 @@ -2547,7 +2556,7 @@ InstallOtherMethod( RankMatDestructive, InstallOtherMethod( RankMat, "generic method for matrices", - [ IsMatrix ], + [ IsMatrixOrMatrixObj ], mat -> RankMatDestructive( MutableCopyMatrix( mat ) ) ); @@ -3040,8 +3049,7 @@ InstallOtherMethod( SolutionMatDestructive, local i,ncols,sem, vno, z,x, sol; ncols := Length(vec); z := ZeroOfBaseDomain(mat); - sol := ListWithIdenticalEntries(NrRows(mat),z); - ConvertToVectorRepNC(sol); + sol:= ZeroVector( NrRows( mat ), vec ); if ncols <> NrCols(mat) then Error("SolutionMat: matrix and vector incompatible"); fi; @@ -4798,7 +4806,10 @@ BindGlobal("POW_MAT_INT", function(mat, n) b := rec(vectors := [], pivots := [], heads := []); t := []; # maybe better start with a random vector? - for a in id do + for a in RowsOfMatrix( id ) do +#TODO: 'RowsOfMatrix' is not what we want to call here. +# In fact, we should better create standard basis vectors +# as we need them, instead of creating 'id' . r := addb(b,a); if r = true then repeat diff --git a/lib/maxsub.gi b/lib/maxsub.gi index e04c94eaa5..5c823e4fd9 100644 --- a/lib/maxsub.gi +++ b/lib/maxsub.gi @@ -219,10 +219,8 @@ BindGlobal("MaximalSubgroupClassesSol",function(G) # if necessary extent the fphom if homliftlevel+1 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 c369951114..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> @@ -2743,11 +2757,16 @@ DeclareGlobalFunction("OnLines"); ## ## ## implements the action on sets of sets. -## For the special case that the sets are pairwise disjoint, +## set must be a proper set whose entries are again proper sets +## (see ). +##

+## returns the proper set whose elements are +## the images obtained by applying the action function +## to x and g, +## for each element x of set. +##

+## For the special case that the elements of set are pairwise disjoint, ## it is possible to use . -## set must be a sorted list whose entries are again sorted lists, -## otherwise an error is triggered -## (see ). ## OnSetsSets( [ [ 1, 2 ], [ 3, 4 ] ], (1,2,3) ); ## [ [ 1, 4 ], [ 2, 3 ] ] @@ -2774,9 +2793,16 @@ DeclareGlobalFunction( "OnSetsSets" ); ## ## implements the action on sets of pairwise disjoint sets ## (see also ). -## set must be a sorted list whose entries are again sorted lists, -## otherwise an error is triggered -## (see ). +## set must be a proper set whose entries are pairwise +## disjoint proper sets. +## However, it is not checked that the entries of +## set are indeed pairwise disjoint. +##

+## returns the proper +## set whose elements are +## the images obtained by applying the action function +## to x and g, +## for each element x of set. ## ## ## <#/GAPDoc> @@ -2794,9 +2820,13 @@ DeclareGlobalFunction( "OnSetsDisjointSets" ); ## ## ## implements the action on sets of tuples. -## set must be a sorted list, -## otherwise an error is triggered -## (see ). +## set must be a proper set of lists without holes +## (see ). +##

+## returns the proper set whose elements are +## the images obtained by applying the action function +## to x and g, +## for each element x of set. ## OnSetsTuples( [ [ 1, 2 ], [ 3, 4 ] ], (1,2,3) ); ## [ [ 1, 4 ], [ 2, 3 ] ] @@ -2815,17 +2845,21 @@ DeclareGlobalFunction("OnSetsTuples"); ############################################################################# ## -#F OnTuplesSets( , ) +#F OnTuplesSets( , ) ## ## <#GAPDoc Label="OnTuplesSets"> ## -## +## ## ## ## implements the action on tuples of sets. -## set must be a list whose entries are again sorted lists, -## otherwise an error is triggered -## (see ). +## tup must be a list without holes whose entries are proper sets +## (see ). +##

+## returns the list of +## the corresponding images obtained by applying the action function +## to x and g, +## for each entry x of tup. ## OnTuplesSets( [ [ 2, 3 ], [ 3, 4 ] ], (1,2,3) ); ## [ [ 1, 3 ], [ 1, 4 ] ] @@ -2844,14 +2878,21 @@ DeclareGlobalFunction("OnTuplesSets"); ############################################################################# ## -#F OnTuplesTuples( , ) +#F OnTuplesTuples( , ) ## ## <#GAPDoc Label="OnTuplesTuples"> ## -## +## ## ## ## implements the action on tuples of tuples. +## tup must be a list without holes whose entries are again +## lists without holes. +##

+## returns the list of +## the corresponding images obtained by applying the action function +## to x and g, +## for each entry x of the list tup. ## OnTuplesTuples( [ [ 2, 3 ], [ 3, 4 ] ], (1,2,3) ); ## [ [ 3, 1 ], [ 1, 4 ] ] diff --git a/lib/oprt.gi b/lib/oprt.gi index d9d6b34a81..a6e9972dbf 100644 --- a/lib/oprt.gi +++ b/lib/oprt.gi @@ -587,10 +587,9 @@ end ); ## #M ActionHomomorphismConstructor( , ) ## -InstallGlobalFunction( ActionHomomorphismConstructor, function(arg) -local xset,surj,G, D, act, fam, filter, hom, i,blockacttest; +InstallGlobalFunction( ActionHomomorphismConstructor, function(xset, surj, arg...) +local G, D, act, fam, filter, hom, i,blockacttest; - xset:=arg[1];surj:=arg[2]; G := ActingDomain( xset ); D := HomeEnumerator( xset ); act := FunctionAction( xset ); @@ -650,8 +649,8 @@ local xset,surj,G, D, act, fam, filter, hom, i,blockacttest; end; hom := rec( ); - if Length(arg)>2 then - filter:=arg[3]; + if Length(arg)>0 then + filter:=arg[1]; elif IsExternalSetByActorsRep( xset ) then filter := filter and IsActionHomomorphismByActors; elif IsMatrixGroup( G ) @@ -1789,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); @@ -1802,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 ); @@ -1920,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); @@ -1932,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); @@ -3380,7 +3377,7 @@ end ); InstallMethod( PreImagesRepresentative,"IsLinearActionHomomorphism", FamRangeEqFamElm, [ IsLinearActionHomomorphism, IsPerm ], 0, function( hom, elm ) - local V, G, Grep, xset,lab,f; + local V, G, Grep, filt, R, xset,lab,f; # is this method applicable? Test whether the domain contains a vector # space basis (respectively just get this basis). @@ -3395,19 +3392,26 @@ function( hom, elm ) V := HomeEnumerator(xset); G:= Source( hom ); Grep:= Representative( G ); + filt:= ConstructingFilter( Grep ); f:=DefaultFieldOfMatrixGroup(G); - + if HasBaseDomain( Grep ) then + R:= BaseDomain( Grep ); + else + R:= f; + fi; +#TODO: Here `BaseDomain( G )` should be used, once it is implemented. if not IsBound(hom!.linActBasisPositions) then hom!.linActBasisPositions:=List(lab,i->PositionCanonical(V,i)); fi; if not IsBound(hom!.linActInverse) then - lab:=ImmutableMatrix(f, Matrix( lab, Grep )); + # Create a matrix whose `BaseDomain` is the same as that of the group. + lab:=ImmutableMatrix(f, Matrix( filt, R, lab )); hom!.linActInverse:=Inverse(lab); fi; elm:=OnTuples(hom!.linActBasisPositions,elm); # image points elm:=V{elm}; # the corresponding vectors - elm:=ImmutableMatrix(f, Matrix( elm, Grep )); + elm:=ImmutableMatrix(f, Matrix( filt, R, elm )); return hom!.linActInverse*elm; end ); @@ -3438,7 +3442,7 @@ end ); InstallMethod( PreImagesRepresentative,"IsProjectiveActionHomomorphism", FamRangeEqFamElm, [ IsProjectiveActionHomomorphism, IsPerm ], 0, function( hom, elm ) - local V, G, Grep, mat, xset,lab,dim,sol,i; + local V, G, Grep, filt, R, mat, xset,lab,dim,sol,i; # is this method applicable? Test whether field # finite, that the domain contains a vector @@ -3457,12 +3461,18 @@ function( hom, elm ) V := HomeEnumerator(xset); G:= Source( hom ); Grep:= Representative( G ); + filt:= ConstructingFilter( Grep ); + if HasBaseDomain( Grep ) then + R:= BaseDomain( Grep ); + else + R:= DefaultFieldOfMatrixGroup(G); + fi; dim:=DimensionOfMatrixGroup(G); elm:=OnTuples(hom!.projActBasisPositions,elm); # image points elm:=V{elm}; # the corresponding vectors - mat:= Matrix( List( elm{ [ 1 .. dim ] }, ShallowCopy ), Grep ); + mat:= Matrix( filt, R, List( elm{ [ 1 .. dim ] }, ShallowCopy ) ); sol:=SolutionMat(mat,elm[dim+1]); for i in [1..dim] do MultMatrixRow( mat, i, sol[i] ); @@ -3488,7 +3498,7 @@ end); InstallMethod(LinearActionBasis,"find basis in domain",true, [IsLinearActionHomomorphism],0, function(hom) -local xset, base, M, D, b, t, i, r, pos, v; +local xset, base, M, filt, R, D, b, t, i, r, pos, v; xset:=UnderlyingExternalSet(hom); if Size(xset)=0 then return fail; @@ -3498,8 +3508,13 @@ local xset, base, M, D, b, t, i, r, pos, v; base:= BaseOfGroup(xset); if IsMatrix( base ) then M:= base; - elif ForAll( base, IsVectorObj ) then - M:= Matrix( BaseOfGroup( xset ), One( ActingDomain( xset ) ) ); + elif ForAll( base, IsVectorObj and HasBaseDomain ) then + # All entries of 'base' have the same 'BaseDomain'. + filt:= ConstructingFilter( Representative( ActingDomain( xset ) ) ); + R:= BaseDomain( base[1] ); + M:= Matrix( filt, R, base ); + else + Error( "unsupported 'BaseOfGroup' value for " ); fi; if RankMat( M ) = NrCols( M ) then # this implies injectivity @@ -3562,7 +3577,7 @@ end); InstallOtherMethod(LinearActionBasis,"projective with extra vector",true, [IsProjectiveActionHomomorphism],0, function(hom) -local xset,G,Grep,D,b,t,i,r,binv,pos,dets,roots,dim,f,v; +local xset,G,Grep,filt,R,D,b,t,i,r,binv,pos,dets,roots,dim,f,v; xset:=UnderlyingExternalSet(hom); if Size(xset)=0 then return fail; @@ -3571,9 +3586,14 @@ local xset,G,Grep,D,b,t,i,r,binv,pos,dets,roots,dim,f,v; # will the determinants suffice to get suitable scalars? G:= Source(hom); Grep:= Representative( G ); + filt:= ConstructingFilter( Grep ); dim:=DimensionOfMatrixGroup(G); f:=DefaultFieldOfMatrixGroup(G); - + if HasBaseDomain( Grep ) then + R:= BaseDomain( Grep ); + else + R:= f; + fi; roots:=Set(RootsOfUPol(f,X(f)^dim-1)); D:=List(GeneratorsOfGroup(G),DeterminantMat); @@ -3622,7 +3642,7 @@ local xset,G,Grep,D,b,t,i,r,binv,pos,dets,roots,dim,f,v; fi; # try to find a vector that has nonzero coefficients for all b - binv:= Inverse( ImmutableMatrix( f, Matrix( b, Grep ) ) ); + binv:= Inverse( ImmutableMatrix( f, Matrix( filt, R, b ) ) ); while i<=Length(D) do if ForAll( Unpack( D[i] * binv ), x -> not IsZero(x) ) then #TODO: get rid of 'Unpack'? 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/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/primality.gd b/lib/primality.gd index 1f6ca240be..b8787d957c 100644 --- a/lib/primality.gd +++ b/lib/primality.gd @@ -97,8 +97,6 @@ DeclareGlobalFunction("IsSquareInt"); DeclareGlobalFunction("IsStrongPseudoPrimeBaseA"); DeclareGlobalFunction("IsBPSWLucasPseudoPrime"); -DeclareGlobalFunction("IsLucasPseudoPrimeDP"); -DeclareGlobalFunction("IsStrongLucasPseudoPrimeDP"); DeclareGlobalFunction("IsBPSWPseudoPrime"); DeclareGlobalFunction("IsBPSWPseudoPrime_VerifyCorrectness"); diff --git a/lib/primality.gi b/lib/primality.gi index 63ff2bb37c..b5a288c320 100644 --- a/lib/primality.gi +++ b/lib/primality.gi @@ -347,71 +347,6 @@ end); # while Jacobi( P^2-4, N ) <> -1 do P:=(P+1) mod N; if P = 2 then return fail; fi; od; # return [ (P^2-4) mod N, P, 1 ]; #end; -#InstallGlobalFunction(IsBPSWLucasPseudoPrime, -#function(N) -# local params, func, lucas; -# if N = 2 then return true; fi; -# if IsSquareInt(N) or IsEvenInt(N) then return false; fi; -# if ValueOption("BPSWLucasParameters") = fail -# then func:=BPSWLucasParameters_GAP; -# else func:=ValueOption("BPSWLucasParameters"); -# fi; -# if ValueOption("BPSWLucasTest") = fail then -# if func = BPSWLucasParameters_GAP -# then lucas:=function(N,D,P) return TraceModQF(P,N+1,N) = [2,P]; end; -# else lucas:=IsLucasPseudoPrimeDP; -# fi; -# else lucas:=ValueOption("BPSWLucasTest"); -# fi; -# params := CALL_FUNC_LIST(func,[N]); -# if Jacobi(params[1],N) = 0 and params[1] < N and 0 < params[1] then return false; fi; -# return CALL_FUNC_LIST(lucas,[N, params[1], params[2]]); -#end); - -############################################################################## -## -#F IsLucasPseudoPrimeDP(N,D,P) - Check if N is a Lucas pseudoprime for -## x^2+P*x+(P^2-D)/4. D must be a nonsquare mod N, and N must be odd or prime. -## -############################################################################## -InstallGlobalFunction(IsLucasPseudoPrimeDP, -function(N,D,P) - local Q; - if N = 2 then return true; fi; - Q := (P^2-D)/4 mod N; - if not ( IsOddInt(N) and 0 <> Q mod N and Jacobi(D,N) = -1 ) then Error(); fi; - return IsOddInt(N) and 0 <> Q mod N and Jacobi(D,N) = -1 and 0 = LucasMod(P,Q,N,N+1)[1]; -end); - -############################################################################## -## -#F IsStrongLucasPseudoPrimeDP(N,D,P) - Check if N is a strong Lucas -## pseudoprime for x^2+P*x+(P^2-D)/4. N must be odd or prime. -## -############################################################################## -InstallGlobalFunction(IsStrongLucasPseudoPrimeDP, -function(N,D,P) - local Q,d,s,J,L,r,Qi; - if N = 2 then return true; fi; - if N in [-1,0,1] then return false; fi; - if not ( IsOddInt(N) and GcdInt(N,D)=1 ) then return false; fi; - Q := (P^2-D)/4 mod N; - J := Jacobi(D,N); - d := N - J; s:=0; while IsEvenInt(d) do s:=s+1; d:=d/2; od; # Now N-(D/N) = 2^s * d, d odd - L := LucasMod(P,Q,N,d); - # Does n divide U_d ? - if L[1] = 0 then return true; fi; - # Does n divide V_{2^r d} for some r=0,1,...,s-1 ? - Qi := PowerModInt(Q,d,N); - for r in [0..s-1] do - if L[2] = 0 then return true; fi; - # L is [Ui,Vi], make it [U2i,V2i] = [ Ui*Vi, Vi^2 - 2Q^i], where i=2^s d - L[1] := L[1]*L[2] mod N; - L[2] := (L[2]^2 - 2*Qi) mod N; - Qi := Qi*Qi mod N; - od; - return false; -end); ############################################################################## ## 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/read3.g b/lib/read3.g index baf3cf714c..b3fdbbc96a 100644 --- a/lib/read3.g +++ b/lib/read3.g @@ -107,6 +107,7 @@ ReadLib( "wordass.gd" ); ReadLib( "matobj2.gd" ); ReadLib( "matobjplist.gd" ); +ReadLib( "matobjgeneric.gd" ); ReadLib( "matobjnz.gd" ); # files dealing with rewriting systems diff --git a/lib/read5.g b/lib/read5.g index e0042c6bf4..cb4a8365b1 100644 --- a/lib/read5.g +++ b/lib/read5.g @@ -114,6 +114,7 @@ ReadLib( "vecmat.gi" ); ReadLib( "vec8bit.gi" ); ReadLib( "mat8bit.gi" ); ReadLib( "matobjplist.gi" ); +ReadLib( "matobjgeneric.gi" ); ReadLib( "matobjnz.gi" ); ReadLib( "meataxe.gi" ); ReadLib( "meatauto.gi" ); diff --git a/lib/ringhom.gi b/lib/ringhom.gi index 21791f48a8..9b3c908705 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 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/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/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/test.gi b/lib/test.gi index 32addda12d..b2b729b86e 100644 --- a/lib/test.gi +++ b/lib/test.gi @@ -614,7 +614,7 @@ DeclareGlobalName("TextAttr"); # from GAPDoc DeclareGlobalName("DefaultReportDiffColors"); # initialized in Test() or by the user BindGlobal("DefaultReportDiff", function(inp, expout, found, fnam, line, time) if UserPreference("UseColorsInTerminal") = true - and IsBound( GAPInfo.PackagesLoaded.gapdoc ) then + and IsBound( DefaultReportDiffColors ) then Print(DefaultReportDiffColors.message); Print("########> Diff in "); if IsStream(fnam) then diff --git a/lib/vec8bit.gd b/lib/vec8bit.gd index 092c3ff08e..9cca4572c9 100644 --- a/lib/vec8bit.gd +++ b/lib/vec8bit.gd @@ -47,7 +47,7 @@ MakeImmutable(PRIMES_COMPACT_FIELDS); ## , the entries are packed into bytes. ## DeclareRepresentation( "Is8BitVectorRep", - IsDataObjectRep and IsVectorObj + IsDataObjectRep and IsVectorObj and IsList and IsCopyable and IsNoImmediateMethodsObject and HasBaseDomain and HasOneOfBaseDomain and HasZeroOfBaseDomain); diff --git a/lib/vec8bit.gi b/lib/vec8bit.gi index 1602a4ca36..39893b4afb 100644 --- a/lib/vec8bit.gi +++ b/lib/vec8bit.gi @@ -985,7 +985,7 @@ InstallMethodWithRandomSource( Randomize, for i in [1..Length(v)] do v[i] := Random(rs,l); od; return v; end ); -InstallMethod( MutableCopyMatrix, "for an 8bit matrix", +InstallOtherMethod( MutableCopyMatrix, "for an 8bit matrix", [ Is8BitMatrixRep ], function( m ) local mm; @@ -1088,10 +1088,16 @@ InstallMethod( BaseField, "for a compressed 8bit vector", InstallTagBasedMethod( NewVector, Is8BitVectorRep, function( filter, f, l ) - if ValueOption( "check" ) <> false and not Size(f) in [3..256] then + local check, res; + check:= ValueOption( "check" ) <> false; + if check and not Size(f) in [3..256] then Error("Is8BitVectorRep only supports base fields with 3 to 256 elements"); fi; - return CopyToVectorRep(l,Size(f)); + res:= CopyToVectorRep( l, Size( f ) ); + if check and res = fail then + Error( "cannot copy to 'Is8BitVectorRep'" ); + fi; + return res; end ); # This is faster than the default method. @@ -1125,7 +1131,9 @@ InstallTagBasedMethod( NewMatrix, else m := List(l,ShallowCopy); fi; - ConvertToMatrixRep(m,Size(f)); + if ConvertToMatrixRep( m, Size( f ) ) = fail then + Error( "cannot convert to 'Is8BitMatrixRep'" ); + fi; return m; end ); diff --git a/lib/vecmat.gd b/lib/vecmat.gd index 393a969f93..9b27408ed2 100644 --- a/lib/vecmat.gd +++ b/lib/vecmat.gd @@ -50,7 +50,7 @@ BIND_GLOBAL( "GF2Zero", 0*Z(2) ); ## , the entries are packed into bits. ## DeclareRepresentation( "IsGF2VectorRep", - IsDataObjectRep and IsVectorObj + IsDataObjectRep and IsVectorObj and IsList and IsCopyable and IsNoImmediateMethodsObject and HasBaseDomain and HasOneOfBaseDomain and HasZeroOfBaseDomain); @@ -254,7 +254,7 @@ DeclareGlobalFunction( "ConvertToMatrixRep" ); ## i+1. ## DeclareRepresentation( "IsGF2MatrixRep", - IsPositionalObjectRep and IsRowListMatrix + IsPositionalObjectRep and IsRowListMatrix and IsMatrix and IsCopyable and IsNoImmediateMethodsObject and HasNumberRows and HasNumberColumns diff --git a/lib/vecmat.gi b/lib/vecmat.gi index 8e319696b3..24e2f72445 100644 --- a/lib/vecmat.gi +++ b/lib/vecmat.gi @@ -2434,7 +2434,7 @@ InstallMethodWithRandomSource( Randomize, return v; end ); -InstallMethod( MutableCopyMatrix, "for a gf2 matrix", +InstallOtherMethod( MutableCopyMatrix, "for a gf2 matrix", [ IsGF2MatrixRep ], function( m ) local mm; @@ -2553,8 +2553,13 @@ InstallMethod( BaseField, "for a compressed gf2 vector", InstallTagBasedMethod( NewVector, IsGF2VectorRep, function( filter, f, l ) + local res; if Size(f) <> 2 then Error("IsGF2VectorRep only supported over GF(2)"); fi; - return CopyToVectorRep(l,2); + res:= CopyToVectorRep( l, 2 ); + if res = fail then + Error( "cannot copy to 'IsGF2VectorRep'" ); + fi; + return res; end ); InstallTagBasedMethod( NewZeroVector, @@ -2581,7 +2586,9 @@ InstallTagBasedMethod( NewMatrix, else m := List(l,ShallowCopy); fi; - ConvertToMatrixRep(m,2); + if ConvertToMatrixRep( m, 2 ) = fail then + Error( "cannot convert to 'IsGF2MatrixRep'" ); + fi; return m; end ); diff --git a/lib/zmodnz.gi b/lib/zmodnz.gi index 980652b8f1..2a352eccf0 100644 --- a/lib/zmodnz.gi +++ b/lib/zmodnz.gi @@ -869,6 +869,7 @@ InstallMethod( TriangulizeMat, ## #M ViewObj( ) . . . . . . . . . . . . . . . . method for full ring Z/nZ #M PrintObj( ) . . . . . . . . . . . . . . . . method for full ring Z/nZ +#M String( ) . . . . . . . . . . . . . . . . . method for full ring Z/nZ ## InstallMethod( ViewObj, "for full ring Z/nZ", @@ -884,6 +885,11 @@ InstallMethod( PrintObj, Print( "(Integers mod ", Size( obj ), ")" ); end ); +InstallMethod( String, + "for full ring Z/nZ", + [ IsZmodnZObjNonprimeCollection and IsWholeFamily ], SUM_FLAGS, + obj -> Concatenation( "(Integers mod ", String( Size( obj ) ), ")" ) ); + ############################################################################# ## diff --git a/src/ariths.c b/src/ariths.c index f908e4761a..92201121a3 100644 --- a/src/ariths.c +++ b/src/ariths.c @@ -20,7 +20,7 @@ #define RequireValue(funcname, val) \ do { \ - if (!val) \ + if (!(val)) \ ErrorMayQuit(funcname ": method should have returned a value", \ 0, 0); \ } while (0) diff --git a/src/boehm_gc.c b/src/boehm_gc.c index a0bbd942aa..0235f5bc3e 100644 --- a/src/boehm_gc.c +++ b/src/boehm_gc.c @@ -544,14 +544,9 @@ UInt ResizeBag(Bag bag, UInt new_size) } -/***************************************************************************** -** The following functions are not required respectively supported, so empty -** implementations are provided -** -*/ - void InitGlobalBag(Bag * addr, const Char * cookie) { + // No need to track globals with Boehm GC } void SwapMasterPoint(Bag bag1, Bag bag2) diff --git a/src/code.c b/src/code.c index a5daa42082..40268f9de8 100644 --- a/src/code.c +++ b/src/code.c @@ -44,22 +44,29 @@ GAP_STATIC_ASSERT(sizeof(StatHeader) == 8, "StatHeader has wrong size"); +#ifdef HPCGAP struct CodeModuleState { - Bag StackStat; - Int CountStat; +#endif +DECL_MODULE_STATE Bag StackStat; +DECL_MODULE_STATE Int CountStat; - Bag StackExpr; - Int CountExpr; +DECL_MODULE_STATE Bag StackExpr; +DECL_MODULE_STATE Int CountExpr; +#ifdef HPCGAP }; 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); } #define CS(x) (CShelper()->x) +#else +#define CS(x) (x) +#endif /**************************************************************************** @@ -1755,14 +1762,14 @@ void CodeListExprEnd( } // allocate the list expression - if ( ! range && ! (top && tilde) ) { - list = NewExpr(cs, EXPR_LIST, INT_INTEXPR(pos) * sizeof(Expr)); + if (range) { + list = NewExpr(cs, EXPR_RANGE, INT_INTEXPR(pos) * sizeof(Expr)); } - else if ( ! range && (top && tilde) ) { + else if (top && tilde) { list = NewExpr(cs, EXPR_LIST_TILDE, INT_INTEXPR(pos) * sizeof(Expr)); } - else /* if ( range && ! (top && tilde) ) */ { - list = NewExpr(cs, EXPR_RANGE, INT_INTEXPR(pos) * sizeof(Expr)); + else { + list = NewExpr(cs, EXPR_LIST, INT_INTEXPR(pos) * sizeof(Expr)); } // enter the entries @@ -3250,8 +3257,10 @@ static StructInitInfo module = { .preSave = PreSave, .postRestore = PostRestore, +#ifdef HPCGAP .moduleStateSize = sizeof(struct CodeModuleState), .moduleStateOffsetPtr = &CodeStateOffset, +#endif .initModuleState = InitModuleState, }; diff --git a/src/collectors.cc b/src/collectors.cc index 9a127eda65..c3561ea8db 100644 --- a/src/collectors.cc +++ b/src/collectors.cc @@ -46,24 +46,40 @@ extern "C" { *F * * * * * * * * * * * * * module specific state * * * * * * * * * * * * * */ +#ifdef HPCGAP struct CollectorsState_ { - Obj SC_NW_STACK; - Obj SC_LW_STACK; - Obj SC_PW_STACK; - Obj SC_EW_STACK; - Obj SC_GE_STACK; - Obj SC_CW_VECTOR; - Obj SC_CW2_VECTOR; - UInt SC_MAX_STACK_SIZE; +#endif + +DECL_MODULE_STATE Obj SC_NW_STACK; +DECL_MODULE_STATE Obj SC_LW_STACK; +DECL_MODULE_STATE Obj SC_PW_STACK; +DECL_MODULE_STATE Obj SC_EW_STACK; +DECL_MODULE_STATE Obj SC_GE_STACK; +DECL_MODULE_STATE Obj SC_CW_VECTOR; +DECL_MODULE_STATE Obj SC_CW2_VECTOR; +DECL_MODULE_STATE UInt SC_MAX_STACK_SIZE; +#ifdef HPCGAP }; 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); } +#define SC_NW_STACK (CollectorsState()->SC_NW_STACK) +#define SC_LW_STACK (CollectorsState()->SC_LW_STACK) +#define SC_PW_STACK (CollectorsState()->SC_PW_STACK) +#define SC_EW_STACK (CollectorsState()->SC_EW_STACK) +#define SC_GE_STACK (CollectorsState()->SC_GE_STACK) +#define SC_CW_VECTOR (CollectorsState()->SC_CW_VECTOR) +#define SC_CW2_VECTOR (CollectorsState()->SC_CW2_VECTOR) +#define SC_MAX_STACK_SIZE (CollectorsState()->SC_MAX_STACK_SIZE) + +#endif + /**************************************************************************** ** @@ -84,7 +100,7 @@ extern inline struct CollectorsState_ * CollectorsState(void) */ #define SC_PUSH_WORD( word, exp ) \ if ( ++sp == max ) { \ - CollectorsState()->SC_MAX_STACK_SIZE *= 2; \ + SC_MAX_STACK_SIZE *= 2; \ return -1; \ } \ *++nw = DATA_WORD(word); \ @@ -95,7 +111,7 @@ extern inline struct CollectorsState_ * CollectorsState(void) #define SC_PUSH_GEN( gen, exp ) \ if ( ++sp == max ) { \ - CollectorsState()->SC_MAX_STACK_SIZE *= 2; \ + SC_MAX_STACK_SIZE *= 2; \ return -1; \ } \ *++nw = DATA_WORD(gen); \ @@ -365,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); @@ -385,44 +401,44 @@ static Int SingleCollectWord(Obj sc, Obj vv, Obj w) exps = (UInt)1 << (ebits-1); // contains the stack of words to insert - vnw = CollectorsState()->SC_NW_STACK; + vnw = SC_NW_STACK; // contains the word end of the word in - vlw = CollectorsState()->SC_LW_STACK; + vlw = SC_LW_STACK; // contains the position of the word in to look at - vpw = CollectorsState()->SC_PW_STACK; + vpw = SC_PW_STACK; // contains the unprocessed exponents at position - vew = CollectorsState()->SC_EW_STACK; + vew = SC_EW_STACK; // contains the global exponent of the word - vge = CollectorsState()->SC_GE_STACK; + vge = SC_GE_STACK; // get the maximal stack size - max = CollectorsState()->SC_MAX_STACK_SIZE; + max = SC_MAX_STACK_SIZE; // ensure that the stacks are large enough 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; @@ -876,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 ) { @@ -893,44 +909,44 @@ static Int CombiCollectWord(Obj sc, Obj vv, Obj w) exps = (UInt)1 << (ebits-1); // contains the stack of words to insert - vnw = CollectorsState()->SC_NW_STACK; + vnw = SC_NW_STACK; // contains the word end of the word in - vlw = CollectorsState()->SC_LW_STACK; + vlw = SC_LW_STACK; // contains the position of the word in to look at - vpw = CollectorsState()->SC_PW_STACK; + vpw = SC_PW_STACK; // contains the unprocessed exponents at position - vew = CollectorsState()->SC_EW_STACK; + vew = SC_EW_STACK; // contains the global exponent of the word - vge = CollectorsState()->SC_GE_STACK; + vge = SC_GE_STACK; // get the maximal stack size - max = CollectorsState()->SC_MAX_STACK_SIZE; + max = SC_MAX_STACK_SIZE; // ensure that the stacks are large enough 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; @@ -1267,7 +1283,7 @@ static Obj ReducedComm(FinPowConjCol * fc, Obj sc, Obj w, Obj u) Obj vc2; // collect vector // use 'cwVector' to collect word * to - vcw = CollectorsState()->SC_CW_VECTOR; + vcw = SC_CW_VECTOR; num = SC_NUMBER_RWS_GENERATORS(sc); // check that it has the correct length, unpack into it @@ -1283,7 +1299,7 @@ static Obj ReducedComm(FinPowConjCol * fc, Obj sc, Obj w, Obj u) } // use 'cw2Vector' to collect word * to - vc2 = CollectorsState()->SC_CW2_VECTOR; + vc2 = SC_CW2_VECTOR; // check that it has the correct length, unpack into it if ( fc->vectorWord( vc2, w, num ) == -1 ) { @@ -1325,7 +1341,7 @@ static Obj ReducedForm(FinPowConjCol * fc, Obj sc, Obj w) Obj type; // type of the return objue // use 'cwVector' to collect word to - vcw = CollectorsState()->SC_CW_VECTOR; + vcw = SC_CW_VECTOR; num = SC_NUMBER_RWS_GENERATORS(sc); // check that it has the correct length @@ -1358,7 +1374,7 @@ static Obj ReducedLeftQuotient(FinPowConjCol * fc, Obj sc, Obj w, Obj u) Obj vc2; // collect vector // use 'cwVector' to collect word to - vcw = CollectorsState()->SC_CW_VECTOR; + vcw = SC_CW_VECTOR; num = SC_NUMBER_RWS_GENERATORS(sc); // check that it has the correct length, unpack into it @@ -1368,7 +1384,7 @@ static Obj ReducedLeftQuotient(FinPowConjCol * fc, Obj sc, Obj w, Obj u) } // use 'cw2Vector' to collect word to - vc2 = CollectorsState()->SC_CW2_VECTOR; + vc2 = SC_CW2_VECTOR; // check that it has the correct length, unpack into it if ( fc->vectorWord( vc2, u, num ) == -1 ) { @@ -1402,7 +1418,7 @@ static Obj ReducedProduct(FinPowConjCol * fc, Obj sc, Obj w, Obj u) Obj vcw; // collect vector // use 'cwVector' to collect word to - vcw = CollectorsState()->SC_CW_VECTOR; + vcw = SC_CW_VECTOR; num = SC_NUMBER_RWS_GENERATORS(sc); // check that it has the correct length, unpack into it @@ -1441,8 +1457,8 @@ static Obj ReducedPowerSmallInt(FinPowConjCol * fc, Obj sc, Obj w, Obj vpow) pow = INT_INTOBJ(vpow); // use 'cwVector' and 'cw2Vector to collect words to - vcw = CollectorsState()->SC_CW_VECTOR; - vc2 = CollectorsState()->SC_CW2_VECTOR; + vcw = SC_CW_VECTOR; + vc2 = SC_CW2_VECTOR; num = SC_NUMBER_RWS_GENERATORS(sc); type = SC_DEFAULT_TYPE(sc); @@ -1528,8 +1544,8 @@ static Obj ReducedQuotient(FinPowConjCol * fc, Obj sc, Obj w, Obj u) Obj vc2; // collect vector // use 'cwVector' to collect word to - vcw = CollectorsState()->SC_CW_VECTOR; - vc2 = CollectorsState()->SC_CW2_VECTOR; + vcw = SC_CW_VECTOR; + vc2 = SC_CW2_VECTOR; num = SC_NUMBER_RWS_GENERATORS(sc); type = SC_DEFAULT_TYPE(sc); @@ -1647,8 +1663,7 @@ static Obj FuncFinPowConjCol_ReducedQuotient ( Obj self, Obj sc, Obj w, Obj u ) */ static Obj FuncSET_SCOBJ_MAX_STACK_SIZE(Obj self, Obj size) { - CollectorsState()->SC_MAX_STACK_SIZE = - GetPositiveSmallInt(SELF_NAME, size); + SC_MAX_STACK_SIZE = GetPositiveSmallInt(SELF_NAME, size); return 0; } @@ -1739,25 +1754,25 @@ static Int InitLibrary ( static Int InitModuleState(void) { // register global bags with the garbage collector - InitGlobalBag( &CollectorsState()->SC_NW_STACK, "SC_NW_STACK" ); - InitGlobalBag( &CollectorsState()->SC_LW_STACK, "SC_LW_STACK" ); - InitGlobalBag( &CollectorsState()->SC_PW_STACK, "SC_PW_STACK" ); - InitGlobalBag( &CollectorsState()->SC_EW_STACK, "SC_EW_STACK" ); - InitGlobalBag( &CollectorsState()->SC_GE_STACK, "SC_GE_STACK" ); - InitGlobalBag( &CollectorsState()->SC_CW_VECTOR, "SC_CW_VECTOR" ); - InitGlobalBag( &CollectorsState()->SC_CW2_VECTOR, "SC_CW2_VECTOR" ); + InitGlobalBag(&SC_NW_STACK, "SC_NW_STACK"); + InitGlobalBag(&SC_LW_STACK, "SC_LW_STACK"); + InitGlobalBag(&SC_PW_STACK, "SC_PW_STACK"); + InitGlobalBag(&SC_EW_STACK, "SC_EW_STACK"); + InitGlobalBag(&SC_GE_STACK, "SC_GE_STACK"); + InitGlobalBag(&SC_CW_VECTOR, "SC_CW_VECTOR"); + InitGlobalBag(&SC_CW2_VECTOR, "SC_CW2_VECTOR"); const UInt maxStackSize = 256; const UInt desiredStackSize = sizeof(Obj) * (maxStackSize + 2); - CollectorsState()->SC_NW_STACK = NewKernelBuffer(desiredStackSize); - CollectorsState()->SC_LW_STACK = NewKernelBuffer(desiredStackSize); - CollectorsState()->SC_PW_STACK = NewKernelBuffer(desiredStackSize); - CollectorsState()->SC_EW_STACK = NewKernelBuffer(desiredStackSize); - CollectorsState()->SC_GE_STACK = NewKernelBuffer(desiredStackSize); + SC_NW_STACK = NewKernelBuffer(desiredStackSize); + SC_LW_STACK = NewKernelBuffer(desiredStackSize); + SC_PW_STACK = NewKernelBuffer(desiredStackSize); + SC_EW_STACK = NewKernelBuffer(desiredStackSize); + SC_GE_STACK = NewKernelBuffer(desiredStackSize); - CollectorsState()->SC_CW_VECTOR = NEW_STRING(0); - CollectorsState()->SC_CW2_VECTOR = NEW_STRING(0); - CollectorsState()->SC_MAX_STACK_SIZE = maxStackSize; + SC_CW_VECTOR = NEW_STRING(0); + SC_CW2_VECTOR = NEW_STRING(0); + SC_MAX_STACK_SIZE = maxStackSize; return 0; } @@ -1779,8 +1794,10 @@ static StructInitInfo module = { /* preSave = */ 0, /* postSave = */ 0, /* postRestore = */ 0, +#ifdef HPCGAP /* moduleStateSize = */ sizeof(CollectorsState_), /* moduleStateOffsetPtr = */ &CollectorsStateOffset, +#endif /* initModuleState = */ InitModuleState, /* destroyModuleState = */ 0, }; diff --git a/src/cyclotom.c b/src/cyclotom.c index 0686e459cd..17b61a3c03 100644 --- a/src/cyclotom.c +++ b/src/cyclotom.c @@ -142,10 +142,11 @@ static inline void SET_NOF_CYC(Obj cyc, Obj val) // #define XXX_CYC(cyc,len) (EXPOS_CYC(cyc,len)[0]) - +#ifdef HPCGAP static ModuleStateOffset CycStateOffset = -1; struct CycModuleState { +#endif /**************************************************************************** ** @@ -158,7 +159,7 @@ struct CycModuleState { ** It is created in 'InitCyc' with room for up to 1000 coefficients and is ** resized when need arises. */ -Obj ResultCyc; +DECL_MODULE_STATE Obj ResultCyc; /**************************************************************************** ** @@ -178,21 +179,23 @@ Obj ResultCyc; ** is called to compute $e_n^i$ and can then do this easier by just putting ** 1 at the th place in 'ResultCyc' and then calling 'Cyclotomic'. */ -Obj LastECyc; -UInt LastNCyc; +DECL_MODULE_STATE Obj LastECyc; +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); } // For convenience and readability -#define ResultCyc CycState()->ResultCyc -#define LastECyc CycState()->LastECyc -#define LastNCyc CycState()->LastNCyc - +#define ResultCyc (CycState()->ResultCyc) +#define LastECyc (CycState()->LastECyc) +#define LastNCyc (CycState()->LastNCyc) +#endif static void GrowResultCyc(UInt size) { @@ -833,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 @@ -2201,8 +2204,10 @@ static StructInitInfo module = { .initKernel = InitKernel, .initLibrary = InitLibrary, +#ifdef HPCGAP .moduleStateSize = sizeof(struct CycModuleState), .moduleStateOffsetPtr = &CycStateOffset, +#endif .initModuleState = InitModuleState, }; diff --git a/src/dt.c b/src/dt.c index e9f44de22b..67f2912197 100644 --- a/src/dt.c +++ b/src/dt.c @@ -61,7 +61,7 @@ #include "modules.h" #include "plist.h" -static void UnmarkTree(Obj z); +static void UnmarkTree(Obj tree); static UInt Mark(Obj tree, Obj reftree, Int indexx); static Int AlmostEqual(Obj tree1, Int index1, Obj tree2, Int index2); static Int Equal(Obj tree1, Int index1, Obj tree2, Int index2); @@ -726,16 +726,15 @@ static Int Leftof(Obj tree1, Int index1, Obj tree2, Int index2) */ static Int Leftof2(Obj tree1, Int index1, Obj tree2, Int index2) { - if ( DT_GEN(tree2, index2) < DT_GEN(tree1, DT_RIGHT(tree1, index1) ) ) - return 0; - else if (Equal(tree1, DT_RIGHT(tree1, index1), tree2, index2 ) ) - return 0; - else if (DT_GEN(tree2, index2) == DT_GEN(tree1, DT_RIGHT(tree1, index1)) ) - return Leftof(tree1, DT_RIGHT(tree1, index1), tree2, index2 ); - else if (Equal(tree1, DT_LEFT(tree1, index1), tree2, index2) ) - return 0; - else - return Leftof(tree1, DT_LEFT(tree1, index1), tree2, index2); + if (DT_GEN(tree2, index2) < DT_GEN(tree1, DT_RIGHT(tree1, index1))) + return 0; + if (Equal(tree1, DT_RIGHT(tree1, index1), tree2, index2)) + return 0; + if (DT_GEN(tree2, index2) == DT_GEN(tree1, DT_RIGHT(tree1, index1))) + return Leftof(tree1, DT_RIGHT(tree1, index1), tree2, index2); + if (Equal(tree1, DT_LEFT(tree1, index1), tree2, index2)) + return 0; + return Leftof(tree1, DT_LEFT(tree1, index1), tree2, index2); } 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 64c3aa5a3f..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 @@ -192,13 +185,13 @@ void ErrorBoundedInt(const char * funcname, int min, int max) NORETURN; -#define RequireBoundedIntEx(funcname, op, argname, min, max) \ - do { \ - if (!(IS_INTOBJ(op) && min <= INT_INTOBJ(op) && \ - INT_INTOBJ(op) <= max)) { \ - ErrorBoundedInt(funcname, op, argname, min, max); \ - } \ - } while (0) +EXPORT_INLINE void RequireBoundedIntEx( + const char * funcname, Obj op, const char * argname, int min, int max) +{ + if (!(IS_INTOBJ(op) && min <= INT_INTOBJ(op) && INT_INTOBJ(op) <= max)) { + ErrorBoundedInt(funcname, op, argname, min, max); + } +} #define RequireBoundedInt(funcname, op, min, max) \ RequireBoundedIntEx(funcname, op, NICE_ARGNAME(op), min, max) diff --git a/src/exprs.c b/src/exprs.c index 511188322b..840d2d709b 100644 --- a/src/exprs.c +++ b/src/exprs.c @@ -40,7 +40,9 @@ #include "hpc/aobjects.h" #endif +#ifdef HPCGAP struct ExprsState { +#endif /**************************************************************************** ** @@ -55,14 +57,16 @@ struct ExprsState { ** This sometimes puts in superfluous parenthesis: 2 * f( (3 + 4) ), since it ** doesn't know that a function call adds automatically parenthesis. */ -UInt PrintPrecedence; +DECL_MODULE_STATE UInt PrintPrecedence; -UInt OldPrintPrecedence; +DECL_MODULE_STATE UInt OldPrintPrecedence; +#ifdef HPCGAP }; 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); @@ -70,6 +74,7 @@ extern inline struct ExprsState * ExprsState(void) #define PrintPrecedence ExprsState()->PrintPrecedence #define OldPrintPrecedence ExprsState()->OldPrintPrecedence +#endif /**************************************************************************** ** @@ -1814,9 +1819,10 @@ static StructInitInfo module = { .name = "exprs", .initKernel = InitKernel, .initLibrary = InitLibrary, - +#ifdef HPCGAP .moduleStateSize = sizeof(struct ExprsState), .moduleStateOffsetPtr = &ExprsStateOffset, +#endif }; StructInitInfo * InitInfoExprs ( void ) diff --git a/src/finfield.c b/src/finfield.c index b2b3915c4e..5f2bdb2e69 100644 --- a/src/finfield.c +++ b/src/finfield.c @@ -597,7 +597,7 @@ static void PrFFE(Obj ffe) ** field before the addition. ** ** 'SumFFEFFE' just does the conversions mentioned above and then calls the -** macro 'SUM_FFV' to do the actual addition. +** function 'SUM_FFV' to do the actual addition. */ static Obj SUM_FFE_LARGE; @@ -642,64 +642,61 @@ static Obj SumFFEFFE(Obj opL, Obj opR) return NEW_FFE( fX, vX ); } -static Obj SumFFEInt(Obj opL, Obj opR) +static inline FFV IntToFFE(Obj op, FF fX) { - FFV vL, vR, vX; // value of left, right, result - FF fX; // field of result - Int pX; // char. of result - const FFV* sX; // successor table of result field + FFV base; + FFV res; + FFV vX; + const FFV * sX; + Int pX; - // get the field for the result - fX = FLD_FFE( opL ); pX = CHAR_FF( fX ); sX = SUCC_FF( fX ); - // get the right operand - vX = ((INT_INTOBJ( opR ) % pX) + pX) % pX; + vX = ((INT_INTOBJ(op) % pX) + pX) % pX; if ( vX == 0 ) { - vR = 0; - } - else { - vR = 1; - for ( ; 1 < vX; vX-- ) vR = sX[vR]; + return 0; } - // get the left operand - vL = VAL_FFE( opL ); - - vX = SUM_FFV( vL, vR, sX ); - return NEW_FFE( fX, vX ); + base = 1; + res = 0; + while (vX != 0) { + if (vX & 1) { + res = SUM_FFV(res, base, sX); + } + vX >>= 1; + if (vX != 0) { + base = SUM_FFV(base, base, sX); + } + } + return res; } -static Obj SumIntFFE(Obj opL, Obj opR) +static inline Obj SumFFEInt(Obj opL, Obj opR) { FFV vL, vR, vX; // value of left, right, result FF fX; // field of result - Int pX; // char. of result const FFV* sX; // successor table of result field // get the field for the result - fX = FLD_FFE( opR ); - pX = CHAR_FF( fX ); + fX = FLD_FFE( opL ); sX = SUCC_FF( fX ); - // get the left operand - vX = ((INT_INTOBJ( opL ) % pX) + pX) % pX; - if ( vX == 0 ) { - vL = 0; - } - else { - vL = 1; - for ( ; 1 < vX; vX-- ) vL = sX[vL]; - } - // get the right operand - vR = VAL_FFE( opR ); + vR = IntToFFE( opR, fX ); + + // get the left operand + vL = VAL_FFE( opL ); vX = SUM_FFV( vL, vR, sX ); return NEW_FFE( fX, vX ); } +static Obj SumIntFFE(Obj opL, Obj opR) +{ + return SumFFEInt(opR, opL); +} + /**************************************************************************** ** @@ -751,7 +748,7 @@ static Obj AInvFFE(Obj op) ** field before the subtraction. ** ** 'DiffFFEFFE' just does the conversions mentioned above and then calls the -** macros 'NEG_FFV' and 'SUM_FFV' to do the actual subtraction. +** functions 'NEG_FFV' and 'SUM_FFV' to do the actual subtraction. */ static Obj DIFF_FFE_LARGE; @@ -801,23 +798,14 @@ static Obj DiffFFEInt(Obj opL, Obj opR) { FFV vL, vR, vX; // value of left, right, result FF fX; // field of result - Int pX; // char. of result const FFV* sX; // successor table of result field // get the field for the result fX = FLD_FFE( opL ); - pX = CHAR_FF( fX ); sX = SUCC_FF( fX ); // get the right operand - vX = ((INT_INTOBJ( opR ) % pX) + pX) % pX; - if ( vX == 0 ) { - vR = 0; - } - else { - vR = 1; - for ( ; 1 < vX; vX-- ) vR = sX[vR]; - } + vR = IntToFFE( opR, fX ); // get the left operand vL = VAL_FFE( opL ); @@ -831,23 +819,14 @@ static Obj DiffIntFFE(Obj opL, Obj opR) { FFV vL, vR, vX; // value of left, right, result FF fX; // field of result - Int pX; // char. of result const FFV* sX; // successor table of result field // get the field for the result fX = FLD_FFE( opR ); - pX = CHAR_FF( fX ); sX = SUCC_FF( fX ); // get the left operand - vX = ((INT_INTOBJ( opL ) % pX) + pX) % pX; - if ( vX == 0 ) { - vL = 0; - } - else { - vL = 1; - for ( ; 1 < vX; vX-- ) vL = sX[vL]; - } + vL = IntToFFE( opL, fX ); // get the right operand vR = VAL_FFE( opR ); @@ -871,7 +850,7 @@ static Obj DiffIntFFE(Obj opL, Obj opR) ** field before the multiplication. ** ** 'ProdFFEFFE' just does the conversions mentioned above and then calls the -** macro 'PROD_FFV' to do the actual multiplication. +** function 'PROD_FFV' to do the actual multiplication. */ static Obj PROD_FFE_LARGE; @@ -916,27 +895,18 @@ static Obj ProdFFEFFE(Obj opL, Obj opR) return NEW_FFE( fX, vX ); } -static Obj ProdFFEInt(Obj opL, Obj opR) +static inline Obj ProdFFEInt(Obj opL, Obj opR) { FFV vL, vR, vX; // value of left, right, result FF fX; // field of result - Int pX; // char. of result const FFV* sX; // successor table of result field // get the field for the result fX = FLD_FFE( opL ); - pX = CHAR_FF( fX ); sX = SUCC_FF( fX ); // get the right operand - vX = ((INT_INTOBJ( opR ) % pX) + pX) % pX; - if ( vX == 0 ) { - vR = 0; - } - else { - vR = 1; - for ( ; 1 < vX; vX-- ) vR = sX[vR]; - } + vR = IntToFFE( opR, fX ); // get the left operand vL = VAL_FFE( opL ); @@ -947,31 +917,7 @@ static Obj ProdFFEInt(Obj opL, Obj opR) static Obj ProdIntFFE(Obj opL, Obj opR) { - FFV vL, vR, vX; // value of left, right, result - FF fX; // field of result - Int pX; // char. of result - const FFV* sX; // successor table of result field - - // get the field for the result - fX = FLD_FFE( opR ); - pX = CHAR_FF( fX ); - sX = SUCC_FF( fX ); - - // get the left operand - vX = ((INT_INTOBJ( opL ) % pX) + pX) % pX; - if ( vX == 0 ) { - vL = 0; - } - else { - vL = 1; - for ( ; 1 < vX; vX-- ) vL = sX[vL]; - } - - // get the right operand - vR = VAL_FFE( opR ); - - vX = PROD_FFV( vL, vR, sX ); - return NEW_FFE( fX, vX ); + return ProdFFEInt(opR, opL); } @@ -1026,7 +972,7 @@ static Obj InvFFE(Obj op) ** field before the division. ** ** 'QuoFFEFFE' just does the conversions mentioned above and then calls the -** macro 'QUO_FFV' to do the actual division. +** function 'QUO_FFV' to do the actual division. */ static Obj QUO_FFE_LARGE; @@ -1078,23 +1024,14 @@ static Obj QuoFFEInt(Obj opL, Obj opR) { FFV vL, vR, vX; // value of left, right, result FF fX; // field of result - Int pX; // char. of result const FFV* sX; // successor table of result field // get the field for the result fX = FLD_FFE( opL ); - pX = CHAR_FF( fX ); sX = SUCC_FF( fX ); // get the right operand - vX = ((INT_INTOBJ( opR ) % pX) + pX) % pX; - if ( vX == 0 ) { - vR = 0; - } - else { - vR = 1; - for ( ; 1 < vX; vX-- ) vR = sX[vR]; - } + vR = IntToFFE( opR, fX ); // get the left operand vL = VAL_FFE( opL ); @@ -1110,23 +1047,14 @@ static Obj QuoIntFFE(Obj opL, Obj opR) { FFV vL, vR, vX; // value of left, right, result FF fX; // field of result - Int pX; // char. of result const FFV* sX; // successor table of result field // get the field for the result fX = FLD_FFE( opR ); - pX = CHAR_FF( fX ); sX = SUCC_FF( fX ); // get the left operand - vX = ((INT_INTOBJ( opL ) % pX) + pX) % pX; - if ( vX == 0 ) { - vL = 0; - } - else { - vL = 1; - for ( ; 1 < vX; vX-- ) vL = sX[vL]; - } + vL = IntToFFE( opL, fX ); // get the right operand vR = VAL_FFE( opR ); @@ -1148,7 +1076,7 @@ static Obj QuoIntFFE(Obj opL, Obj opR) ** left operand is represented, even if it lies in a much smaller field. ** ** 'PowFFEInt' just does the conversions mentioned above and then calls the -** macro 'POW_FFV' to do the actual exponentiation. +** function 'POW_FFV' to do the actual exponentiation. */ static Obj PowFFEInt(Obj opL, Obj opR) { diff --git a/src/funcs.c b/src/funcs.c index 9937ad4699..4d585e5bb2 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -41,43 +41,50 @@ #endif +#ifdef HPCGAP static ModuleStateOffset FuncsStateOffset = -1; struct FuncsModuleState { - Int RecursionDepth; +#endif + DECL_MODULE_STATE Int RecursionDepth; +#ifdef HPCGAP }; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct FuncsModuleState *FuncsState(void) { return (struct FuncsModuleState *)StateSlotsAtOffset(FuncsStateOffset); } +#define RecursionDepth (FuncsState()->RecursionDepth) +#endif + Int IncRecursionDepth(void) { - int depth = ++(FuncsState()->RecursionDepth); + int depth = ++RecursionDepth; return depth; } void DecRecursionDepth(void) { - FuncsState()->RecursionDepth--; + RecursionDepth--; /* FIXME: According to a comment in the function RecursionDepthTrap below, RecursionDepth can become "slightly" negative. This needs some investigation. - GAP_ASSERT(FuncsState()->RecursionDepth >= 0); + GAP_ASSERT(RecursionDepth >= 0); */ } Int GetRecursionDepth(void) { - return FuncsState()->RecursionDepth; + return RecursionDepth; } void SetRecursionDepth(Int depth) { GAP_ASSERT(depth >= 0); - FuncsState()->RecursionDepth = depth; + RecursionDepth = depth; } /**************************************************************************** @@ -380,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); } } @@ -879,7 +885,7 @@ static Int InitKernel ( static Int InitModuleState(void) { - FuncsState()->RecursionDepth = 0; + RecursionDepth = 0; return 0; } @@ -895,9 +901,10 @@ static StructInitInfo module = { .name = "funcs", .initKernel = InitKernel, .initLibrary = InitLibrary, - +#ifdef HPCGAP .moduleStateSize = sizeof(struct FuncsModuleState), .moduleStateOffsetPtr = &FuncsStateOffset, +#endif .initModuleState = InitModuleState, }; diff --git a/src/gap.c b/src/gap.c index a2b02693be..e88bcc8711 100644 --- a/src/gap.c +++ b/src/gap.c @@ -18,10 +18,10 @@ #include "compiler.h" #include "error.h" #include "funcs.h" -#include "gapstate.h" #ifdef USE_GASMAN #include "gasman_intern.h" #endif +#include "gapstate.h" #include "gaptime.h" #include "gvars.h" #include "integer.h" @@ -123,11 +123,18 @@ static UInt Time; */ static UInt MemoryAllocated; - #ifndef HPCGAP -GAPState MainGAPState; -#endif +// HACK: include gapstate a second time, but with DECL_GAP_STATE +// defined to be empty, to root the global variables here; i.e., +// `DECL_GAP_STATE Obj Tilde;` is turned into just `Obj Tilde;` +// and so on. +#undef GAP_GAPSTATE_H +#undef DECL_GAP_STATE +#define DECL_GAP_STATE +#include "gapstate.h" + +#endif /**************************************************************************** ** @@ -402,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); @@ -418,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/gapstate.h b/src/gapstate.h index 16d74d2c8a..4cb6060d63 100644 --- a/src/gapstate.h +++ b/src/gapstate.h @@ -23,31 +23,35 @@ #include +#ifdef HPCGAP enum { STATE_SLOTS_SIZE = 32768 - 1024, }; +#define DECL_GAP_STATE + typedef struct GAPState { -#ifdef HPCGAP // TLS data -- this *must* come first, so that we can safely // cast a GAPState pointer into a ThreadLocalStorage pointer ThreadLocalStorage tls; +#elif !defined(DECL_GAP_STATE) +#define DECL_GAP_STATE extern #endif // for Boehm GC #if defined(USE_BOEHM_GC) #define MAX_GC_PREFIX_DESC 4 - void ** FreeList[MAX_GC_PREFIX_DESC + 2]; + DECL_GAP_STATE void ** FreeList[MAX_GC_PREFIX_DESC + 2]; #endif // From intrprtr.c - Obj Tilde; + DECL_GAP_STATE Obj Tilde; // The current assertion level for use in Assert - Int CurrentAssertionLevel; + DECL_GAP_STATE Int CurrentAssertionLevel; // From gvar.c - Obj CurrNamespace; + DECL_GAP_STATE Obj CurrNamespace; // From vars.c @@ -57,19 +61,19 @@ typedef struct GAPState { // Assignments to the local variables change this bag. We do not call // 'CHANGED_BAG' for each of such change. Instead we wait until a garbage // collection begins and then call 'CHANGED_BAG' in 'BeginCollectBags'. - Bag CurrLVars; + DECL_GAP_STATE Bag CurrLVars; // 'PtrLVars' is a pointer to the 'STATE(CurrLVars)' bag. This makes it // faster to access local variables. // // Since a garbage collection may move this bag around, the pointer // 'PtrLVars' must be recalculated afterwards in 'VarsAfterCollectBags'. - Obj * PtrLVars; + DECL_GAP_STATE Obj * PtrLVars; - Bag LVarsPool[16]; + DECL_GAP_STATE Bag LVarsPool[16]; // From read.c - jmp_buf ReadJmpError; + DECL_GAP_STATE jmp_buf ReadJmpError; // 'Prompt' holds the string that is to be printed if a new line is read // from the interactive files '*stdin*' or '*errin*'. @@ -77,19 +81,19 @@ typedef struct GAPState { // It is set to 'gap> ' or 'brk> ' in the read-eval-print loops and // changed to the partial prompt '> ' in 'Read' after the first symbol is // read. - char Prompt[80]; + DECL_GAP_STATE char Prompt[80]; // From stats.c // `ReturnObjStat` is the result of the return-statement that was last // executed. It is set in `ExecReturnObj` and used in the handlers that // interpret functions. - Obj ReturnObjStat; + DECL_GAP_STATE Obj ReturnObjStat; - ExecStatFunc * CurrExecStatFuncs; + DECL_GAP_STATE ExecStatFunc * CurrExecStatFuncs; // From code.c - void * PtrBody; + DECL_GAP_STATE void * PtrBody; // From opers.c #ifdef HPCGAP @@ -99,36 +103,37 @@ typedef struct GAPState { #endif // for use by GAP_TRY / GAP_CATCH and related code - int TryCatchDepth; + DECL_GAP_STATE int TryCatchDepth; // Set by `FuncJUMP_TO_CATCH` to the value of its second argument, and // and then later extracted by `CALL_WITH_CATCH`. Not currently used by // the GAP kernel itself, as far as I can tell. - Obj ThrownObject; + DECL_GAP_STATE Obj ThrownObject; // Set to TRUE when a read-eval-loop encounters a `quit` statement. - BOOL UserHasQuit; + DECL_GAP_STATE BOOL UserHasQuit; // Set to TRUE when a read-eval-loop encounters a `QUIT` statement. - BOOL UserHasQUIT; + DECL_GAP_STATE BOOL UserHasQUIT; // Set by the primary read-eval loop in `FuncSHELL`, based on the value of // `ErrorLLevel`. Also, `ReadEvalCommand` saves and restores this value // before executing code. - Obj ErrorLVars; + DECL_GAP_STATE Obj ErrorLVars; // Records where on the stack `ErrorLVars` is relative to the top; this is // modified by `FuncDownEnv` / `FuncUpEnv`, and ultimately used and // controlled by the primary read-eval loop in `FuncSHELL`. - Int ErrorLLevel; + DECL_GAP_STATE Int ErrorLLevel; // This callback is called in FuncJUMP_TO_CATCH, this is not used by GAP // itself but by programs that use GAP as a library to handle errors - void (*JumpToCatchCallback)(void); + DECL_GAP_STATE void (*JumpToCatchCallback)(void); // From info.c - Int ShowUsedInfoClassesActive; + DECL_GAP_STATE Int ShowUsedInfoClassesActive; +#ifdef HPCGAP UInt1 StateSlots[STATE_SLOTS_SIZE]; } GAPState; @@ -136,26 +141,25 @@ typedef struct GAPState { // so that all its members can be access with a 16 bit signed offset GAP_STATIC_ASSERT(sizeof(GAPState) < 32768, "GAPState is too big"); -#ifdef HPCGAP +#define DECL_MODULE_STATE EXPORT_INLINE GAPState * ActiveGAPState(void) { return (GAPState *)GetTLS(); } +#define STATE(x) (ActiveGAPState()->x) + #else -extern GAPState MainGAPState; +#define DECL_MODULE_STATE static -EXPORT_INLINE GAPState * ActiveGAPState(void) -{ - return &MainGAPState; -} +#define STATE(x) (x) #endif -#define STATE(x) (ActiveGAPState()->x) +#ifdef HPCGAP // Offset into StateSlots typedef Int ModuleStateOffset; @@ -167,7 +171,9 @@ EXPORT_INLINE void * StateSlotsAtOffset(ModuleStateOffset offset) } // Access a module's registered state -#define MODULE_STATE(module) \ - (*(module ## ModuleState *)StateSlotsAtOffset(module ## StateOffset)) +#define MODULE_STATE(module, ident) \ + (((module ## ModuleState *)StateSlotsAtOffset(module ## StateOffset))->ident) + +#endif #endif // GAP_GAPSTATE_H 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 d3d24163a8..eac2600859 100644 --- a/src/io.c +++ b/src/io.c @@ -74,65 +74,73 @@ static Obj SetPrintFormattingStatus; static Obj FilenameCache; static SymbolTable FilenameSymbolTable; -static ModuleStateOffset IOStateOffset = -1; - enum { MAX_OPEN_FILES = 16, }; +#ifdef HPCGAP +static ModuleStateOffset IOStateOffset = -1; + struct IOModuleState { +#endif // A pointer to the current input file - TypInputFile * Input; + DECL_MODULE_STATE TypInputFile * Input; // A pointer to the current output file. It points to the top of the // stack 'OutputFiles'. - TypOutputFile * Output; + DECL_MODULE_STATE TypOutputFile * Output; // - TypOutputFile * IgnoreStdoutErrout; + DECL_MODULE_STATE TypOutputFile * IgnoreStdoutErrout; // The file identifier of the current input logfile. If it is not 0 the // scanner echoes all input from the files '*stdin*' and '*errin*' to // this file. - TypOutputFile * InputLog; + DECL_MODULE_STATE TypOutputFile * InputLog; // The file identifier of the current output logfile. If it is not 0 the // scanner echoes all output to the files '*stdout*' and '*errout*' to // this file. - TypOutputFile * OutputLog; + DECL_MODULE_STATE TypOutputFile * OutputLog; - TypOutputFile InputLogFileOrStream; - TypOutputFile OutputLogFileOrStream; + DECL_MODULE_STATE TypOutputFile InputLogFileOrStream; + DECL_MODULE_STATE TypOutputFile OutputLogFileOrStream; - TypOutputFile DefaultOutput; + DECL_MODULE_STATE TypOutputFile DefaultOutput; #ifdef HPCGAP - Obj DefaultOutputStream; - Obj DefaultInputStream; + DECL_MODULE_STATE Obj DefaultOutputStream; + DECL_MODULE_STATE Obj DefaultInputStream; #endif - Int NoSplitLine; + DECL_MODULE_STATE Int NoSplitLine; - BOOL PrintFormattingForStdout; - BOOL PrintFormattingForErrout; + DECL_MODULE_STATE BOOL PrintFormattingForStdout; + DECL_MODULE_STATE BOOL PrintFormattingForErrout; +#ifdef HPCGAP }; // for debugging from GDB / lldb, we mark this as extern inline -extern inline struct IOModuleState * IO(void) +extern inline struct IOModuleState * IOHelper(void) { return (struct IOModuleState *)StateSlotsAtOffset(IOStateOffset); } +#define IO(x) (IOHelper()->x) +#else +#define IO(x) (x) +#endif + void LockCurrentOutput(BOOL lock) { - IO()->IgnoreStdoutErrout = lock ? IO()->Output : NULL; + IO(IgnoreStdoutErrout) = lock ? IO(Output) : NULL; } TypInputFile * GetCurrentInput(void) { - return IO()->Input; + return IO(Input); } /**************************************************************************** @@ -279,7 +287,7 @@ static GVarDescriptor DEFAULT_OUTPUT_STREAM; static UInt OpenDefaultInput(TypInputFile * input) { Obj func, stream; - stream = IO()->DefaultInputStream; + stream = IO(DefaultInputStream); if (stream) return OpenInputStream(input, stream, FALSE); func = GVarOptFunction(&DEFAULT_INPUT_STREAM); @@ -290,14 +298,14 @@ static UInt OpenDefaultInput(TypInputFile * input) ErrorQuit("DEFAULT_INPUT_STREAM() did not return a stream", 0, 0); if (IsStringConv(stream)) return OpenInput(input, CONST_CSTR_STRING(stream)); - IO()->DefaultInputStream = stream; + IO(DefaultInputStream) = stream; return OpenInputStream(input, stream, FALSE); } static UInt OpenDefaultOutput(TypOutputFile * output) { Obj func, stream; - stream = IO()->DefaultOutputStream; + stream = IO(DefaultOutputStream); if (stream) return OpenOutputStream(output, stream); func = GVarOptFunction(&DEFAULT_OUTPUT_STREAM); @@ -308,7 +316,7 @@ static UInt OpenDefaultOutput(TypOutputFile * output) ErrorQuit("DEFAULT_OUTPUT_STREAM() did not return a stream", 0, 0); if (IsStringConv(stream)) return OpenOutput(output, CONST_CSTR_STRING(stream), FALSE); - IO()->DefaultOutputStream = stream; + IO(DefaultOutputStream) = stream; return OpenOutputStream(output, stream); } #endif @@ -353,7 +361,7 @@ UInt OpenInput(TypInputFile * input, const Char * filename) /* Handle *defin*; redirect *errin* to *defin* if the default * channel is already open. */ if (streq(filename, "*defin*") || - (streq(filename, "*errin*") && IO()->DefaultInputStream)) + (streq(filename, "*errin*") && IO(DefaultInputStream))) return OpenDefaultInput(input); #endif @@ -367,7 +375,7 @@ UInt OpenInput(TypInputFile * input, const Char * filename) // paranoia: fill with garbage, to verify we initialize everything memset(input, 0x47, sizeof(TypInputFile)); #endif - input->prev = IO()->Input; + input->prev = IO(Input); input->stream = 0; input->file = file; @@ -386,7 +394,7 @@ UInt OpenInput(TypInputFile * input, const Char * filename) input->number = 1; input->lastErrorLine = 0; - IO()->Input = input; + IO(Input) = input; // indicate success return 1; @@ -408,7 +416,7 @@ UInt OpenInputStream(TypInputFile * input, Obj stream, BOOL echo) // paranoia: fill with garbage, to verify we initialize everything memset(input, 0x47, sizeof(TypInputFile)); #endif - input->prev = IO()->Input; + input->prev = IO(Input); input->stream = stream; input->file = -1; input->isstringstream = (CALL_1ARGS(IsInputStringStream, stream) == True); @@ -429,7 +437,7 @@ UInt OpenInputStream(TypInputFile * input, Obj stream, BOOL echo) input->number = 1; input->lastErrorLine = 0; - IO()->Input = input; + IO(Input) = input; // indicate success return 1; @@ -454,16 +462,16 @@ UInt OpenInputStream(TypInputFile * input, Obj stream, BOOL echo) UInt CloseInput(TypInputFile * input) { GAP_ASSERT(input); - GAP_ASSERT(input == IO()->Input); + GAP_ASSERT(input == IO(Input)); // revert to previous input - IO()->Input = input->prev; + IO(Input) = input->prev; if (input->stream) { // 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; @@ -515,17 +523,17 @@ UInt OpenLog ( { // refuse to open a logfile if we already log to one - if (IO()->InputLog != 0 || IO()->OutputLog != 0) + if (IO(InputLog) != 0 || IO(OutputLog) != 0) return 0; // try to open the file - IO()->OutputLogFileOrStream.file = SyFopen(filename, "w", FALSE); - IO()->OutputLogFileOrStream.stream = 0; - if (IO()->OutputLogFileOrStream.file == -1) + IO(OutputLogFileOrStream).file = SyFopen(filename, "w", FALSE); + IO(OutputLogFileOrStream).stream = 0; + if (IO(OutputLogFileOrStream).file == -1) return 0; - IO()->InputLog = &IO()->OutputLogFileOrStream; - IO()->OutputLog = &IO()->OutputLogFileOrStream; + IO(InputLog) = &IO(OutputLogFileOrStream); + IO(OutputLog) = &IO(OutputLogFileOrStream); // otherwise indicate success return 1; @@ -543,15 +551,15 @@ UInt OpenLogStream ( { // refuse to open a logfile if we already log to one - if (IO()->InputLog != 0 || IO()->OutputLog != 0) + if (IO(InputLog) != 0 || IO(OutputLog) != 0) return 0; // try to open the file - IO()->OutputLogFileOrStream.stream = stream; - IO()->OutputLogFileOrStream.file = -1; + IO(OutputLogFileOrStream).stream = stream; + IO(OutputLogFileOrStream).file = -1; - IO()->InputLog = &IO()->OutputLogFileOrStream; - IO()->OutputLog = &IO()->OutputLogFileOrStream; + IO(InputLog) = &IO(OutputLogFileOrStream); + IO(OutputLog) = &IO(OutputLogFileOrStream); // otherwise indicate success return 1; @@ -572,16 +580,16 @@ UInt OpenLogStream ( UInt CloseLog ( void ) { // refuse to close a non existent logfile - if (IO()->InputLog == 0 || IO()->OutputLog == 0 || - IO()->InputLog != IO()->OutputLog) + if (IO(InputLog) == 0 || IO(OutputLog) == 0 || + IO(InputLog) != IO(OutputLog)) return 0; // close the logfile - if (!IO()->InputLog->stream) { - SyFclose(IO()->InputLog->file); + if (!IO(InputLog)->stream) { + SyFclose(IO(InputLog)->file); } - IO()->InputLog = 0; - IO()->OutputLog = 0; + IO(InputLog) = 0; + IO(OutputLog) = 0; // indicate success return 1; @@ -608,16 +616,16 @@ UInt OpenInputLog ( { // refuse to open a logfile if we already log to one - if (IO()->InputLog != 0) + if (IO(InputLog) != 0) return 0; // try to open the file - IO()->InputLogFileOrStream.file = SyFopen(filename, "w", FALSE); - IO()->InputLogFileOrStream.stream = 0; - if (IO()->InputLogFileOrStream.file == -1) + IO(InputLogFileOrStream).file = SyFopen(filename, "w", FALSE); + IO(InputLogFileOrStream).stream = 0; + if (IO(InputLogFileOrStream).file == -1) return 0; - IO()->InputLog = &IO()->InputLogFileOrStream; + IO(InputLog) = &IO(InputLogFileOrStream); // otherwise indicate success return 1; @@ -635,14 +643,14 @@ UInt OpenInputLogStream ( { // refuse to open a logfile if we already log to one - if (IO()->InputLog != 0) + if (IO(InputLog) != 0) return 0; // try to open the file - IO()->InputLogFileOrStream.stream = stream; - IO()->InputLogFileOrStream.file = -1; + IO(InputLogFileOrStream).stream = stream; + IO(InputLogFileOrStream).file = -1; - IO()->InputLog = &IO()->InputLogFileOrStream; + IO(InputLog) = &IO(InputLogFileOrStream); // otherwise indicate success return 1; @@ -663,19 +671,19 @@ UInt OpenInputLogStream ( UInt CloseInputLog ( void ) { // refuse to close a non existent logfile - if (IO()->InputLog == 0) + if (IO(InputLog) == 0) return 0; // refuse to close a log opened with LogTo - if (IO()->InputLog == IO()->OutputLog) + if (IO(InputLog) == IO(OutputLog)) return 0; // close the logfile - if (!IO()->InputLog->stream) { - SyFclose(IO()->InputLog->file); + if (!IO(InputLog)->stream) { + SyFclose(IO(InputLog)->file); } - IO()->InputLog = 0; + IO(InputLog) = 0; // indicate success return 1; @@ -702,17 +710,17 @@ UInt OpenOutputLog ( { // refuse to open a logfile if we already log to one - if (IO()->OutputLog != 0) + if (IO(OutputLog) != 0) return 0; // try to open the file - memset(&IO()->OutputLogFileOrStream, 0, sizeof(TypOutputFile)); - IO()->OutputLogFileOrStream.stream = 0; - IO()->OutputLogFileOrStream.file = SyFopen(filename, "w", FALSE); - if (IO()->OutputLogFileOrStream.file == -1) + memset(&IO(OutputLogFileOrStream), 0, sizeof(TypOutputFile)); + IO(OutputLogFileOrStream).stream = 0; + IO(OutputLogFileOrStream).file = SyFopen(filename, "w", FALSE); + if (IO(OutputLogFileOrStream).file == -1) return 0; - IO()->OutputLog = &IO()->OutputLogFileOrStream; + IO(OutputLog) = &IO(OutputLogFileOrStream); // otherwise indicate success return 1; @@ -730,15 +738,15 @@ UInt OpenOutputLogStream ( { // refuse to open a logfile if we already log to one - if (IO()->OutputLog != 0) + if (IO(OutputLog) != 0) return 0; // try to open the file - memset(&IO()->OutputLogFileOrStream, 0, sizeof(TypOutputFile)); - IO()->OutputLogFileOrStream.stream = stream; - IO()->OutputLogFileOrStream.file = -1; + memset(&IO(OutputLogFileOrStream), 0, sizeof(TypOutputFile)); + IO(OutputLogFileOrStream).stream = stream; + IO(OutputLogFileOrStream).file = -1; - IO()->OutputLog = &IO()->OutputLogFileOrStream; + IO(OutputLog) = &IO(OutputLogFileOrStream); // otherwise indicate success return 1; @@ -759,19 +767,19 @@ UInt OpenOutputLogStream ( UInt CloseOutputLog ( void ) { // refuse to close a non existent logfile - if (IO()->OutputLog == 0) + if (IO(OutputLog) == 0) return 0; // refuse to close a log opened with LogTo - if (IO()->OutputLog == IO()->InputLog) + if (IO(OutputLog) == IO(InputLog)) return 0; // close the logfile - if (!IO()->OutputLog->stream) { - SyFclose(IO()->OutputLog->file); + if (!IO(OutputLog)->stream) { + SyFclose(IO(OutputLog)->file); } - IO()->OutputLog = 0; + IO(OutputLog) = 0; // indicate success return 1; @@ -816,7 +824,7 @@ UInt OpenOutput(TypOutputFile * output, const Char * filename, BOOL append) GAP_ASSERT(output); // do nothing for stdout and errout if caught - if (IO()->Output != NULL && IO()->IgnoreStdoutErrout == IO()->Output && + if (IO(Output) != NULL && IO(IgnoreStdoutErrout) == IO(Output) && (streq(filename, "*errout*") || streq(filename, "*stdout*"))) { return 1; } @@ -839,17 +847,17 @@ UInt OpenOutput(TypOutputFile * output, const Char * filename, BOOL append) // paranoia: fill with garbage, to verify we initialize everything memset(output, 0x47, sizeof(TypOutputFile)); #endif - output->prev = IO()->Output; - IO()->Output = output; + output->prev = IO(Output); + IO(Output) = output; output->isstringstream = FALSE; output->stream = 0; output->file = file; output->line[0] = '\0'; output->pos = 0; if (streq(filename, "*stdout*")) - output->format = IO()->PrintFormattingForStdout; + output->format = IO(PrintFormattingForStdout); else if (streq(filename, "*errout*")) - output->format = IO()->PrintFormattingForErrout; + output->format = IO(PrintFormattingForErrout); else output->format = TRUE; output->indent = 0; @@ -879,8 +887,8 @@ UInt OpenOutputStream(TypOutputFile * output, Obj stream) // paranoia: fill with garbage, to verify we initialize everything memset(output, 0x47, sizeof(TypOutputFile)); #endif - output->prev = IO()->Output; - IO()->Output = output; + output->prev = IO(Output); + IO(Output) = output; output->isstringstream = (CALL_1ARGS(IsOutputStringStream, stream) == True); output->stream = stream; output->file = -1; @@ -921,15 +929,15 @@ UInt CloseOutput(TypOutputFile * output) // silently refuse to close the test output file; this is probably an // attempt to close *errout* which is silently not opened, so let's // silently not close it - if (IO()->IgnoreStdoutErrout == IO()->Output) + if (IO(IgnoreStdoutErrout) == IO(Output)) return 1; - GAP_ASSERT(output == IO()->Output); + GAP_ASSERT(output == IO(Output)); // refuse to close the initial output file '*stdout*' #ifdef HPCGAP if (output->prev == 0 && output->stream && - IO()->DefaultOutputStream == output->stream) + IO(DefaultOutputStream) == output->stream) return 0; #else if (output->prev == 0) @@ -943,7 +951,7 @@ UInt CloseOutput(TypOutputFile * output) } // revert to previous output file and indicate success - IO()->Output = output->prev; + IO(Output) = output->prev; // don't keep GAP objects alive unnecessarily output->stream = 0; @@ -1068,7 +1076,7 @@ static Char GetLine(TypInputFile * input) Pr("%c", (Int)'\03', 0); } else if (input->file == 0 || input->file == 2) { - if (IO()->Output->pos > 0) + if (IO(Output)->pos > 0) Pr("\n", 0, 0); if ( PrintPromptHook ) Call0ArgsInNewReader( PrintPromptHook ); @@ -1095,9 +1103,9 @@ static Char GetLine(TypInputFile * input) } // if necessary echo the line to the logfile - if (IO()->InputLog != 0 && input->echo == 1) + if (IO(InputLog) != 0 && input->echo == 1) if (!(input->ptr[0] == '\377' && input->ptr[1] == '\0')) - PutLine2(IO()->InputLog, input->ptr, strlen(input->ptr)); + PutLine2(IO(InputLog), input->ptr, strlen(input->ptr)); // return the current character return *input->ptr; @@ -1156,9 +1164,9 @@ static void PutLineTo(TypOutputFile * stream, UInt len) PutLine2( stream, stream->line, len ); // if necessary echo it to the logfile - if (IO()->OutputLog != 0 && !stream->stream) { + if (IO(OutputLog) != 0 && !stream->stream) { if (stream->file == 1 || stream->file == 3) { - PutLine2(IO()->OutputLog, stream->line, len); + PutLine2(IO(OutputLog), stream->line, len); } } } @@ -1298,9 +1306,9 @@ static void PutChrTo(TypOutputFile * stream, Char ch) /* TODO: For threads other than the main thread, reserve some extra space for the thread id indicator. See issue #136. */ else if (stream->pos < - SyNrCols - 2 - 6 * (TLS(threadID) != 0) - IO()->NoSplitLine) { + SyNrCols - 2 - 6 * (TLS(threadID) != 0) - IO(NoSplitLine)) { #else - else if (stream->pos < SyNrCols - 2 - IO()->NoSplitLine) { + else if (stream->pos < SyNrCols - 2 - IO(NoSplitLine)) { #endif // put the character on this line @@ -1390,7 +1398,7 @@ static void PutChrTo(TypOutputFile * stream, Char ch) */ static Obj FuncToggleEcho(Obj self) { - IO()->Input->echo = !IO()->Input->echo; + IO(Input)->echo = !IO(Input)->echo; return (Obj)0; } @@ -1428,8 +1436,8 @@ static Obj FuncPRINT_CPROMPT(Obj self, Obj prompt) void ResetOutputIndent(void) { - GAP_ASSERT(IO()->Output); - IO()->Output->indent = 0; + GAP_ASSERT(IO(Output)); + IO(Output)->indent = 0; } @@ -1505,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. @@ -1548,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'); @@ -1558,6 +1564,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%d' print an integer @@ -1583,6 +1590,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%s' or '%g' print a string @@ -1625,14 +1633,14 @@ static inline void FormatOutput( // with null bytes, behavior of 'prec' is undefined. if (*q == '\0') continue; - if (*q == '\\' && IO()->NoSplitLine == 0) { + if (*q == '\\' && IO(NoSplitLine) == 0) { if (*(q + 1) < '8' && *(q + 1) >= '0') - IO()->NoSplitLine = 3; + IO(NoSplitLine) = 3; else - IO()->NoSplitLine = 1; + IO(NoSplitLine) = 1; } - else if (IO()->NoSplitLine > 0) - IO()->NoSplitLine--; + else if (IO(NoSplitLine) > 0) + IO(NoSplitLine)--; put_a_char(state, *q); if (arg1obj) { @@ -1642,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 @@ -1691,6 +1700,7 @@ static inline void FormatOutput( // on to the next argument arg1 = arg2; + arg2 = 0; } // '%I' print an identifier @@ -1734,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 @@ -1788,11 +1800,11 @@ void Pr ( Int arg2 ) { #ifdef HPCGAP - if (!IO()->Output) { - OpenDefaultOutput(&IO()->DefaultOutput); + if (!IO(Output)) { + OpenDefaultOutput(&IO(DefaultOutput)); } #endif - PrTo(IO()->Output, format, arg1, arg2); + PrTo(IO(Output), format, arg1, arg2); } typedef struct { @@ -1818,52 +1830,52 @@ void SPrTo(Char *buffer, UInt maxlen, const Char *format, Int arg1, Int arg2) static Obj FuncINPUT_FILENAME(Obj self) { - if (IO()->Input == 0) + if (IO(Input) == 0) return MakeImmString("*defin*"); - UInt gapnameid = GetInputFilenameID(IO()->Input); + UInt gapnameid = GetInputFilenameID(IO(Input)); return GetCachedFilename(gapnameid); } static Obj FuncINPUT_LINENUMBER(Obj self) { - return INTOBJ_INT(IO()->Input ? IO()->Input->number : 0); + return INTOBJ_INT(IO(Input) ? IO(Input)->number : 0); } static Obj FuncSET_PRINT_FORMATTING_STDOUT(Obj self, Obj val) { BOOL format = (val != False); - TypOutputFile * output = IO()->Output; + TypOutputFile * output = IO(Output); while (output) { if (!output->stream && output->file == 1) output->format = format; output = output->prev; } - IO()->PrintFormattingForStdout = format; + IO(PrintFormattingForStdout) = format; return 0; } static Obj FuncPRINT_FORMATTING_STDOUT(Obj self) { - return IO()->PrintFormattingForStdout ? True : False; + return IO(PrintFormattingForStdout) ? True : False; } static Obj FuncSET_PRINT_FORMATTING_ERROUT(Obj self, Obj val) { BOOL format = (val != False); - TypOutputFile * output = IO()->Output; + TypOutputFile * output = IO(Output); while (output) { if (!output->stream && output->file == 3) output->format = format; output = output->prev; } - IO()->PrintFormattingForErrout = format; + IO(PrintFormattingForErrout) = format; return 0; } static Obj FuncPRINT_FORMATTING_ERROUT(Obj self) { - return IO()->PrintFormattingForErrout ? True : False; + return IO(PrintFormattingForErrout) ? True : False; } /**************************************************************************** @@ -1878,7 +1890,7 @@ static Obj FuncCALL_WITH_FORMATTING_STATUS(Obj self, Obj status, Obj func, Obj a RequireTrueOrFalse(SELF_NAME, status); RequireSmallList(SELF_NAME, args); - TypOutputFile * output = IO()->Output; + TypOutputFile * output = IO(Output); if (!output) ErrorMayQuit("CALL_WITH_FORMATTING_STATUS called while no output is open", 0, 0); @@ -1902,18 +1914,18 @@ static Obj FuncCALL_WITH_FORMATTING_STATUS(Obj self, Obj status, Obj func, Obj a static Obj FuncIS_INPUT_TTY(Obj self) { - GAP_ASSERT(IO()->Input); - if (IO()->Input->stream) + GAP_ASSERT(IO(Input)); + if (IO(Input)->stream) return False; - return SyBufIsTTY(IO()->Input->file) ? True : False; + return SyBufIsTTY(IO(Input)->file) ? True : False; } static Obj FuncIS_OUTPUT_TTY(Obj self) { - GAP_ASSERT(IO()->Output); - if (IO()->Output->stream) + GAP_ASSERT(IO(Output)); + if (IO(Output)->stream) return False; - return SyBufIsTTY(IO()->Output->file) ? True : False; + return SyBufIsTTY(IO(Output)->file) ? True : False; } static Obj FuncGET_FILENAME_CACHE(Obj self) @@ -1960,14 +1972,14 @@ static Int InitLibrary ( static Int InitKernel ( StructInitInfo * module ) { - IO()->Input = 0; - IO()->Output = 0; - IO()->InputLog = 0; - IO()->OutputLog = 0; - IO()->PrintFormattingForStdout = TRUE; - IO()->PrintFormattingForErrout = TRUE; + IO(Input) = 0; + IO(Output) = 0; + IO(InputLog) = 0; + IO(OutputLog) = 0; + IO(PrintFormattingForStdout) = TRUE; + IO(PrintFormattingForErrout) = TRUE; - OpenOutput(&IO()->DefaultOutput, "*stdout*", FALSE); + OpenOutput(&IO(DefaultOutput), "*stdout*", FALSE); InitSymbolTableKernel(&FilenameSymbolTable, "FilenameSymbolCount", "FilenameSymbolTable", GetCachedFilename, @@ -1982,9 +1994,9 @@ static Int InitKernel ( #else // register global bags with the garbage collector - InitGlobalBag(&(IO()->InputLogFileOrStream.stream), + InitGlobalBag(&(IO(InputLogFileOrStream).stream), "src/io.c:InputLogFileOrStream"); - InitGlobalBag(&(IO()->OutputLogFileOrStream.stream), + InitGlobalBag(&(IO(OutputLogFileOrStream).stream), "src/io.c:OutputLogFileOrStream"); #endif @@ -2014,9 +2026,10 @@ static StructInitInfo module = { .name = "io", .initKernel = InitKernel, .initLibrary = InitLibrary, - +#ifdef HPCGAP .moduleStateSize = sizeof(struct IOModuleState), .moduleStateOffsetPtr = &IOStateOffset, +#endif }; StructInitInfo * InitInfoIO ( void ) 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/listoper.c b/src/listoper.c index a30e7b7af9..08ef0484b9 100644 --- a/src/listoper.c +++ b/src/listoper.c @@ -1758,8 +1758,8 @@ FuncADD_TO_LIST_ENTRIES_PLIST_RANGE(Obj self, Obj list, Obj range, Obj x) ** ** Examples: x^2y^3 < y^7, x^4 y^5 < x^3 y^6 */ -static Obj FuncMONOM_TOT_DEG_LEX ( Obj self, Obj u, Obj v ) { - +static Obj FuncMONOM_TOT_DEG_LEX(Obj self, Obj u, Obj v) +{ Int4 i, lu, lv; Obj total; @@ -1835,8 +1835,8 @@ static Obj FuncMONOM_TOT_DEG_LEX ( Obj self, Obj u, Obj v ) { ** ** Examples: x^2y^3 < y^7, x^4 y^5 < x^3 y^6 */ -static Obj FuncMONOM_GRLEX( Obj self, Obj u, Obj v ) { - +static Obj FuncMONOM_GRLEX(Obj self, Obj u, Obj v) +{ Int4 i, lu, lv; Obj total,ai,bi; @@ -1902,8 +1902,8 @@ static Obj FuncMONOM_GRLEX( Obj self, Obj u, Obj v ) { ** representation. This is time critical and thus in the kernel. ** the function assumes that all lists are plists. */ -static Obj FuncZIPPED_SUM_LISTS( Obj self, Obj z1, Obj z2, Obj zero, Obj f ) { - +static Obj FuncZIPPED_SUM_LISTS(Obj self, Obj z1, Obj z2, Obj zero, Obj f) +{ Int l1,l2,i; Int i1,i2; Obj sum,x,y; @@ -1981,8 +1981,8 @@ static Obj FuncZIPPED_SUM_LISTS( Obj self, Obj z1, Obj z2, Obj zero, Obj f ) { ** implements the multiplication of monomials. Both must be plain lists ** of integers. */ -static Obj FuncMONOM_PROD( Obj self, Obj m1, Obj m2 ) { - +static Obj FuncMONOM_PROD(Obj self, Obj m1, Obj m2) +{ UInt a,b,l1,l2,i1,i2,i; Obj e,f,c,prod; 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/modules.c b/src/modules.c index 5b7a0f832c..6b1b689c6b 100644 --- a/src/modules.c +++ b/src/modules.c @@ -97,6 +97,8 @@ static Int NrImportedGVars; static StructImportedGVars ImportedFuncs[MAX_IMPORTED_GVARS]; static Int NrImportedFuncs; +#ifdef HPCGAP + static Int StateNextFreeOffset = 0; // Start of next free memory area (as offset into GAPState.StateSlots) static void RegisterModuleState(StructInitInfo * info) @@ -123,6 +125,7 @@ static void RegisterModuleState(StructInitInfo * info) StateNextFreeOffset = (StateNextFreeOffset + sizeof(Obj)-1) & ~(sizeof(Obj)-1); } +#endif /************************************************************************* ** @@ -149,7 +152,9 @@ Int ActivateModule(StructInitInfo * info) { Int res = 0; +#ifdef HPCGAP RegisterModuleState(info); +#endif if (info->initKernel) { res = info->initKernel(info); @@ -941,7 +946,9 @@ void ModulesSetup(void) fputs(")\n", stderr); } +#ifdef HPCGAP RegisterModuleState(info); +#endif } NrBuiltinModules = NrModules; } diff --git a/src/modules.h b/src/modules.h index def31697c2..1c21120aed 100644 --- a/src/modules.h +++ b/src/modules.h @@ -90,12 +90,18 @@ struct init_info { // function to call after restoring workspace Int (*postRestore)(StructInitInfo *); +#ifdef HPCGAP // number of bytes this module needs for its per-thread module state + // Only used in HPC-GAP, but not behind an #ifdef guard to avoid API + // breakage for C++ kernel extensions UInt moduleStateSize; // if this is not zero, then the module state offset is stored into // the address this points at + // Only used in HPC-GAP, but not behind an #ifdef guard to avoid API + // breakage for C++ kernel extensions Int * moduleStateOffsetPtr; +#endif // initialize thread local module state Int (*initModuleState)(void); diff --git a/src/objcftl.c b/src/objcftl.c index 557827816f..83adcc9b13 100644 --- a/src/objcftl.c +++ b/src/objcftl.c @@ -32,20 +32,30 @@ #include "plist.h" +#ifdef HPCGAP static ModuleStateOffset CFTLStateOffset = -1; struct CFTLModuleState { - Obj WORD_STACK; - Obj WORD_EXPONENT_STACK; - Obj SYLLABLE_STACK; - Obj EXPONENT_STACK; +#endif + DECL_MODULE_STATE Obj WORD_STACK; + DECL_MODULE_STATE Obj WORD_EXPONENT_STACK; + DECL_MODULE_STATE Obj SYLLABLE_STACK; + DECL_MODULE_STATE Obj EXPONENT_STACK; +#ifdef HPCGAP }; +// for debugging from GDB / lldb, we mark this as extern inline extern inline struct CFTLModuleState *CFTLState(void) { return (struct CFTLModuleState *)StateSlotsAtOffset(CFTLStateOffset); } +#define WORD_STACK (CFTLState()->WORD_STACK) +#define WORD_EXPONENT_STACK (CFTLState()->WORD_EXPONENT_STACK) +#define SYLLABLE_STACK (CFTLState()->SYLLABLE_STACK) +#define EXPONENT_STACK (CFTLState()->EXPONENT_STACK) +#endif + static inline Obj IncInt(Obj x) { if (IS_INTOBJ(x) && x != INTOBJ_MAX) { @@ -133,10 +143,10 @@ static Obj CollectPolycyc(Obj pcp, Obj list, Obj word) Obj ipow = CONST_ADDR_OBJ(pcp)[ PC_INVERSEPOWERS ]; Obj exp = CONST_ADDR_OBJ(pcp)[ PC_EXPONENTS ]; - Obj wst = CFTLState()->WORD_STACK; - Obj west = CFTLState()->WORD_EXPONENT_STACK; - Obj sst = CFTLState()->SYLLABLE_STACK; - Obj est = CFTLState()->EXPONENT_STACK; + Obj wst = WORD_STACK; + Obj west = WORD_EXPONENT_STACK; + Obj sst = SYLLABLE_STACK; + Obj est = EXPONENT_STACK; Obj conj=0, iconj=0; /*QQ initialize to please compiler */ @@ -411,15 +421,15 @@ static Int InitLibrary ( static Int InitModuleState(void) { - InitGlobalBag( &CFTLState()->WORD_STACK, "WORD_STACK" ); - InitGlobalBag( &CFTLState()->WORD_EXPONENT_STACK, "WORD_EXPONENT_STACK" ); - InitGlobalBag( &CFTLState()->SYLLABLE_STACK, "SYLLABLE_STACK" ); - InitGlobalBag( &CFTLState()->EXPONENT_STACK, "EXPONENT_STACK" ); + InitGlobalBag( &WORD_STACK, "WORD_STACK" ); + InitGlobalBag( &WORD_EXPONENT_STACK, "WORD_EXPONENT_STACK" ); + InitGlobalBag( &SYLLABLE_STACK, "SYLLABLE_STACK" ); + InitGlobalBag( &EXPONENT_STACK, "EXPONENT_STACK" ); - CFTLState()->WORD_STACK = NEW_PLIST( T_PLIST, 4096 ); - CFTLState()->WORD_EXPONENT_STACK = NEW_PLIST( T_PLIST, 4096 ); - CFTLState()->SYLLABLE_STACK = NEW_PLIST( T_PLIST, 4096 ); - CFTLState()->EXPONENT_STACK = NEW_PLIST( T_PLIST, 4096 ); + WORD_STACK = NEW_PLIST( T_PLIST, 4096 ); + WORD_EXPONENT_STACK = NEW_PLIST( T_PLIST, 4096 ); + SYLLABLE_STACK = NEW_PLIST( T_PLIST, 4096 ); + EXPONENT_STACK = NEW_PLIST( T_PLIST, 4096 ); return 0; } @@ -436,8 +446,10 @@ static StructInitInfo module = { .initKernel = InitKernel, .initLibrary = InitLibrary, +#ifdef HPCGAP .moduleStateSize = sizeof(struct CFTLModuleState), .moduleStateOffsetPtr = &CFTLStateOffset, +#endif .initModuleState = InitModuleState, }; diff --git a/src/objects.c b/src/objects.c index d76f74d6bb..8775fc0159 100644 --- a/src/objects.c +++ b/src/objects.c @@ -44,12 +44,14 @@ enum { MAXPRINTDEPTH = 64, }; +#ifdef HPCGAP static ModuleStateOffset ObjectsStateOffset = -1; typedef struct { - UInt PrintObjDepth; - Obj PrintObjThiss[MAXPRINTDEPTH]; - Int PrintObjIndices[MAXPRINTDEPTH]; +#endif + DECL_MODULE_STATE UInt PrintObjDepth; + DECL_MODULE_STATE Obj PrintObjThiss[MAXPRINTDEPTH]; + DECL_MODULE_STATE Int PrintObjIndices[MAXPRINTDEPTH]; // This variable is used to allow a ViewObj method to call PrintObj on the // same object without triggering use of '~'. It contains one of the @@ -57,10 +59,16 @@ typedef struct { // 0: there is no enclosing call to PrintObj or ViewObj still open, or // 1: the innermost such is PrintObj, or // 2: the innermost such is ViewObj. - UInt LastPV; + DECL_MODULE_STATE UInt LastPV; +#ifdef HPCGAP } ObjectsModuleState; +#define PrintObjDepth MODULE_STATE(Objects, PrintObjDepth) +#define PrintObjThiss MODULE_STATE(Objects, PrintObjThiss) +#define PrintObjIndices MODULE_STATE(Objects, PrintObjIndices) +#define LastPV MODULE_STATE(Objects, LastPV) +#endif static Int lastFreePackageTNUM = FIRST_PACKAGE_TNUM; @@ -895,13 +903,13 @@ static Obj FuncGET_TNAM_FROM_TNUM(Obj self, Obj obj) // This function is used to keep track of which objects are already // being printed or viewed to trigger the use of ~ when needed. -static inline BOOL IS_ON_PRINT_STACK(const ObjectsModuleState * os, Obj obj) +static inline BOOL IS_ON_PRINT_STACK(Obj obj) { if (!(FIRST_RECORD_TNUM <= TNUM_OBJ(obj) && TNUM_OBJ(obj) <= LAST_LIST_TNUM)) return FALSE; - for (UInt i = 0; i < os->PrintObjDepth; i++) - if (os->PrintObjThiss[i] == obj) + for (UInt i = 0; i < PrintObjDepth; i++) + if (PrintObjThiss[i] == obj) return TRUE; return FALSE; } @@ -961,46 +969,44 @@ void PrintObj(Obj obj) } #endif - ObjectsModuleState * os = &MODULE_STATE(Objects); - // First check if is actually the current object being viewed, since // ViewObj() may result in a call to PrintObj(); in that case, // we should not put on the print stack - if ((os->PrintObjDepth > 0) && (os->LastPV == 2) && - (obj == os->PrintObjThiss[os->PrintObjDepth - 1])) { - os->LastPV = 1; + if ((PrintObjDepth > 0) && (LastPV == 2) && + (obj == PrintObjThiss[PrintObjDepth - 1])) { + LastPV = 1; PRINT_OBJ(obj); - os->LastPV = 2; + LastPV = 2; } // print the path if is on the stack - else if (IS_ON_PRINT_STACK(os, obj)) { + else if (IS_ON_PRINT_STACK(obj)) { Pr("~", 0, 0); - for (int i = 0; obj != os->PrintObjThiss[i]; i++) { - PRINT_PATH(os->PrintObjThiss[i], os->PrintObjIndices[i]); + for (int i = 0; obj != PrintObjThiss[i]; i++) { + PRINT_PATH(PrintObjThiss[i], PrintObjIndices[i]); } } // dispatch to the appropriate printing function - else if (os->PrintObjDepth < MAXPRINTDEPTH) { + else if (PrintObjDepth < MAXPRINTDEPTH) { - Obj oldThis = os->PrintObjThiss[os->PrintObjDepth]; - Int oldIndx = os->PrintObjIndices[os->PrintObjDepth]; + Obj oldThis = PrintObjThiss[PrintObjDepth]; + Int oldIndx = PrintObjIndices[PrintObjDepth]; // push obj on the stack - os->PrintObjThiss[os->PrintObjDepth] = obj; - os->PrintObjIndices[os->PrintObjDepth] = 0; - os->PrintObjDepth++; + PrintObjThiss[PrintObjDepth] = obj; + PrintObjIndices[PrintObjDepth] = 0; + PrintObjDepth++; - UInt lastPV = os->LastPV; - os->LastPV = 1; + UInt lastPV = LastPV; + LastPV = 1; PRINT_OBJ(obj); - os->LastPV = lastPV; + LastPV = lastPV; // pop from the stack - os->PrintObjDepth--; - os->PrintObjThiss[os->PrintObjDepth] = oldThis; - os->PrintObjIndices[os->PrintObjDepth] = oldIndx; + PrintObjDepth--; + PrintObjThiss[PrintObjDepth] = oldThis; + PrintObjIndices[PrintObjDepth] = oldIndx; } else { Pr("\nprinting stopped, too many recursion levels!\n", 0, 0); @@ -1044,19 +1050,19 @@ static Obj FuncPRINT_OBJ(Obj self, Obj obj) UInt SetPrintObjState(UInt state) { - UInt oldDepth = MODULE_STATE(Objects).PrintObjDepth; - UInt oldLastPV = MODULE_STATE(Objects).LastPV; - MODULE_STATE(Objects).PrintObjDepth = state >> 2; - MODULE_STATE(Objects).LastPV = state & 3; + UInt oldDepth = PrintObjDepth; + UInt oldLastPV = LastPV; + PrintObjDepth = state >> 2; + LastPV = state & 3; return (oldDepth << 2) | oldLastPV; } void SetPrintObjIndex(Int index) { - UInt depth = MODULE_STATE(Objects).PrintObjDepth; + UInt depth = PrintObjDepth; if (depth == 0) ErrorQuit("SetPrintObjIndex: bad state, PrintObjDepth is 0", 0, 0); - MODULE_STATE(Objects).PrintObjIndices[depth - 1] = index; + PrintObjIndices[depth - 1] = index; } static Obj FuncSET_PRINT_OBJ_INDEX(Obj self, Obj index) @@ -1087,36 +1093,34 @@ void ViewObj(Obj obj) } #endif - ObjectsModuleState * os = &MODULE_STATE(Objects); - // print the path if is on the stack - if (IS_ON_PRINT_STACK(os, obj)) { + if (IS_ON_PRINT_STACK(obj)) { Pr("~", 0, 0); - for (int i = 0; obj != os->PrintObjThiss[i]; i++) { - PRINT_PATH(os->PrintObjThiss[i], os->PrintObjIndices[i]); + for (int i = 0; obj != PrintObjThiss[i]; i++) { + PRINT_PATH(PrintObjThiss[i], PrintObjIndices[i]); } } // dispatch to the appropriate viewing function - else if (os->PrintObjDepth < MAXPRINTDEPTH) { + else if (PrintObjDepth < MAXPRINTDEPTH) { - Obj oldThis = os->PrintObjThiss[os->PrintObjDepth]; - Int oldIndx = os->PrintObjIndices[os->PrintObjDepth]; + Obj oldThis = PrintObjThiss[PrintObjDepth]; + Int oldIndx = PrintObjIndices[PrintObjDepth]; // push obj on the stack - os->PrintObjThiss[os->PrintObjDepth] = obj; - os->PrintObjIndices[os->PrintObjDepth] = 0; - os->PrintObjDepth++; + PrintObjThiss[PrintObjDepth] = obj; + PrintObjIndices[PrintObjDepth] = 0; + PrintObjDepth++; - UInt lastPV = os->LastPV; - os->LastPV = 2; + UInt lastPV = LastPV; + LastPV = 2; DoOperation1Args(ViewObjOper, obj); - os->LastPV = lastPV; + LastPV = lastPV; // pop from the stack - os->PrintObjDepth--; - os->PrintObjThiss[os->PrintObjDepth] = oldThis; - os->PrintObjIndices[os->PrintObjDepth] = oldIndx; + PrintObjDepth--; + PrintObjThiss[PrintObjDepth] = oldThis; + PrintObjIndices[PrintObjDepth] = oldIndx; } else { Pr("\nviewing stopped, too many recursion levels!\n", 0, 0); @@ -2341,8 +2345,10 @@ static StructInitInfo module = { .initKernel = InitKernel, .initLibrary = InitLibrary, +#ifdef HPCGAP .moduleStateSize = sizeof(ObjectsModuleState), .moduleStateOffsetPtr = &ObjectsStateOffset, +#endif }; StructInitInfo * InitInfoObjects ( void ) diff --git a/src/objfgelm.cc b/src/objfgelm.cc index 48d21c52b8..633b5f970f 100644 --- a/src/objfgelm.cc +++ b/src/objfgelm.cc @@ -1596,8 +1596,10 @@ static StructInitInfo module = { /* preSave = */ 0, /* postSave = */ 0, /* postRestore = */ 0, +#ifdef HPCGAP /* moduleStateSize = */ 0, /* moduleStateOffsetPtr = */ 0, +#endif /* initModuleState = */ 0, /* destroyModuleState = */ 0, }; diff --git a/src/objpcgel.cc b/src/objpcgel.cc index ec5b0b05f8..358e59330a 100644 --- a/src/objpcgel.cc +++ b/src/objpcgel.cc @@ -381,8 +381,10 @@ static StructInitInfo module = { /* preSave = */ 0, /* postSave = */ 0, /* postRestore = */ 0, +#ifdef HPCGAP /* moduleStateSize = */ 0, /* moduleStateOffsetPtr = */ 0, +#endif /* initModuleState = */ 0, /* destroyModuleState = */ 0, }; 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 546e08d928..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; } } @@ -3903,8 +3904,10 @@ static StructInitInfo module = { /* preSave = */ 0, /* postSave = */ 0, /* postRestore = */ PostRestore, +#ifdef HPCGAP /* moduleStateSize = */ 0, /* moduleStateOffsetPtr = */ 0, +#endif /* initModuleState = */ InitModuleState, /* destroyModuleState = */ 0, }; diff --git a/src/permutat.cc b/src/permutat.cc index 50a030366d..7f7bb034a2 100644 --- a/src/permutat.cc +++ b/src/permutat.cc @@ -84,9 +84,11 @@ Obj IdentityPerm; static const UInt MAX_DEG_PERM4 = ((Int)1 << (sizeof(UInt) == 8 ? 32 : 28)) - 1; +#ifdef HPCGAP static ModuleStateOffset PermutatStateOffset = -1; typedef struct { +#endif /**************************************************************************** ** @@ -102,20 +104,21 @@ typedef struct { ** costs (particularly when starting new threads). ** Use the UseTmpPerm() utility function to ensure it is constructed! */ -Obj TmpPerm; +DECL_MODULE_STATE Obj TmpPerm; +#ifdef HPCGAP } PermutatModuleState; -#define TmpPerm MODULE_STATE(Permutat).TmpPerm +#define TmpPerm MODULE_STATE(Permutat, 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 @@ -3039,8 +3042,10 @@ static StructInitInfo module = { /* preSave = */ 0, /* postSave = */ 0, /* postRestore = */ PostRestore, +#ifdef HPCGAP /* moduleStateSize = */ sizeof(PermutatModuleState), /* moduleStateOffsetPtr = */ &PermutatStateOffset, +#endif /* initModuleState = */ InitModuleState, /* destroyModuleState = */ 0, }; 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/pperm.cc b/src/pperm.cc index 921c204d9e..af1fdcb270 100644 --- a/src/pperm.cc +++ b/src/pperm.cc @@ -120,9 +120,11 @@ static Obj EmptyPartialPerm; "must be a partial permutation") +#ifdef HPCGAP static ModuleStateOffset PPermStateOffset = -1; typedef struct { +#endif /************************************************************************** * @@ -136,12 +138,13 @@ typedef struct { * The buffer is *not* guaranteed to have any particular value, routines * that require a zero-initialization need to do this at the start. */ - Obj TmpPPerm; + DECL_MODULE_STATE Obj TmpPPerm; +#ifdef HPCGAP } PPermModuleState; - -#define TmpPPerm MODULE_STATE(PPerm).TmpPPerm +#define TmpPPerm MODULE_STATE(PPerm, TmpPPerm) +#endif static inline void ResizeTmpPPerm(UInt len) { @@ -3995,8 +3998,10 @@ static StructInitInfo module = { /* preSave = */ 0, /* postSave = */ 0, /* postRestore = */ 0, +#ifdef HPCGAP /* moduleStateSize = */ sizeof(PPermModuleState), /* moduleStateOffsetPtr = */ &PPermStateOffset, +#endif /* initModuleState = */ InitModuleState, /* destroyModuleState = */ 0, }; 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 3620454218..37e642bb77 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -62,13 +62,23 @@ static void SyntaxErrorOrWarning(ScannerState * s, Pr(" in %g:%d", (Int)name, GetInputLineNumber(s->input)); Pr("\n", 0, 0); - // print the current line + // print the current line — but skip the line print, and the + // caret below, if the buffer has been replaced by the scanner's + // end-of-input sentinel (0xFF). That happens when the syntax + // error fires after parsing has advanced past the offending + // line (e.g. `h := ;` parsed from a string with no trailing + // newline): the line buffer is refilled at EOF before the + // 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); - if (len > 0 && line[len-1] != '\n') - Pr("%s\n", (Int)line, 0); - else - Pr("%s", (Int)line, 0); + 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') + Pr("%s\n", (Int)line, 0); + else + Pr("%s", (Int)line, 0); + } // print a '^' pointing to the current position Int startPos = s->SymbolStartPos[tokenoffset]; @@ -83,7 +93,7 @@ static void SyntaxErrorOrWarning(ScannerState * s, pos = GetInputLinePosition(s->input); } - if (0 < pos && startPos <= pos) { + if (!line_is_sentinel && 0 < pos && startPos <= pos) { Int i; for (i = 0; i < startPos; i++) { if (line[i] == '\t') 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.c b/src/stringobj.c index 9e70b53f53..c3f659de5b 100644 --- a/src/stringobj.c +++ b/src/stringobj.c @@ -1062,7 +1062,7 @@ static BOOL IsSSortString(Obj list) len = GET_LEN_STRING( list ); ptr = CONST_CHARS_STRING(list); for ( i = 1; i < len; i++ ) { - if ( ! (ptr[i-1] < ptr[i]) ) + if (ptr[i - 1] >= ptr[i]) break; } @@ -1468,7 +1468,7 @@ static Obj FuncPOSITION_SUBSTRING(Obj self, Obj string, Obj substr, Obj off) for (i = ipos; i < max; i++) { if (c == s[i]) { for (j = 1; j < lenss; j++) { - if (! (s[i+j] == ss[j])) + if (s[i + j] != ss[j]) break; } if (j == lenss) 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 2558a37693..557e7b02a5 100644 --- a/src/trans.cc +++ b/src/trans.cc @@ -175,21 +175,22 @@ static Int GetPositiveListEntryEx(const char * funcname, GetPositiveListEntryEx(funcname, list, idx, NICE_ARGNAME(list)) +#ifdef HPCGAP static ModuleStateOffset TransStateOffset = -1; typedef struct { +#endif // TmpTrans is essentially the same as TmpPerm - Obj TmpTrans; + DECL_MODULE_STATE Obj TmpTrans; +#ifdef HPCGAP } TransModuleState; -static inline Obj GetTmpTrans(void) -{ - return MODULE_STATE(Trans).TmpTrans; -} +#define TmpTrans MODULE_STATE(Trans, TmpTrans) +#endif static inline UInt4 * AddrTmpTrans(void) { - return ADDR_TRANS4(GetTmpTrans()); + return ADDR_TRANS4(TmpTrans); } @@ -255,9 +256,9 @@ static inline void SET_EXT_TRANS(Obj f, Obj deg) static inline void ResizeTmpTrans(UInt len) { - Obj tmpTrans = GetTmpTrans(); + Obj tmpTrans = TmpTrans; if (tmpTrans == (Obj)0) { - MODULE_STATE(Trans).TmpTrans = NewBag(T_TRANS4, len * sizeof(UInt4) + 3 * sizeof(Obj)); + TmpTrans = NewBag(T_TRANS4, len * sizeof(UInt4) + 3 * sizeof(Obj)); } else if (SIZE_OBJ(tmpTrans) < len * sizeof(UInt4) + 3 * sizeof(Obj)) { ResizeBag(tmpTrans, len * sizeof(UInt4) + 3 * sizeof(Obj)); @@ -3864,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); @@ -3875,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)) { @@ -3885,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); @@ -3899,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)) { @@ -3909,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); @@ -3920,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); @@ -4120,7 +4122,8 @@ static StructGVarFilt GVarFilts[] = { }; -/****************************************************************************** +/**************************************************************************** +** *V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export */ static StructGVarFunc GVarFuncs[] = { @@ -4182,7 +4185,8 @@ static StructGVarFunc GVarFuncs[] = { }; -/****************************************************************************** +/**************************************************************************** +** *F InitKernel( ) . . . . . . . . initialise kernel data structures */ static Int InitKernel(StructInitInfo * module) @@ -4211,7 +4215,7 @@ static Int InitKernel(StructInitInfo * module) InitHdlrFuncsFromTable(GVarFuncs); // register global bags with the garbage collector - InitGlobalBag(&MODULE_STATE(Trans).TmpTrans, "src/trans.c:TmpTrans"); + InitGlobalBag(&TmpTrans, "src/trans.c:TmpTrans"); InitGlobalBag(&IdentityTrans, "src/trans.c:IdentityTrans"); #ifdef GAP_ENABLE_SAVELOAD @@ -4270,7 +4274,8 @@ static Int InitKernel(StructInitInfo * module) return 0; } -/****************************************************************************** +/**************************************************************************** +** *F InitLibrary( ) . . . . . . . initialise library data structures */ static Int InitLibrary(StructInitInfo * module) @@ -4284,9 +4289,8 @@ static Int InitLibrary(StructInitInfo * module) // code which would not otherwise be accessible, since no other // transformation created in this file is a T_TRANS4 unless its internal // degree is > 65536. Such transformation can be created by packages with - // a - // kernel module, and so we introduce the next transformation for testing - // purposes. + // a kernel module, and so we introduce the next transformation for + // testing purposes. Obj ID_TRANS4 = NEW_TRANS4(0); AssReadOnlyGVar(GVarName("ID_TRANS4"), ID_TRANS4); @@ -4295,7 +4299,7 @@ static Int InitLibrary(StructInitInfo * module) static Int InitModuleState(void) { - MODULE_STATE(Trans).TmpTrans = 0; + TmpTrans = 0; return 0; } @@ -4317,8 +4321,10 @@ static StructInitInfo module = { /* preSave = */ 0, /* postSave = */ 0, /* postRestore = */ 0, +#ifdef HPCGAP /* moduleStateSize = */ sizeof(TransModuleState), /* moduleStateOffsetPtr = */ &TransStateOffset, +#endif /* initModuleState = */ InitModuleState, /* destroyModuleState = */ 0, }; 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/00008.tst b/tst/testbugfix/00008.tst index 0488c51eca..b9860dcf8d 100644 --- a/tst/testbugfix/00008.tst +++ b/tst/testbugfix/00008.tst @@ -5,7 +5,7 @@ gap> EulerianFunction( CyclicGroup(6), 1 ); 2 gap> EulerianFunction( CyclicGroup(5), 1 ); 4 -gap> g:=SmallGroup(1,1);; +gap> g:=TrivialGroup(IsPcGroup);; gap> ConjugacyClassesSubgroups(g);; gap> g:=Group([ (3,5), (1,3,5) ]);; gap> MaximalSubgroups(g);; diff --git a/tst/testbugfix/2005-05-03-t00070.tst b/tst/testbugfix/2005-05-03-t00070.tst deleted file mode 100644 index 618574eb11..0000000000 --- a/tst/testbugfix/2005-05-03-t00070.tst +++ /dev/null @@ -1,5 +0,0 @@ -# 2005/05/03 (BE) -gap> NumberSmallGroups(5^6); -684 -gap> NumberSmallGroups(5*7*9*11*13); -22 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/MatrixObj/CompanionMatrix.tst b/tst/testinstall/MatrixObj/CompanionMatrix.tst index b5e27bbb2c..a2b1330b57 100644 --- a/tst/testinstall/MatrixObj/CompanionMatrix.tst +++ b/tst/testinstall/MatrixObj/CompanionMatrix.tst @@ -67,6 +67,22 @@ gap> TestCompanionMatrix(IsPlistMatrixRep, x+1, F); gap> TestCompanionMatrix(IsPlistMatrixRep, x^2+x+1, F); <2x2-matrix over Rationals> +# +# IsGenericMatrixRep +# +gap> F:= GF(251);; x:= X(F);; +gap> TestCompanionMatrix(IsGenericMatrixRep, x+1, F); +<1x1-matrix over GF(251)> +gap> TestCompanionMatrix(IsGenericMatrixRep, x^2+x+1, F); +<2x2-matrix over GF(251)> + +# +gap> F:= Integers;; x:= X(F);; +gap> TestCompanionMatrix(IsGenericMatrixRep, x+1, F); +<1x1-matrix over Integers> +gap> TestCompanionMatrix(IsGenericMatrixRep, x^2+x+1, F); +<2x2-matrix over Integers> + # # IsPlistRep # diff --git a/tst/testinstall/MatrixObj/ElementaryMatrices.tst b/tst/testinstall/MatrixObj/ElementaryMatrices.tst index e2080c550a..2204e66d9c 100644 --- a/tst/testinstall/MatrixObj/ElementaryMatrices.tst +++ b/tst/testinstall/MatrixObj/ElementaryMatrices.tst @@ -67,6 +67,14 @@ true gap> TestElementaryTransforms( mat, -1 ); gap> TestWholeMatrixTransforms( mat, -1 ); +# +gap> mat := NewMatrix(IsGenericMatrixRep, Integers, 3, +> [ [ 2, 4, 5 ], [ 7, 11, -4 ], [ -3, 20, 0 ] ] );; +gap> IsGenericMatrixRep(mat); +true +gap> TestElementaryTransforms( mat, -1 ); +gap> TestWholeMatrixTransforms( mat, -1 ); + # gap> TestPositionNonZeroInRow([ [ 1 ] ]); gap> TestPositionNonZeroInRow(Matrix([ [ 1 ] ])); diff --git a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst index eeb77a8213..445c4d82e8 100644 --- a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst +++ b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst @@ -1,15 +1,14 @@ gap> START_TEST("ExtractSubMatrix.tst"); - -# +gap> IsBoundGlobal("EXTRACT_SUB_MATRIX"); +true +gap> EXTRACT_SUB_MATRIX = ExtractSubMatrix; +true gap> m1 := [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] gap> ExtractSubMatrix( m1, [ 2, 1 ], [ 3, 1 ] ); [ [ 6, 4 ], [ 3, 1 ] ] -gap> m2 := IdentityMatrix( Integers, 4 ); -<4x4-matrix over Integers> -gap> m3 := ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ); -<2x2-matrix over Integers> -gap> Unpack( m3 ); +gap> m2 := IdentityMatrix( Integers, 4 );; +gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); [ [ 0, 1 ], [ 1, 0 ] ] # IsGF2MatrixRep @@ -27,6 +26,7 @@ gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); < mutable compressed matrix 20x20 over GF(3) > gap> IsOne(m2); true - -# +gap> m2 := IdentityMatrix( Integers, 4 );; +gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); +[ [ 0, 1 ], [ 1, 0 ] ] gap> STOP_TEST("ExtractSubMatrix.tst"); diff --git a/tst/testinstall/MatrixObj/IdentityMatrix.tst b/tst/testinstall/MatrixObj/IdentityMatrix.tst index 1cabf541aa..74f429b3f2 100644 --- a/tst/testinstall/MatrixObj/IdentityMatrix.tst +++ b/tst/testinstall/MatrixObj/IdentityMatrix.tst @@ -73,6 +73,24 @@ gap> TestIdentityMatrix(IsPlistMatrixRep, Integers mod 4, 0); gap> TestIdentityMatrix(IsPlistMatrixRep, Integers mod 4, -1); Error, IdentityMatrix: the dimension must be non-negative +# +# IsGenericMatrixRep +# +gap> TestIdentityMatrix(IsGenericMatrixRep, GF(2), 2); +<2x2-matrix over GF(2)> +gap> TestIdentityMatrix(IsGenericMatrixRep, GF(2), 0); +<0x0-matrix over GF(2)> +gap> TestIdentityMatrix(IsGenericMatrixRep, GF(2), -1); +Error, IdentityMatrix: the dimension must be non-negative + +# +gap> TestIdentityMatrix(IsGenericMatrixRep, Integers, 2); +<2x2-matrix over Integers> +gap> TestIdentityMatrix(IsGenericMatrixRep, Integers, 0); +<0x0-matrix over Integers> +gap> TestIdentityMatrix(IsGenericMatrixRep, Integers, -1); +Error, IdentityMatrix: the dimension must be non-negative + # # Test IdentityMatrix variant which "guesses" a suitable representation, i.e.: # IdentityMatrix( , , ) diff --git a/tst/testinstall/MatrixObj/ListOp.tst b/tst/testinstall/MatrixObj/ListOp.tst index 0c394900f8..e8a6580c23 100644 --- a/tst/testinstall/MatrixObj/ListOp.tst +++ b/tst/testinstall/MatrixObj/ListOp.tst @@ -23,4 +23,7 @@ gap> List( v ); [ ] gap> List( v, DegreeFFE ); [ ] +gap> v1:= Vector( IsPlistVectorRep, Rationals, [] );; +gap> v1[1]:= 0; +Error,

is out of bounds gap> STOP_TEST("ListOp.tst"); diff --git a/tst/testinstall/MatrixObj/Matrix.tst b/tst/testinstall/MatrixObj/Matrix.tst index 85d6c9d80f..bc07b33465 100644 --- a/tst/testinstall/MatrixObj/Matrix.tst +++ b/tst/testinstall/MatrixObj/Matrix.tst @@ -45,5 +45,16 @@ gap> Display(m); gap> m = Matrix( IsPlistMatrixRep, GF(2), [1,2,3,4] * Z(2), 2 ); true +# +gap> m := Matrix( IsGenericMatrixRep, GF(2), [[1,2],[3,4]] * Z(2) ); +<2x2-matrix over GF(2)> +gap> Display(m); +<2x2-matrix over GF(2): +[[ Z(2)^0, 0*Z(2) ] + [ Z(2)^0, 0*Z(2) ] +]> +gap> m = Matrix( IsGenericMatrixRep, GF(2), [1,2,3,4] * Z(2), 2 ); +true + # gap> STOP_TEST("Matrix.tst"); diff --git a/tst/testinstall/MatrixObj/ZeroMatrix.tst b/tst/testinstall/MatrixObj/ZeroMatrix.tst index 2affaa554b..a21962bfcf 100644 --- a/tst/testinstall/MatrixObj/ZeroMatrix.tst +++ b/tst/testinstall/MatrixObj/ZeroMatrix.tst @@ -79,6 +79,24 @@ gap> TestZeroMatrix(IsPlistMatrixRep, Integers mod 4, 2, 0); gap> TestZeroMatrix(IsPlistMatrixRep, Integers mod 4, 0, 3); <0x3-matrix over (Integers mod 4)> +# +# IsGenericMatrixRep +# +gap> TestZeroMatrix(IsGenericMatrixRep, GF(2), 2, 3); +<2x3-matrix over GF(2)> +gap> TestZeroMatrix(IsGenericMatrixRep, GF(2), 2, 0); +<2x0-matrix over GF(2)> +gap> TestZeroMatrix(IsGenericMatrixRep, GF(2), 0, 3); +<0x3-matrix over GF(2)> + +# +gap> TestZeroMatrix(IsGenericMatrixRep, Integers, 2, 3); +<2x3-matrix over Integers> +gap> TestZeroMatrix(IsGenericMatrixRep, Integers, 2, 0); +<2x0-matrix over Integers> +gap> TestZeroMatrix(IsGenericMatrixRep, Integers, 0, 3); +<0x3-matrix over Integers> + # # Test ZeroMatrix variant which "guesses" a suitable representation, i.e.: # ZeroMatrix( , , ) diff --git a/tst/testinstall/MatrixObj/arith.tst b/tst/testinstall/MatrixObj/arith.tst index 40b646af3f..87bdccbd01 100644 --- a/tst/testinstall/MatrixObj/arith.tst +++ b/tst/testinstall/MatrixObj/arith.tst @@ -16,5 +16,13 @@ Error, * is not defined gap> mat * matobj; Error, * is not defined +# Powering matrices works. +gap> mat:= Matrix( Integers, [ [ 1, 1 ], [ 0, 1 ] ] );; +gap> Unpack( mat^2 ) = Unpack( mat )^2; +true +gap> mat:= Matrix( Rationals, [ [ 1, 1 ], [ 0, 1 ] ] );; +gap> Unpack( mat^2 ) = Unpack( mat )^2; +true + # gap> STOP_TEST( "arith.tst" ); diff --git a/tst/testinstall/MatrixObj/matobjgeneric.tst b/tst/testinstall/MatrixObj/matobjgeneric.tst new file mode 100644 index 0000000000..e1bc6c3ca1 --- /dev/null +++ b/tst/testinstall/MatrixObj/matobjgeneric.tst @@ -0,0 +1,465 @@ +#@local e, v, v2, w, M, z, rows, a, b, c, d, p, ev, n, ai, inv, zm, zs, N, T, R +gap> START_TEST( "matobjgeneric.tst" ); + +# +# MakeIsPlistVectorRep: test input validation +# +gap> e:= MakeIsPlistVectorRep( Integers, [], true ); + +gap> v:= MakeIsPlistVectorRep( Integers, [ 1 ], true ); + +gap> v2:= NewVector( IsPlistVectorRep, Integers, [ 1, 0 ] ); + +gap> w:= MakeIsPlistVectorRep( Rationals, [ 1 ], true ); + + +# +gap> MakeIsGenericMatrixRep( Integers, 2, [ v ], true ); +Error, the entries of must be plain lists +gap> M:= MakeIsGenericMatrixRep( Integers, 2, [], true ); +<0x2-matrix over Integers> +gap> MakeIsGenericMatrixRep( Integers, 1, [ [ 1 ] ], true ); +<1x1-matrix over Integers> +gap> MakeIsGenericMatrixRep( Integers, 2, [ [ 1 ] ], true ); +Error, the entries of must have length +gap> MakeIsGenericMatrixRep( Integers, 1, [ [ 1/2 ] ], true ); +Error, the elements in must lie in +gap> MakeIsGenericMatrixRep( GF(2), 1, [ [ Z(2) ] ], true ); +<1x1-matrix over GF(2)> +gap> MakeIsGenericMatrixRep( GF(2), 1, [ [ Z(4) ] ], true ); +Error, the elements in must lie in + +# +gap> NewMatrix( IsGenericMatrixRep, Integers, 2, [] ); +<0x2-matrix over Integers> +gap> NewMatrix( IsGenericMatrixRep, Integers, 2, [ 1 ] ); +Error, NewMatrix: Length of is not a multiple of +gap> NewMatrix( IsGenericMatrixRep, Integers, 2, [ [ 1 ] ] ); +Error, the entries of must have length +gap> NewMatrix( IsGenericMatrixRep, Integers, 2, [ [ 1, 2 ] ] ); +<1x2-matrix over Integers> +gap> NewMatrix( IsGenericMatrixRep, Integers, 2, [ v ] ); +Error, the entries of must have length +gap> M:= NewMatrix( IsGenericMatrixRep, Integers, 2, [ [ 1, 2 ], [ 3, 4 ] ] ); +<2x2-matrix over Integers> +gap> IsMutable( M ); +true +gap> Unpack( M ); +[ [ 1, 2 ], [ 3, 4 ] ] +gap> M[2,1]; +3 +gap> M[1]; +Error, row access unsupported; use M[i,j] or RowsOfMatrix(M) +gap> M[2,2] := 5;; +gap> Unpack( M ); +[ [ 1, 2 ], [ 3, 5 ] ] + +# +gap> rows:= RowsOfMatrix( M ); +[ , + ] +gap> Length( rows ); +2 +gap> IsPlistVectorRep( rows[1] ); +true +gap> Unpack( rows[1] ); +[ 1, 2 ] +gap> M[1,1] := 77;; +gap> rows[1][1]; +1 + +# +gap> M:= NewMatrix( IsGenericMatrixRep, Integers, 2, [ v2, v2 ] );; +gap> Unpack( M ); +[ [ 1, 0 ], [ 1, 0 ] ] + +# +# Empty matrices and empty vectors +# +# +gap> a:= ZeroMatrix( IsGenericMatrixRep, Integers, 2, 0 ); +<2x0-matrix over Integers> +gap> b:= ZeroMatrix( IsGenericMatrixRep, Integers, 0, 3 ); +<0x3-matrix over Integers> +gap> c:= ZeroMatrix( IsGenericMatrixRep, Integers, 0, 0 ); +<0x0-matrix over Integers> +gap> d:= ZeroMatrix( IsGenericMatrixRep, Integers, 0, 2 ); +<0x2-matrix over Integers> +gap> z:= ZeroMatrix( IsGenericMatrixRep, Integers, 2, 3 ); +<2x3-matrix over Integers> +gap> IsMutable( z ); +true +gap> Unpack( z ); +[ [ 0, 0, 0 ], [ 0, 0, 0 ] ] + +# +gap> M:= NewIdentityMatrix( IsGenericMatrixRep, Integers, 2 );; +gap> Unpack( M ); +[ [ 1, 0 ], [ 0, 1 ] ] + +# +gap> a = NewMatrix( IsGenericMatrixRep, Integers, 0, [ [], [] ] ); +true +gap> b = NewMatrix( IsGenericMatrixRep, Integers, 3, [] ); +true +gap> c = NewMatrix( IsGenericMatrixRep, Integers, 0, [] ); +true +gap> d = NewMatrix( IsGenericMatrixRep, Integers, 2, [] ); +true + +# +gap> p:= a * b; +<2x3-matrix over Integers> +gap> Unpack( p ); +[ [ 0, 0, 0 ], [ 0, 0, 0 ] ] +gap> p:= d * a; +<0x0-matrix over Integers> +gap> Unpack( p ); +[ ] +gap> p:= c * b; +<0x3-matrix over Integers> +gap> Unpack( p ); +[ ] + +# empty vector times (necessarily also empty) matrix +gap> ev:= NewVector( IsPlistVectorRep, Integers, [] ); + +gap> a * ev; + +gap> Unpack( last ); +[ 0, 0 ] +gap> ev * b; + +gap> Unpack( last ); +[ 0, 0, 0 ] + +# non-empty vector times empty matrix +gap> v2:= NewVector( IsPlistVectorRep, Integers, [ 1, 2 ] ); + +gap> d * v2; + +gap> Unpack( last ); +[ ] +gap> Unpack( v2 * a ); +[ ] + +# +gap> b + b; +<0x3-matrix over Integers> +gap> b - b; +<0x3-matrix over Integers> +gap> -b; +<0x3-matrix over Integers> +gap> ZeroMutable( b ); +<0x3-matrix over Integers> + +# +gap> InverseMutable( c ); +<0x0-matrix over Integers> +gap> InverseSameMutability( c ); +<0x0-matrix over Integers> + +# +gap> M:= Matrix( IsGenericMatrixRep, Integers, [ [ 0, 0, 2 ], [ 0, 0, 0 ] ] );; +gap> PositionNonZeroInRow( M, 1 ); +3 +gap> PositionNonZeroInRow( M, 1, 2 ); +3 +gap> PositionNonZeroInRow( M, 2 ); +4 + +# +gap> M:= Matrix( IsGenericMatrixRep, Integers, [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] );; +gap> MultMatrixRowLeft( M, 1, -1 );; +gap> Unpack( M ); +[ [ -1, -2, -3 ], [ 4, 5, 6 ] ] +gap> MultMatrixRowRight( M, 2, 2 );; +gap> Unpack( M ); +[ [ -1, -2, -3 ], [ 8, 10, 12 ] ] +gap> AddMatrixRowsLeft( M, 1, 2, 3 );; +gap> Unpack( M ); +[ [ 23, 28, 33 ], [ 8, 10, 12 ] ] +gap> AddMatrixRowsRight( M, 2, 1, 2 );; +gap> Unpack( M ); +[ [ 23, 28, 33 ], [ 54, 66, 78 ] ] +gap> SwapMatrixRows( M, 1, 2 );; +gap> Unpack( M ); +[ [ 54, 66, 78 ], [ 23, 28, 33 ] ] + +# +# Test Inverse / InverseMutable +# +gap> M:= Matrix( IsGenericMatrixRep, Integers, [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ] );; +gap> InverseMutable( M ); +Error, InverseMutable: matrix must be square + +# +gap> M:= ZeroMatrix( IsGenericMatrixRep, Integers, 2, 2 );; +gap> InverseMutable( M ); +fail + +# +gap> M:= Matrix( IsGenericMatrixRep, GF(2), [ [ Z(2)^0, Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ] );; +gap> N:= InverseMutable( M );; +gap> Display( N ); +<2x2-matrix over GF(2): +[[ 0*Z(2), Z(2)^0 ] + [ Z(2)^0, Z(2)^0 ] +]> +gap> IsOne( N * M ); +true +gap> IsOne( M * N ); +true + +# +gap> M:= Matrix( IsGenericMatrixRep, Rationals, [ [ 1, 2 ], [ 3, 5 ] ] );; +gap> N:= InverseMutable( M );; +gap> Display( N ); +<2x2-matrix over Rationals: +[[ -5, 2 ] + [ 3, -1 ] +]> + +# +# mutability after operations +# +gap> M:= Matrix( IsGenericMatrixRep, Rationals, [ [ 1, 2 ], [ 3, 5 ] ] );; +gap> IsMutable(M); +true +gap> N:= InverseSameMutability( M );; +gap> IsMutable(N); +true +gap> IsMutable( M * N ); +true +gap> IsMutable( M + N ); +true +gap> IsMutable( M - N ); +true +gap> IsMutable( -M ); +true +gap> MakeImmutable(M);; +gap> IsMutable( M * N ); +true +gap> IsMutable( M + N ); +true +gap> IsMutable( M - N ); +true +gap> N:= InverseSameMutability( M );; +gap> IsMutable(N); +false +gap> IsMutable( M * N ); +false +gap> IsMutable( M + N ); +false +gap> IsMutable( M - N ); +false +gap> IsMutable( -M ); +false + +# +gap> M:= Matrix( IsGenericMatrixRep, Integers, [ [ 1, 2 ], [ 3, 4 ] ] );; +gap> M[1,1] := 1/2; +Error, must lie in the base domain of +gap> M[3,1] := 1; +Error, is out of bounds +gap> M[1,3] := 1; +Error, is out of bounds + +# +gap> a:= Matrix( IsGenericMatrixRep, Integers, [ [ 1, 2 ] ] );; +gap> b:= Matrix( IsGenericMatrixRep, Rationals, [ [ 1, 2 ] ] );; +gap> a + b; +Error, and are not compatible +gap> a - b; +Error, and are not compatible +gap> c:= Matrix( IsGenericMatrixRep, Integers, [ [ 1 ], [ 2 ] ] );; +gap> c * c; +Error, \*: Matrices do not fit together +gap> d:= Matrix( IsGenericMatrixRep, Rationals, [ [ 1 ], [ 2 ] ] );; +gap> a * d; +Error, \*: Matrices not over same base domain + +# +# ShallowCopy, MutableCopyMatrix +# +gap> M:= Matrix( IsGenericMatrixRep, Integers, [ [ 1, 2 ], [ 3, 4 ] ] );; +gap> N:= ShallowCopy( M );; +gap> N[1,1] := 99;; +gap> Unpack( M ); +[ [ 1, 2 ], [ 3, 4 ] ] +gap> Unpack( N ); +[ [ 99, 2 ], [ 3, 4 ] ] +gap> N:= MutableCopyMatrix( M );; +gap> N[1,2] := 77;; +gap> Unpack( M ); +[ [ 1, 2 ], [ 3, 4 ] ] +gap> Unpack( N ); +[ [ 1, 77 ], [ 3, 4 ] ] + +# +# ExtractSubMatrix, CopySubMatrix +# +gap> Unpack( ExtractSubMatrix( M, [ 2, 1 ], [ 2 ] ) ); +[ [ 4 ], [ 2 ] ] +gap> T:= ZeroMatrix( IsGenericMatrixRep, Integers, 2, 3 );; +gap> CopySubMatrix( M, T, [ 2, 1 ], [ 1, 2 ], [ 2 ], [ 3 ] );; +gap> Unpack( T ); +[ [ 0, 0, 4 ], [ 0, 0, 2 ] ] +gap> CopySubMatrix( Matrix( IsGenericMatrixRep, Rationals, [ [ 1, 2 ] ] ), +> T, [ 1 ], [ 1 ], [ 1 ], [ 1 ] ); +Error, and are not compatible + +# +# TransposedMatMutable +# +gap> Unpack( TransposedMatMutable( M ) ); +[ [ 1, 3 ], [ 2, 4 ] ] + +# +# ChangedBaseDomain +# +gap> N:= ChangedBaseDomain( M, Rationals );; +gap> BaseDomain( N ); +Rationals +gap> Unpack( N ); +[ [ 1, 2 ], [ 3, 4 ] ] +gap> IsMutable( N ); +true +gap> MakeImmutable( M );; +gap> N:= ChangedBaseDomain( M, Rationals );; +gap> IsMutable( N ); +false + +# +# ViewObj, PrintObj, Display, String +# +gap> M := Matrix( IsGenericMatrixRep, GF(2), [ [ Z(2)^0, 0*Z(2) ] ] ); +<1x2-matrix over GF(2)> +gap> Print(M, "\n"); +NewMatrix(IsGenericMatrixRep,GF(2),2,[ [ Z(2)^0, 0*Z(2) ] ]) +gap> Display(M); +<1x2-matrix over GF(2): +[[ Z(2)^0, 0*Z(2) ] +]> +gap> String(M); +"NewMatrix(IsGenericMatrixRep,GF(2),2,[ [ Z(2)^0, 0*Z(2) ] ])" + +# +gap> MakeImmutable( M ); + +gap> Print(M, "\n"); +NewMatrix(IsGenericMatrixRep,GF(2),2,[ [ Z(2)^0, 0*Z(2) ] ]) +gap> Display(M); + +gap> String(M); +"NewMatrix(IsGenericMatrixRep,GF(2),2,[ [ Z(2)^0, 0*Z(2) ] ])" + +# +gap> M :=Matrix( IsGenericMatrixRep, Integers, [ [ 1, 2 ], [ 3, 4 ] ] ); +<2x2-matrix over Integers> +gap> Print(M, "\n"); +NewMatrix(IsGenericMatrixRep,Integers,2,[ [ 1, 2 ], [ 3, 4 ] ]) +gap> Display(M); +<2x2-matrix over Integers: +[[ 1, 2 ] + [ 3, 4 ] +]> +gap> String(M); +"NewMatrix(IsGenericMatrixRep,Integers,2,[ [ 1, 2 ], [ 3, 4 ] ])" + +# +gap> MakeImmutable( M ); + +gap> Print(M, "\n"); +NewMatrix(IsGenericMatrixRep,Integers,2,[ [ 1, 2 ], [ 3, 4 ] ]) +gap> Display(M); + +gap> String(M); +"NewMatrix(IsGenericMatrixRep,Integers,2,[ [ 1, 2 ], [ 3, 4 ] ])" + +# +# vec * mat, mat * vec +# +gap> M:= Matrix( IsGenericMatrixRep, Integers, [ [ 1, 2 ], [ 3, 4 ] ] );; +gap> v:= Vector( Integers, [ 1, 2 ] ); + +gap> Display( M * v ); + +gap> Display( v * M ); + + +# +gap> M * [ 1, 2 ]; +[ 5, 11 ] +gap> [ 1, 2 ] * M; +[ 7, 10 ] + +# +gap> R:= Integers mod 6;; +gap> M:= Matrix( IsGenericMatrixRep, R, One(R) * [ [ 1, 2 ], [ 3, 4 ] ] );; +gap> v:= NewVector( IsZmodnZVectorRep, R, One(R) * [ 1, 2 ] ); + +gap> Display( M * v ); + +gap> Display( v * M ); + + +# error handling +gap> M * [ 1, 2, 3 ]; +Error, and are not compatible +gap> [ 1, 2, 3 ] * M; +Error, and are not compatible +gap> M * [ Z(2), Z(2) ]; +Error, and are not compatible +gap> [ Z(2), Z(2) ] * M; +Error, and are not compatible + +# multiplication with empty list is not well-defined: we don't know if +# is meant to be a vector of length 0, or something else; so rather +# error out +gap> a:= ZeroMatrix( IsGenericMatrixRep, Integers, 2, 0 );; +gap> b:= ZeroMatrix( IsGenericMatrixRep, Integers, 0, 3 );; +gap> a * []; +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `BaseDomain' on 1 arguments +gap> [] * b; +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `BaseDomain' on 1 arguments + +# +# families +# +gap> M:= NewZeroMatrix( IsGenericMatrixRep, Integers, 2, 3 ); +<2x3-matrix over Integers> +gap> IsMutable( M ); +true +gap> IsCyclotomicCollColl( M ); +true +gap> IsFFECollColl( M ); +false + +# +gap> M:= NewZeroMatrix( IsGenericMatrixRep, GF(257), 2, 3 ); +<2x3-matrix over GF(257)> +gap> IsMutable( M ); +true +gap> IsCyclotomicCollColl( M ); +false +gap> IsFFECollColl( M ); +true + +# +gap> STOP_TEST( "matobjgeneric.tst" ); diff --git a/tst/testinstall/MatrixObj/matobjplist.tst b/tst/testinstall/MatrixObj/matobjplist.tst index f1099217d9..5a609ef25e 100644 --- a/tst/testinstall/MatrixObj/matobjplist.tst +++ b/tst/testinstall/MatrixObj/matobjplist.tst @@ -3,6 +3,8 @@ gap> START_TEST( "matobjplist.tst" ); # gap> e:= MakeIsPlistVectorRep( Integers, [], true );; +gap> MakeIsPlistVectorRep( Integers, [ 1 .. 4 ], true );; +Error, must be in 'IsPlistRep' gap> v:= MakeIsPlistVectorRep( Integers, [ 1 ], true );; gap> MakeIsPlistVectorRep( Integers, [ 1/2 ], true );; Error, the elements in must lie in @@ -37,10 +39,8 @@ gap> NewVector( IsPlistVectorRep, Integers, [ 1/2 ] );; Error, the elements in must lie in # -gap> NewZeroVector( IsPlistVectorRep, Integers, 0 );; -gap> z:= NewZeroVector( IsPlistVectorRep, Integers, 1 );; -gap> IsMutable( z ); -true +gap> NewZeroVector( IsPlistVectorRep, Integers, 0 ); + # gap> NewMatrix( IsPlistMatrixRep, Integers, 2, [] );; @@ -56,18 +56,74 @@ gap> IsMutable( M ) and ForAll( [ 1 .. Length( M ) ], i -> IsMutable( M[i] ) ); true # -gap> NewZeroMatrix( IsPlistMatrixRep, Integers, 0, 0 );; -gap> NewZeroMatrix( IsPlistMatrixRep, Integers, 2, 0 );; -gap> NewZeroMatrix( IsPlistMatrixRep, Integers, 0, 3 );; -gap> M:= NewZeroMatrix( IsPlistMatrixRep, Integers, 2, 3 );; +gap> NewZeroMatrix( IsPlistMatrixRep, Integers, 0, 0 ); +<0x0-matrix over Integers> +gap> NewZeroMatrix( IsPlistMatrixRep, Integers, 2, 0 ); +<2x0-matrix over Integers> +gap> NewZeroMatrix( IsPlistMatrixRep, Integers, 0, 3 ); +<0x3-matrix over Integers> +gap> M:= NewZeroMatrix( IsPlistMatrixRep, Integers, 2, 3 ); +<2x3-matrix over Integers> gap> IsMutable( M ) and ForAll( [ 1 .. Length( M ) ], i -> IsMutable( M[i] ) ); true # -gap> NewIdentityMatrix( IsPlistMatrixRep, Integers, 0 );; -gap> M:= NewIdentityMatrix( IsPlistMatrixRep, Integers, 2 );; +gap> NewIdentityMatrix( IsPlistMatrixRep, Integers, 0 ); +<0x0-matrix over Integers> +gap> M:= NewIdentityMatrix( IsPlistMatrixRep, Integers, 2 ); +<2x2-matrix over Integers> gap> IsMutable( M ) and ForAll( [ 1 .. Length( M ) ], i -> IsMutable( M[i] ) ); true +# +# special filters and families +# +gap> v:= NewVector( IsPlistVectorRep, Integers, [ 1, 2, 0 ] ); + +gap> IsMutable( v ); +true +gap> IsIntVector( v ); +true +gap> IsFFEVector( v ); +false +gap> IsCyclotomicCollection( v ); +true +gap> IsFFECollection( v ); +false + +# +gap> v:= NewVector( IsPlistVectorRep, GF(257), Z(257)^0 * [ 1, 2, 0 ] ); + +gap> IsMutable( v ); +true +gap> IsIntVector( v ); +false +gap> IsFFEVector( v ); +true +gap> IsCyclotomicCollection( v ); +false +gap> IsFFECollection( v ); +true + +# +gap> M:= NewZeroMatrix( IsPlistMatrixRep, Integers, 2, 3 ); +<2x3-matrix over Integers> +gap> IsMutable( M ); +true +gap> IsCyclotomicCollColl( M ); +true +gap> IsFFECollColl( M ); +false + +# +gap> M:= NewZeroMatrix( IsPlistMatrixRep, GF(257), 2, 3 ); +<2x3-matrix over GF(257)> +gap> IsMutable( M ); +true +gap> IsCyclotomicCollColl( M ); +false +gap> IsFFECollColl( M ); +true + # gap> STOP_TEST( "matobjplist.tst" ); diff --git a/tst/testinstall/MatrixObj/testmatobj.g b/tst/testinstall/MatrixObj/testmatobj.g index bca02e4c1c..5d1ac8de44 100644 --- a/tst/testinstall/MatrixObj/testmatobj.g +++ b/tst/testinstall/MatrixObj/testmatobj.g @@ -211,6 +211,8 @@ TestWholeMatrixTransforms := function(mat, scalar) basedomain := BaseDomain(mat); if IsPlistMatrixRep(mat) then src := NewMatrix(IsPlistMatrixRep, basedomain, NrCols(mat), src); + elif IsGenericMatrixRep(mat) then + src := NewMatrix(IsGenericMatrixRep, basedomain, NrCols(mat), src); elif Is8BitMatrixRep(mat) then ConvertToMatrixRep(src, basedomain); fi; @@ -257,8 +259,9 @@ end; TestPositionNonZeroInRow := function(mat) local ncols; - # Make a matrix with specific patter of the same kind as mat - mat := Matrix([ [ 0, 1, 0, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 1, 0 ] ], mat); + # Make a matrix with specific pattern of the same kind as mat + mat := Matrix([ [ 0, 1, 0, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 1, 0 ] ] + * One( BaseDomain( mat ) ), mat); ncols := NrCols(mat); if PositionNonZeroInRow(mat, 1) <> 2 then diff --git a/tst/testinstall/coder.tst b/tst/testinstall/coder.tst index 9b24d64773..a625d73333 100644 --- a/tst/testinstall/coder.tst +++ b/tst/testinstall/coder.tst @@ -1,3 +1,4 @@ +#@local f,r,l # # Tests for the GAP coder logic. # @@ -8,6 +9,29 @@ # gap> START_TEST("coder.tst"); +# +# non boolean expression as condition +# +gap> function() if 1 then fi; end(); +Error, must be 'true' or 'false' (not the integer 1) + +# +# return is allowed in functions +# +gap> function() return; end(); +gap> function() return 1; end(); +1 + +# +# help system +# +gap> function() ?qwert_asdf end; +Syntax error: '?' cannot be used in this context in stream:1 +function() ?qwert_asdf end; + ^^^^^^^^^^^^^^^^ +Syntax error: while parsing a function: statement or 'end' expected in stream:\ +2 + # # function call with options # @@ -26,71 +50,47 @@ gap> ({}-> f(1 : ("a") := 23 ) )(); # # records # -gap> function() -> local r; -> r := rec(a:=1); -> Display(r); -> r.a := 1; -> Display(r.a); -> Display(IsBound(r.a)); -> Unbind(r.a); -> return r; -> end(); -rec( - a := 1 ) +gap> r := ({}-> rec(a:=1) )(); +rec( a := 1 ) + +# +gap> function() r.a := 1; end(); +gap> ({}-> r.a )(); 1 +gap> ({}-> IsBound(r.a) )(); true +gap> function() Unbind(r.a); end(); +gap> ({}-> r )(); rec( ) # -gap> function() -> local r; -> r := rec(a:=1); -> Display(r); -> r!.a := 1; -> Display(r!.a); -> Display(IsBound(r!.a)); -> Unbind(r!.a); -> return r; -> end(); -rec( - a := 1 ) +gap> function() r!.a := 1; end(); +gap> ({}-> r!.a )(); 1 +gap> ({}-> IsBound(r!.a) )(); true +gap> function() Unbind(r!.a); end(); +gap> ({}-> r )(); rec( ) # -gap> function() -> local r; -> r := rec(("a"):=1); -> Display(r); -> r.("a") := 1; -> Display(r.("a")); -> Display(IsBound(r.("a"))); -> Unbind(r.("a")); -> return r; -> end(); -rec( - a := 1 ) +gap> function() r.("a") := 1; end(); +gap> ({}-> r.("a") )(); 1 +gap> ({}-> IsBound(r.("a")) )(); true +gap> function() Unbind(r.("a")); end(); +gap> ({}-> r )(); rec( ) # -gap> function() -> local r; -> r := rec(("a"):=1); -> Display(r); -> r!.("a") := 1; -> Display(r!.("a")); -> Display(IsBound(r!.("a"))); -> Unbind(r!.("a")); -> return r; -> end(); -rec( - a := 1 ) +gap> function() r!.("a") := 1; end(); +gap> ({}-> r!.("a") )(); 1 +gap> ({}-> IsBound(r!.("a")) )(); true +gap> function() Unbind(r!.("a")); end(); +gap> ({}-> r )(); rec( ) # test special case in CodeRecExprBeginElmExpr @@ -110,32 +110,26 @@ rec( 42 := 3, 43 := 4, x := 1, y := 2 ) gap> r := Objectify(NewType(NewFamily("MockFamily"), IsComponentObjectRep), rec());; # -gap> function() -> r!.a := 1; -> Display(r!.a); -> Display(IsBound(r!.a)); -> Unbind(r!.a); -> Display(IsBound(r!.a)); -> end(); +gap> function() r!.a := 1; end(); +gap> ({}-> r!.a )(); 1 +gap> ({}-> IsBound(r!.a) )(); true -false +gap> function() Unbind(r!.a); end(); # -gap> function() -> r!.("a") := 1; -> Display(r!.("a")); -> Display(IsBound(r!.("a"))); -> Unbind(r!.("a")); -> Display(IsBound(r!.("a"))); -> end(); +gap> function() r!.("a") := 1; end(); +gap> ({}-> r!.("a") )(); 1 +gap> ({}-> IsBound(r!.("a")) )(); true -false +gap> function() Unbind(r!.("a")); end(); # # lists # +gap> l := ({}-> [1,2,3] )(); +[ 1, 2, 3 ] gap> function() > local l; > l:=[1,2,3]; @@ -221,17 +215,6 @@ Error, PosObj Assignment: must be a positive small integer (not the\ # gap> l := Objectify(NewType(NewFamily("MockFamily"), IsPositionalObjectRep),[]);; -# -gap> l![1] := 42; -42 -gap> l![1]; -42 -gap> IsBound(l![1]); -true -gap> Unbind(l![1]); -gap> IsBound(l![1]); -false - # gap> function() > l![1] := 42; @@ -263,17 +246,6 @@ Error, PosObj Assignment: must be a positive small integer (not the\ # gap> l := Objectify(NewType(NewFamily("MockFamily"), IsAtomicPositionalObjectRep),[23]);; -# -gap> l![1] := 42; -42 -gap> l![1]; -42 -gap> IsBound(l![1]); -true -gap> Unbind(l![1]); -gap> IsBound(l![1]); -false - # gap> function() > l![1] := 42; diff --git a/tst/testinstall/combinat.tst b/tst/testinstall/combinat.tst index f1bf71034f..5b027dac88 100644 --- a/tst/testinstall/combinat.tst +++ b/tst/testinstall/combinat.tst @@ -2,7 +2,7 @@ ## ## This file tests the functions that mainly deal with combinatorics. ## -#@local n,mset,comb1,comb2,comb3,it,pn1,pn2,s,k,x +#@local n,mset,comb1,comb2,comb3,it,pn1,pn2,s,k,x,y gap> START_TEST("combinat.tst"); @@ -549,6 +549,143 @@ gap> for s in [[], [5], [1,2,3,4], [2,5,7], ["a","b","c","d","e"], [3..9]] do > od; > od; +#F EnumeratorOfPartitionsSet( [, [, ] ] ) +gap> EnumeratorOfPartitionsSet(); +Error, Function: number of arguments must be at least 1 (not 0) +gap> EnumeratorOfPartitionsSet(fail); +Error, EnumeratorOfPartitionsSet: must be a set +gap> EnumeratorOfPartitionsSet([],fail); +Error, EnumeratorOfPartitionsSet: must be an integer +gap> EnumeratorOfPartitionsSet([1],1,fail); +Error, EnumeratorOfPartitionsSet: must be true or false +gap> EnumeratorOfPartitionsSet([1],1,true,"too many"); +Error, usage: EnumeratorOfPartitionsSet( [, [, ] ] ) +gap> for s in [ +> [], [5], [1, 2, 3, 4], [2, 5, 7], ["a", "b", "c", "d", "e"], [3 .. 9], +> [[1], [1, 2], [2, 3], [4]], ["a", "ab", "c"], "abcd" +> ] do +> pn1 := PartitionsSet(s); +> pn2 := List(EnumeratorOfPartitionsSet(s)); +> if Length(pn1) <> Length(pn2) then +> Error("wrong number of elements for s = ", s); +> elif Set(pn1) <> Set(pn2) then +> Error("different elements for s = ", s); +> fi; +> for y in pn1 do +> if Position(pn2, y) = fail then +> Error("did not find position of element y = ", y, " when s = ", s); +> fi; +> if pn2[Position(pn2, y)] <> y then +> Error("position does not cancel for y = ", y, " when s = ", s); +> fi; +> od; +> for k in [0 .. Size(s) + 1] do +> pn1 := PartitionsSet(s, k); +> pn2 := List(EnumeratorOfPartitionsSet(s, k)); +> if Length(pn1) <> Length(pn2) then +> Error("wrong number of elements for s = ", s, ", k = ", k); +> elif Set(pn1) <> Set(pn2) then +> Error("different elements for s = ", s, ", k = ", k); +> fi; +> for y in pn1 do +> if Position(pn2, y) = fail then +> Error("did not find position of element y = ", y, " when s = ", s); +> fi; +> if pn2[Position(pn2, y)] <> y then +> Error("position does not cancel for y = ", y, " when s = ", s); +> fi; +> od; +> od; +> for k in [0 .. Size(s) + 1] do +> pn1:= []; +> for x in [0 .. k] do +> Append(pn1, PartitionsSet(s, x)); +> od; +> pn2:= List(IteratorOfPartitionsSet(s, k, true)); +> if Length(pn1) <> Length(pn2) then +> Error("wrong number of elements for s = ", s, ", k <= ", k); +> elif Set(pn1) <> Set(pn2) then +> Error("different elements for s = ", s, ", k <= ", k); +> fi; +> for y in pn1 do +> if Position(pn2, y) = fail then +> Error("did not find position of element y = ", y, " when s = ", s); +> fi; +> if pn2[Position(pn2, y)] <> y then +> Error("position does not cancel for y = ", y, " when s = ", s); +> fi; +> od; +> od; +> od; +gap> pn2 := EnumeratorOfPartitionsSet(["a", "ab", "c", "cd"]);; +gap> Position(pn2, [["a", "ab", "c"], ["cd"]]); +2 +gap> Position(pn2, [["a", "ab"], ["c"], ["cd"]]); +9 +gap> Position(pn2, [["cd"], ["a", "ab", "c"]]); +fail +gap> Position(pn2, [["a", "c", "ab"], ["cd"]]); +fail +gap> Position(pn2, [["a", "ab", "c"], ["d"]]); +fail +gap> Position(pn2, [["a", "ab", "c"], "cd"]); +fail +gap> Position(pn2, [1, 2]); +fail +gap> Position(pn2, 1); +fail +gap> pn2 := EnumeratorOfPartitionsSet(["a", "ab", "c", "cd"], 2);; +gap> Position(pn2, [["a", "ab", "c"], ["cd"]]); +1 +gap> Position(pn2, [["a", "ab"], ["c"], ["cd"]]); +fail +gap> Position(pn2, [["cd"], ["a", "ab", "c"]]); +fail +gap> Position(pn2, [["a", "c", "ab"], ["cd"]]); +fail +gap> Position(pn2, [["a", "ab", "c"], ["d"]]); +fail +gap> Position(pn2, [["a", "ab", "c"], "cd"]); +fail +gap> Position(pn2, [1, 2]); +fail +gap> Position(pn2, 1); +fail +gap> pn2 := EnumeratorOfPartitionsSet(["a", "ab", "c", "cd"], 2, false);; +gap> Position(pn2, [["a", "ab", "c"], ["cd"]]); +1 +gap> Position(pn2, [["a", "ab"], ["c"], ["cd"]]); +fail +gap> Position(pn2, [["cd"], ["a", "ab", "c"]]); +fail +gap> Position(pn2, [["a", "c", "ab"], ["cd"]]); +fail +gap> Position(pn2, [["a", "ab", "c"], ["d"]]); +fail +gap> Position(pn2, [["a", "ab", "c"], "cd"]); +fail +gap> Position(pn2, [1, 2]); +fail +gap> Position(pn2, 1); +fail +gap> pn2 := EnumeratorOfPartitionsSet(["a", "ab", "c", "cd"], 2, true);; +gap> Position(pn2, [["a", "ab", "c"], ["cd"]]); +2 +gap> Position(pn2, [["a", "ab"], ["c"], ["cd"]]); +fail +gap> Position(pn2, [["cd"], ["a", "ab", "c"]]); +fail +gap> Position(pn2, [["a", "c", "ab"], ["cd"]]); +fail +gap> Position(pn2, [["a", "ab", "c"], ["d"]]); +fail +gap> Position(pn2, [["a", "ab", "c"], "cd"]); +fail +gap> Position(pn2, [1, 2]); +fail +gap> Position(pn2, 1); +fail + #F Lucas(

,,) . . . . . . . . . . . . . . value of a lucas sequence gap> Print(List( [0..10], i->Lucas(1,-2,i)[1] ),"\n"); [ 0, 1, 1, 3, 5, 11, 21, 43, 85, 171, 341 ] diff --git a/tst/testinstall/ctbl.tst b/tst/testinstall/ctbl.tst index 47cba12b4e..3f5ec76722 100644 --- a/tst/testinstall/ctbl.tst +++ b/tst/testinstall/ctbl.tst @@ -381,6 +381,15 @@ true gap> IsPerfectCharacterTable( t ); false +# test another bugfix +gap> G:= SymmetricGroup( 2 );; +gap> SetConjugacyClasses( G, +> List( [ (1,2), () ], x -> ConjugacyClass( G, x ) ) ); +gap> t:= CharacterTable( G );; +gap> lin:= Irr( t );; +gap> lin[1][1]; +1 + # compute indicators gap> t:= CharacterTable( SymmetricGroup( 4 ) );; gap> Indicator( t, 2 ); @@ -434,19 +443,19 @@ gap> HasIsIrreducibleCharacter( TrivialCharacter( SymmetricGroup( 4 ) ) ); true # concurring 'Irr' methods -gap> G:= SmallGroup( 24, 5 );; +gap> G:= PcGroupCode( 221729, 24 );; # = SmallGroup( 24, 5 ) gap> IsSupersolvable( G ); true gap> Irr( G );; gap> InfoText( OrdinaryCharacterTable( G ) ); "origin: Baum-Clausen Algorithm" -gap> G:= SmallGroup( 24, 5 );; +gap> G:= PcGroupCode( 221729, 24 );; # = SmallGroup( 24, 5 ) gap> IsSupersolvable( G ); true gap> IrrConlon( G );; Irr( G );; gap> InfoText( OrdinaryCharacterTable( G ) ); "origin: Conlon's Algorithm" -gap> G:= SmallGroup( 24, 5 );; +gap> G:= PcGroupCode( 221729, 24 );; # = SmallGroup( 24, 5 ) gap> IrrDixonSchneider( G );; Irr( G );; gap> InfoText( OrdinaryCharacterTable( G ) ); "origin: Dixon's Algorithm" diff --git a/tst/testinstall/ctblmaps.tst b/tst/testinstall/ctblmaps.tst index a40f5bb942..3d36393af9 100644 --- a/tst/testinstall/ctblmaps.tst +++ b/tst/testinstall/ctblmaps.tst @@ -3,8 +3,7 @@ gap> START_TEST( "ctblmaps.tst" ); # `ConsiderStructureConstants` can unexpectedly exclude all candidates. # (Benjamin Sambale found examples for that.) -gap> if TestPackageAvailability("ctbllib") <> fail and -> LoadPackage("ctbllib", false) <> fail then +gap> if IsPackageMarkedForLoading( "ctbllib", "" ) then > s:= CharacterTable( "2.A6" );; > t:= CharacterTable( "Co3" );; > maps:= [ [ 1, 2, 8, 4, 11, 4, 13, 18, 18, 9, 22, 9, 22 ], diff --git a/tst/testinstall/ctblmono.tst b/tst/testinstall/ctblmono.tst index 0b57b930b0..bb9c88e01e 100644 --- a/tst/testinstall/ctblmono.tst +++ b/tst/testinstall/ctblmono.tst @@ -96,6 +96,8 @@ gap> TestMonomial( irr[2] ); rec( comment := "whole group is monomial", isMonomial := true ) gap> IsMonomial( irr[2] ); true + +# gap> irr:= Irr( SL(2,3) );; gap> chi:= First( irr, x -> x[1] = 3 );; gap> TestMonomialQuick( chi ); @@ -104,6 +106,8 @@ gap> TestMonomial( chi ); rec( comment := "codegree is prime power", isMonomial := true ) gap> IsMonomial( chi ); true + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> irr:= Irr( SmallGroup( 120, 15 ) );; gap> chi:= First( irr, x -> x[1] = 3 and > Length( ClassPositionsOfKernel( x ) ) = 2 );; @@ -121,6 +125,9 @@ gap> TestMonomial( chi ); rec( comment := "induced from monomial Hall subgroup", isMonomial := true ) gap> IsMonomial( chi ); true +#@fi + +# gap> g:= DirectProduct( AlternatingGroup(5), SymmetricGroup(3), > SymmetricGroup(3) );; gap> chi:= First( Irr( g ), x -> x[1] = 2 and @@ -131,6 +138,8 @@ gap> TestMonomial( chi ); rec( comment := "kernel factor group is supersolvable", isMonomial := true ) gap> IsMonomial( chi ); true + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> irr:= Irr( SmallGroup( 144, 31 ) );; gap> chi:= First( irr, x -> x[1] = 6 );; gap> TestMonomialQuick( chi ); @@ -139,6 +148,9 @@ gap> TestMonomial( chi ); rec( comment := "kernel factor group is monomial", isMonomial := true ) gap> IsMonomial( chi ); true +#@fi + +# gap> irr:= Irr( SL(2,3) );; gap> chi:= First( irr, x -> x[1] = 2 );; gap> TestMonomialQuick( chi ); @@ -147,6 +159,8 @@ gap> TestMonomial( chi ); rec( comment := "quasiprimitive character", isMonomial := false ) gap> IsMonomial( chi ); false + +# gap> irr:= Irr( AlternatingGroup( 5 ) );; gap> chi:= First( irr, x -> x[1] = 5 );; gap> TestMonomialQuick( chi ); @@ -166,6 +180,8 @@ gap> TestMonomial( chi, true ).comment; "lattice checked" gap> IsMonomial( chi ); false + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> irr:= Irr( SmallGroup( 96, 204 ) );; gap> chi:= First( irr, x -> x[1] = 4 );; gap> TestMonomialQuick( chi ); @@ -174,6 +190,9 @@ gap> TestMonomial( chi ).comment; "induced from 'character'" gap> IsMonomial( chi ); true +#@fi + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> chi:= First( Irr( SmallGroup( 144, 31 ) ), x -> x[1] = 4 );; gap> TestMonomialQuick( chi ); rec( comment := "no decision by cheap tests", isMonomial := "?" ) @@ -183,6 +202,9 @@ gap> TestMonomial( chi, true ).comment; "induced from 'character'" gap> IsMonomial( chi ); true +#@fi + +# gap> chi:= 0 * [ 1 .. NrConjugacyClasses( S4 ) ];; gap> chi[1]:= Size( S4 );; gap> chi:= ClassFunction( S4, chi );; @@ -193,6 +215,8 @@ gap> TestMonomial( chi, true ).comment; gap> IsMonomial( chi ); true gap> TestMonomialUseLattice:= TestMonomialUseLattice_Orig;; + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> chi:= First( Irr( SmallGroup( 48, 28 ) ), x -> x[1] = 4 );; gap> TestMonomialQuick( chi ); rec( comment := "no decision by cheap tests", isMonomial := "?" ) @@ -200,6 +224,7 @@ gap> TestMonomial( chi ).comment; "induced from 'character'" gap> IsMonomial( chi ); true +#@fi ## gap> TestMonomialQuick( S4 ); @@ -214,6 +239,8 @@ gap> TestMonomial( Sl23 ); rec( comment := "list Delta( G ) contains entry > 1", isMonomial := false ) gap> IsMonomial( Sl23 ); false + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> g:= SmallGroup( 96, 204 );; gap> TestMonomialQuick( g ); rec( comment := "no decision by cheap tests", isMonomial := "?" ) @@ -239,6 +266,9 @@ gap> TestMonomial( g ); rec( comment := "was already stored", isMonomial := true ) gap> IsMonomial( g ); true +#@fi + +# gap> g:= AlternatingGroup( 5 );; gap> TestMonomialQuick( g ); rec( comment := "non-solvable group", isMonomial := false ) @@ -246,6 +276,8 @@ gap> TestMonomial( g ); rec( comment := "non-solvable group", isMonomial := false ) gap> IsMonomial( g ); false + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> g:= SmallGroup( 56, 10 );; gap> TestMonomialQuick( g ); rec( comment := "group order is monomial", isMonomial := true ) @@ -274,6 +306,7 @@ gap> TestMonomial( g ); rec( comment := "Sylow abelian by supersolvable group", isMonomial := true ) gap> IsMonomial( g ); true +#@fi ## gap> TestSubnormallyMonomial( S4 ); diff --git a/tst/testinstall/ctblsolv.tst b/tst/testinstall/ctblsolv.tst index 231e87319f..28a6955f0c 100644 --- a/tst/testinstall/ctblsolv.tst +++ b/tst/testinstall/ctblsolv.tst @@ -1,7 +1,7 @@ #@local G, pair, mth, all, rks, tbl gap> START_TEST("ctblsolv.tst"); -## +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> CharacterDegrees( SmallGroup( 256, 529 ) ); [ [ 1, 8 ], [ 2, 30 ], [ 4, 8 ] ] gap> for pair in [ [ 18, 3 ], [ 27, 3 ], [ 36, 7 ], [ 50, 3 ], [ 54, 4 ] ] do @@ -11,6 +11,7 @@ gap> for pair in [ [ 18, 3 ], [ 27, 3 ], [ 36, 7 ], [ 50, 3 ], [ 54, 4 ] ] do > Error( IdGroup( G ) ); > fi; > od; +#@fi ## gap> mth:= [];; @@ -18,11 +19,11 @@ gap> G:= AbelianGroup( [ 2, 3, 5 ] );; gap> Add( mth, ApplicableMethod( CharacterDegrees, [ G ] ) ); gap> CharacterDegrees( G ) = [ [ 1, 30 ] ]; true -gap> G:= SmallGroup( 24, 12 );; Irr( G );; +gap> G:= SymmetricGroup(IsPcGroup, 4);; Irr( G );; gap> Add( mth, ApplicableMethod( CharacterDegrees, [ G ] ) ); gap> CharacterDegrees( G ) = [ [ 1, 2 ], [ 2, 1 ], [ 3, 2 ] ]; true -gap> G:= SmallGroup( 24, 12 );; CharacterTable( G );; +gap> G:= SymmetricGroup(IsPcGroup, 4);; CharacterTable( G );; gap> Add( mth, ApplicableMethod( CharacterDegrees, [ G ] ) ); gap> CharacterDegrees( G ) = [ [ 1, 2 ], [ 2, 1 ], [ 3, 2 ] ]; true @@ -34,7 +35,7 @@ gap> G:= Group( [ [ E(3) ] ], [ [ E(4) ] ] );; gap> Add( mth, ApplicableMethod( CharacterDegrees, [ G ] ) ); gap> CharacterDegrees( G ) = [ [ 1, 12 ] ]; true -gap> G:= SmallGroup( 24, 12 );; # hier: auch überaufl.!!! +gap> G:= SymmetricGroup(IsPcGroup, 4);; # hier: auch überaufl.!!! gap> Add( mth, ApplicableMethod( CharacterDegrees, [ G ] ) ); gap> CharacterDegrees( G ) = [ [ 1, 2 ], [ 2, 1 ], [ 3, 2 ] ]; true 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/grp/basic.tst b/tst/testinstall/grp/basic.tst index b557cab1be..90254cc625 100644 --- a/tst/testinstall/grp/basic.tst +++ b/tst/testinstall/grp/basic.tst @@ -271,10 +271,10 @@ true # # dicyclic groups # -gap> IdGroup(DicyclicGroup(4)); -[ 4, 1 ] -gap> IdGroup(DicyclicGroup(IsFpGroup,4)); -[ 4, 1 ] +gap> StructureDescription(DicyclicGroup(4)); +"C4" +gap> StructureDescription(DicyclicGroup(IsFpGroup,4)); +"C4" gap> DicyclicGroup(8); gap> DicyclicGroup(IsPcGroup,8); @@ -340,10 +340,12 @@ gap> for n in [ 4, 12, 20, 24 ] do > Error( "gen. quat. group?" ); > fi; > od; +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> Number( AllSmallGroups( [ 1 .. 32 ], IsDicyclicGroup ) ); 8 gap> Number( AllSmallGroups( [ 1 .. 32 ], IsGeneralisedQuaternionGroup ) ); 3 +#@fi # gap> Q:= DicyclicGroup( 20 );; diff --git a/tst/testinstall/grpfp.tst b/tst/testinstall/grpfp.tst index 247402f216..0403a75baf 100644 --- a/tst/testinstall/grpfp.tst +++ b/tst/testinstall/grpfp.tst @@ -162,6 +162,7 @@ false Error, the f.p. group is not finite # RWS for G2(3) and S_6(2) +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> g:=SimpleGroup("G2(3)");; gap> hom:=IsomorphismFpGroupForRewriting(g);; gap> m:=Image(IsomorphismFpMonoid(Image(hom)));; @@ -169,6 +170,9 @@ gap> F:=m!.rewritingSystem;;; gap> ReducedForm(F,UnderlyingElement( > Product(GeneratorsOfMonoid(m){[1,3..19]}))); w1*B5*b6*b7*B8*w2*b1*B3*B4*b5*b6*b7 +#@fi + +# gap> g:=SimpleGroup("S6(2)");; gap> hom:=IsomorphismFpGroupForRewriting(g);; gap> m:=Image(IsomorphismFpMonoid(Image(hom)));; diff --git a/tst/testinstall/grpmat.tst b/tst/testinstall/grpmat.tst index 4c23741723..8ac7e4db9e 100644 --- a/tst/testinstall/grpmat.tst +++ b/tst/testinstall/grpmat.tst @@ -86,8 +86,26 @@ gap> TrivialSubgroup( GL(2, 2) ); # The following should take less than a second. +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> Length( LowIndexSubgroups( GL(2,5), 50 ) ) = 31; true +#@fi + +# 'NiceMonomorphism' behaves well w.r.t. 'ConstructingFilter' +gap> G:= SP( 4, 2 );; +gap> nice:= NiceMonomorphism( G );; +gap> G2:= SP( 4, 2 : ConstructingFilter:= IsPlistMatrixRep );; +gap> nice2:= NiceMonomorphism( G2 );; +gap> IsPlistMatrixRep( One( G ) ); +false +gap> IsPlistMatrixRep( One( G2 ) ); +true +gap> IsIdenticalObj( nice, nice2 ); +false +gap> IsSubset( Source( nice ), G ); +true +gap> IsSubset( Source( nice2 ), G2 ); +true # 'NiceMonomorphism' behaves well w.r.t. 'ConstructingFilter' gap> G:= SP( 4, 2 );; diff --git a/tst/testinstall/grppc.tst b/tst/testinstall/grppc.tst index f526eba327..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);; @@ -137,7 +147,7 @@ gap> List( sys, Size ); [ 4, 7 ] gap> List(sys,i->Length(AsList(i))); [ 4, 7 ] -gap> G := SmallGroup( 144, 183 );; +gap> G := DirectProduct(SymmetricGroup(IsPcGroup, 3), SymmetricGroup(IsPcGroup, 4));; gap> F := FittingSubgroup( G );; gap> S := SylowSubgroup( F, 2 );; gap> Display(Image(IsomorphismPcGroup(S))); @@ -166,7 +176,7 @@ gap> RepresentativeAction(G,x,x^2)<>fail; true gap> RepresentativeAction(G,x,x^2); f1*f2 -gap> g := SmallGroup(243,27);; +gap> g := PcGroupCode(14055476799225975, 243);; # = SmallGroup(243,27) gap> AsSet(Omega(g,3,1)) = Set(Filtered(g, g -> IsOne(g^3))); true gap> AsSet(Omega(g,3,2)) = Set(Filtered(g, g -> IsOne(g^9))); @@ -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/interpreter.tst b/tst/testinstall/interpreter.tst index 5c758de733..f10a18035d 100644 --- a/tst/testinstall/interpreter.tst +++ b/tst/testinstall/interpreter.tst @@ -1,3 +1,4 @@ +#@local f,r,l # # Tests for the GAP interpreter logic. # @@ -14,14 +15,6 @@ gap> START_TEST("interpreter.tst"); gap> if 1 then fi; Error, must be 'true' or 'false' (not the integer 1) -# -# 'quit' inside functions -# -gap> function() quit; end; -Syntax error: 'quit;' cannot be used in this context in stream:1 -function() quit; end; - ^^^^ - # # return is not allowed in interpreter # @@ -30,17 +23,13 @@ gap> return; gap> return 1; 'return' must not be used in file read-eval loop -# -# isolated quit and QUIT are ignore in test files -# -gap> quit; -gap> QUIT; - # # help system # +#@if IsPackageMarkedForLoading( "gapdoc", "" ) gap> ?qwert_asdf Help: no matching entry found +#@fi # # function call with options 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/mapphomo.tst b/tst/testinstall/mapphomo.tst index 3e7a7f49ce..d6468f7834 100644 --- a/tst/testinstall/mapphomo.tst +++ b/tst/testinstall/mapphomo.tst @@ -86,7 +86,7 @@ gap> One( hom ); fail # Check that group homomorphisms created by a function can compute preimages. -gap> for G in [ SymmetricGroup(5), SmallGroup( 24, 12 ), GL(2,3) ] do +gap> for G in [ SymmetricGroup(5), DihedralGroup(8), GL(2,3) ] do > hom:= GroupHomomorphismByFunction( G, G, x -> x ); > PreImagesRepresentative( hom, G.1 ); > od; diff --git a/tst/testinstall/mat8bit.tst b/tst/testinstall/mat8bit.tst index 18e97658d4..db1316d4bd 100644 --- a/tst/testinstall/mat8bit.tst +++ b/tst/testinstall/mat8bit.tst @@ -564,9 +564,32 @@ gap> m := [m[1], mm[1], m[2], mm[2],[]]; , , [ ] ] gap> ConvertToMatrixRep(m); fail +gap> m:= [ [ Z(3) ] ];; +gap> ConvertToVectorRep( m[1], 9 ) = 9; +true +gap> ConvertToMatrixRep( m, 3 ) = 3; +true +gap> m:= [ [ Z(3) ] ];; +gap> ConvertToVectorRep( m[1], 27 ) = 27; +true +gap> ConvertToMatrixRep( m, 9 ) = 9; +true +gap> m:= [ [ Z(3) ] ];; +gap> ConvertToVectorRep( m[1], 9 ) = 9; +true +gap> ConvertToMatrixRep( m, 27 ) = 27; +true +gap> m:= [ [ Z(9) ] ];; +gap> ConvertToVectorRep( m[1], 3 ) = 9; +Error, ConvertToVectorRepNC: Vector cannot be written over GF(3) +gap> ConvertToVectorRep( m[1], 9 ); +9 +gap> ConvertToMatrixRep( m, 3 ); +Error, ConvertToMatrixRep( , ): not all entries of written over\ + # ConvertToMatrixRepNC -gap> ConvertToMatrixRepNC([], 3); +gap> ConvertToMatrixRepNC([], 3); # What is this test supposed to show? 3 # DefaultFieldOfMatrix diff --git a/tst/testinstall/matblock.tst b/tst/testinstall/matblock.tst index f646628043..4043a465e8 100644 --- a/tst/testinstall/matblock.tst +++ b/tst/testinstall/matblock.tst @@ -138,7 +138,7 @@ gap> MinimalPolynomial( R, m2 ) = MinimalPolynomial( R, MatrixByBlockMatrix( m2 true # Groups that consist of block matrices -gap> G:= SmallGroup( 24, 12 );; +gap> G:= SymmetricGroup(IsPcGroup, 4);; gap> H:= SylowSubgroup( G, 2 );; gap> reps:= IrreducibleRepresentations( H );; gap> ind:= InducedRepresentation( reps[5], G );; 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/meatauto.tst b/tst/testinstall/meatauto.tst index 5f7d064756..a51d6ec0f6 100644 --- a/tst/testinstall/meatauto.tst +++ b/tst/testinstall/meatauto.tst @@ -12,7 +12,7 @@ gap> SMTX_NullspaceEqns(e); # # MTX.BasisModuleEndomorphisms # -gap> G:=SmallGroup(24, 3);; +gap> G:=SL(2, 3);; gap> p:=NextPrimeInt(100);; gap> M:=RegularModule(G, GF(p))[2];; gap> MTX.BasisModuleEndomorphisms(M); @@ -44,7 +44,7 @@ gap> MTX.BasisModuleEndomorphisms(M); # # MTX.HomogeneousComponents # -gap> G:=SmallGroup(24, 3);; +gap> G:=SL(2, 3);; gap> p:=NextPrimeInt(100);; gap> M:=RegularModule(G, GF(p))[2];; gap> hc := MTX.HomogeneousComponents(M);; diff --git a/tst/testinstall/meataxe.tst b/tst/testinstall/meataxe.tst index 55dc6c66b2..7e076f17d9 100644 --- a/tst/testinstall/meataxe.tst +++ b/tst/testinstall/meataxe.tst @@ -77,8 +77,10 @@ gap> M2:=TensorProductGModule(M,M); rec( IsOverFiniteField := true, dimension := 9, field := GF(2), generators := [ , ], isMTXModule := true ) -gap> IdGroup(MTX.ModuleAutomorphisms(M2)); -[ 1344, 11301 ] +gap> G:=MTX.ModuleAutomorphisms(M2); + +gap> StructureDescription(G); +"PSL(3,2) x D8" gap> cf:=MTX.CompositionFactors(M2);; gap> ForAll(cf, MTX.IsAbsolutelyIrreducible); true @@ -138,8 +140,8 @@ false # gap> M2:=First(MTX.CompositionFactors(M), m -> m.dimension = 4);; -gap> IdGroup(MTX.ModuleAutomorphisms(M2)); -[ 48, 2 ] +gap> StructureDescription(MTX.ModuleAutomorphisms(M2)); +"C48" gap> MTX.IsIndecomposable(M2); true gap> MTX.IsAbsolutelyIrreducible(M2); diff --git a/tst/testinstall/opers/FittingSubgroup.tst b/tst/testinstall/opers/FittingSubgroup.tst index 172a085e1f..022d10290c 100644 --- a/tst/testinstall/opers/FittingSubgroup.tst +++ b/tst/testinstall/opers/FittingSubgroup.tst @@ -15,11 +15,12 @@ gap> G := CyclicGroup(IsPcGroup, 12);; gap> IsIdenticalObj(G, FittingSubgroup(G)); true -# +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> List(AllSmallGroups(60), g -> Size(FittingSubgroup(g))); [ 30, 30, 30, 60, 1, 15, 15, 15, 20, 30, 30, 30, 60 ] gap> ForAll(AllSmallGroups(60), g -> IsNormal(g, FittingSubgroup(g))); true +#@fi # gap> g := SL(2,5);; diff --git a/tst/testinstall/opers/FrattiniSubgroup.tst b/tst/testinstall/opers/FrattiniSubgroup.tst index 2646c8764c..5064529c1b 100644 --- a/tst/testinstall/opers/FrattiniSubgroup.tst +++ b/tst/testinstall/opers/FrattiniSubgroup.tst @@ -16,12 +16,12 @@ gap> HasIsAbelian(FrattiniSubgroup(G)); true gap> GeneratorsOfGroup(FrattiniSubgroup(G)); [ (x^-195*y^196)^6, (x^-1*y)^630, (x^-1*y)^840 ] -gap> G := DirectProduct(DihedralGroup(IsPcGroup,8), SmallGroup(27,4));; +gap> G := DirectProduct(DihedralGroup(8), ExtraspecialGroup(27,9));; gap> IsNilpotentGroup(G); true gap> F := FrattiniSubgroup(G);; -gap> IdGroup(F); -[ 6, 2 ] +gap> StructureDescription(F); +"C6" gap> HasIsNilpotentGroup(F); true @@ -43,11 +43,12 @@ Group([ ]) gap> AsSet( FrattiniSubgroup(CyclicGroup(IsPcGroup, 9)) ); [ of ..., f2, f2^2 ] -# +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> List(AllSmallGroups(60), g -> Size(FrattiniSubgroup(g))); [ 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] gap> ForAll(AllSmallGroups(60), g -> IsNormal(g, FrattiniSubgroup(g))); true +#@fi # gap> g := SL(2,5);; diff --git a/tst/testinstall/opers/HallSubgroup.tst b/tst/testinstall/opers/HallSubgroup.tst index bf05ddecc7..7435808bbf 100644 --- a/tst/testinstall/opers/HallSubgroup.tst +++ b/tst/testinstall/opers/HallSubgroup.tst @@ -2,20 +2,25 @@ gap> START_TEST("HallSubgroup.tst"); gap> G := GL(3,4);; gap> HallSubgroup(G, [2,3]); fail + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> G := PSL(4,2);; gap> IdGroup(HallSubgroup(G, [2,3])); [ 576, 8654 ] gap> G := PSp(4,5);; gap> IdGroup(HallSubgroup(G,[2,3])); [ 576, 8277 ] +#@fi + +# gap> G := Group([ [ [ Z(2)^0, 0*Z(2), 0*Z(2) ], > [ 0*Z(2), Z(2)^0, 0*Z(2) ], > [ 0*Z(2), Z(2)^0, Z(2)^0 ] ], > [ [ 0*Z(2), Z(2)^0, 0*Z(2) ], > [ 0*Z(2), 0*Z(2), Z(2)^0 ], > [ Z(2)^0, 0*Z(2), 0*Z(2) ] ] ]);; -gap> List(HallSubgroup(G, [2,3]), IdGroup); -[ [ 24, 12 ], [ 24, 12 ] ] +gap> List(HallSubgroup(G, [2,3]), StructureDescription); +[ "S4", "S4" ] # gap> G:=PerfectGroup(IsFpGroup,60,1); diff --git a/tst/testinstall/opers/IsSolvableGroup.tst b/tst/testinstall/opers/IsSolvableGroup.tst index d06f79379f..f1e23afd9d 100644 --- a/tst/testinstall/opers/IsSolvableGroup.tst +++ b/tst/testinstall/opers/IsSolvableGroup.tst @@ -1,9 +1,11 @@ gap> START_TEST("IsSolvableGroup.tst"); +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> List(AllSmallGroups(120), IsSolvableGroup); [ true, true, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, true, true, true, true, true, true, true, true, true, true, true, true ] +#@fi gap> grps := [ > [ (1,2,3,4,5,6,7,8) ], [ (1,2,3,8)(4,5,6,7), (1,5)(2,6)(3,7)(4,8) ], > [ (1,8)(2,3)(4,5)(6,7), (1,3)(2,8)(4,6)(5,7), (1,5)(2,6)(3,7)(4,8) ], diff --git a/tst/testinstall/opers/LatticeByCyclicExtension.tst b/tst/testinstall/opers/LatticeByCyclicExtension.tst index 959f788b0c..779b6fd668 100644 --- a/tst/testinstall/opers/LatticeByCyclicExtension.tst +++ b/tst/testinstall/opers/LatticeByCyclicExtension.tst @@ -1,8 +1,13 @@ gap> START_TEST("LatticeByCyclicExtension.tst"); +# construct SmallGroup(500,1) +gap> H:=CyclicGroup(4);; +gap> N:=CyclicGroup(125);; +gap> A:=AutomorphismGroup(N);; +gap> alpha:=GroupHomomorphismByImages(H,A,[H.1],[A.1^50]);; +gap> G:=SemidirectProduct(H, alpha, N);; + # -gap> G:=SmallGroup(500,1); - gap> fun:=g->IsInt(4/Size(g));; gap> LatticeByCyclicExtension(G); , 12 classes, diff --git a/tst/testinstall/opers/MinimalNormalSubgroups.tst b/tst/testinstall/opers/MinimalNormalSubgroups.tst index f5a7ff3ce7..1983bf5b09 100644 --- a/tst/testinstall/opers/MinimalNormalSubgroups.tst +++ b/tst/testinstall/opers/MinimalNormalSubgroups.tst @@ -7,42 +7,49 @@ gap> G := Group(());; NormalSubgroups(G);; MinimalNormalSubgroups(G); gap> D := DihedralGroup(8);; gap> MinimalNormalSubgroups(D) = [ Center(D) ]; true -gap> List(MinimalNormalSubgroups(D), IdGroup); -[ [ 2, 1 ] ] +gap> List(MinimalNormalSubgroups(D), Size); +[ 2 ] gap> D := DihedralGroup(IsFpGroup, 8);; gap> MinimalNormalSubgroups(D) = [ Center(D) ]; true -gap> List(MinimalNormalSubgroups(D), IdGroup); -[ [ 2, 1 ] ] +gap> List(MinimalNormalSubgroups(D), Size); +[ 2 ] gap> D := Group((1,3),(1,2,3,4));; gap> MinimalNormalSubgroups(D) = [ Center(D) ]; true -gap> List(MinimalNormalSubgroups(D), IdGroup); -[ [ 2, 1 ] ] +gap> List(MinimalNormalSubgroups(D), Size); +[ 2 ] gap> DDD := DirectProduct(D, D, D);; -gap> List(MinimalNormalSubgroups(DDD), IdGroup); -[ [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ] ] +gap> List(MinimalNormalSubgroups(DDD), Size); +[ 2, 2, 2, 2, 2, 2, 2 ] gap> Q := QuaternionGroup(8);; gap> MinimalNormalSubgroups(Q) = [ Center(Q) ]; true -gap> List(MinimalNormalSubgroups(Q), IdGroup); -[ [ 2, 1 ] ] +gap> List(MinimalNormalSubgroups(Q), Size); +[ 2 ] gap> MinimalNormalSubgroups(SymmetricGroup(4)) = [ Group((1,2)(3,4),(1,3)(2,4)) ]; true -gap> List(MinimalNormalSubgroups(SymmetricGroup(5)), IdGroup); -[ [ 60, 5 ] ] -gap> List(MinimalNormalSubgroups(AlternatingGroup(5)), IdGroup); -[ [ 60, 5 ] ] +gap> MinimalNormalSubgroups(SymmetricGroup(5)) = [ AlternatingGroup(5) ]; +true +gap> MinimalNormalSubgroups(AlternatingGroup(5)) = [ AlternatingGroup(5) ]; +true + +# gap> G := Group((1,2),(3,4),(5,6),(7,8));; gap> IsElementaryAbelian(G); true gap> Size(MinimalNormalSubgroups(G)); 15 -gap> MinimalNormalSubgroups(PrimitiveGroup(8,3)) = [ Group([ (1,7)(2,8)(3,5)(4,6), (1,3)(2,4)(5,7)(6,8), (1,2)(3,4)(5,6)(7,8) ]) ]; + +# +gap> G := Group((2,7,4,8,6,5,3), (2,3)(6,7), (1,2)(3,4)(5,6)(7,8));; # = PrimitiveGroup(8,3) +gap> MinimalNormalSubgroups(G) = [ Group([ (1,7)(2,8)(3,5)(4,6), (1,3)(2,4)(5,7)(6,8), (1,2)(3,4)(5,6)(7,8) ]) ]; true gap> k := 5;; P := SylowSubgroup(SymmetricGroup(4*k), 2);; A := Group((4*k+1, 4*k+2, 4*k+3));; G := ClosureGroup(P, A);; IsNilpotentGroup(G);; gap> Set(MinimalNormalSubgroups(G)) = Set([ Group([ (1,2)(3,4)(5,6)(7,8)(9,10)(11,12)(13,14)(15,16) ]), Group([ (17,18)(19,20) ]), Group([ (1,2)(3,4)(5,6)(7,8)(9,10)(11,12)(13,14)(15,16)(17,18)(19,20) ]), Group([ (21,22,23) ]) ]); true + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> G := SmallGroup(24,12);; gap> SortedList(List(MinimalNormalSubgroups(G), IdGroup)); [ [ 4, 2 ] ] @@ -50,13 +57,12 @@ gap> A := DihedralGroup(16);; gap> B := SmallGroup(27, 3);; gap> C := SmallGroup(125, 4);; gap> D := DirectProduct(A, B, C, SmallGroup(1536, 2));; -gap> SortedList(List(MinimalNormalSubgroups(D), IdGroup)); -[ [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], - [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], - [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], - [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], - [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 3, 1 ], [ 3, 1 ], [ 3, 1 ], [ 3, 1 ], - [ 5, 1 ] ] +gap> SortedList(List(MinimalNormalSubgroups(D), Size)); +[ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 5 ] +#@fi + +# gap> G := Group([ (4,8)(6,10), (4,6,10,8,12), (2,4,12)(6,10,8), (3,9)(4,6,10,8,12)(7,11), (3,5)(4,6,10,8,12)(9,11), (1,3,11,9,5)(4,6,10,8,12) ]);; gap> Set(MinimalNormalSubgroups(G)) = Set([ Group([ (6,12)(8,10), (2,10)(4,12), (2,12)(6,10) ]), Group([ (5,11)(7,9), (3,9)(7,11), (1,9,5,11,7) ]) ]); true @@ -69,6 +75,8 @@ gap> G := F/[x^2, y^2, x^(-1)*y^(-1)*x*y, z];; gap> IsFinite(G);; gap> Size(MinimalNormalSubgroups(G)); 3 + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> for G in AllSmallGroups(60) do NormalSubgroups(G);; Print(Collected(List(Set(MinimalNormalSubgroups(G)), IdGroup)), "\n"); od; [ [ [ 2, 1 ], 1 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ] [ [ [ 2, 1 ], 1 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ] @@ -105,6 +113,9 @@ gap> for G in AllSmallGroups(360) do if not IsSolvable(G) then NormalSubgroups(G [ [ 3, 1 ], [ 60, 5 ] ] [ [ 3, 1 ], [ 60, 5 ] ] [ [ 2, 1 ], [ 3, 1 ], [ 60, 5 ] ] +#@fi + +# gap> G := AbelianGroup([2, 3, 4, 5, 6, 7, 8, 9, 10]);; gap> Collected(List(Set(MinimalNormalSubgroups(G)), Size)); [ [ 2, 31 ], [ 3, 13 ], [ 5, 6 ], [ 7, 1 ] ] @@ -114,4 +125,6 @@ gap> Collected(List(Set(MinimalNormalSubgroups(G)), Size)); gap> G := ElementaryAbelianGroup(7^4);; gap> Collected(List(Set(MinimalNormalSubgroups(G)), Size)); [ [ 7, 400 ] ] + +# gap> STOP_TEST("Socle.tst"); diff --git a/tst/testinstall/opers/NormalHallSubgroups.tst b/tst/testinstall/opers/NormalHallSubgroups.tst index 2278d619dc..63dcf7af29 100644 --- a/tst/testinstall/opers/NormalHallSubgroups.tst +++ b/tst/testinstall/opers/NormalHallSubgroups.tst @@ -1,4 +1,5 @@ gap> START_TEST("NormalHallSubgroups.tst"); +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> for G in AllSmallGroups(60) do Print(List(NormalHallSubgroups(G), IdGroup), "\n"); od; [ [ 1, 1 ], [ 5, 1 ], [ 3, 1 ], [ 15, 1 ], [ 12, 1 ], [ 60, 1 ] ] [ [ 1, 1 ], [ 3, 1 ], [ 5, 1 ], [ 15, 1 ], [ 20, 1 ], [ 60, 2 ] ] @@ -40,11 +41,18 @@ gap> List(AllSmallGroups(168), G -> List(NormalHallSubgroups(G), Size)); [ 1, 8, 7, 56, 168 ], [ 1, 3, 7, 56, 21, 168 ], [ 1, 7, 3, 24, 21, 168 ], [ 1, 3, 7, 21, 168 ], [ 1, 8, 3, 24, 7, 56, 21, 168 ] ] gap> for G in AllSmallGroups(168) do primes := PrimeDivisors(Size(G)); l := []; for pi in IteratorOfCombinations(primes) do N := HallSubgroup(G, pi); if N<>fail and IsGroup(N) and IsNormal(G, N) then AddSet(l, N); fi; od; if l <> NormalHallSubgroups(G) then Print(IdGroup(G), "\n"); fi; od; +#@fi + +# +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> List(AllPrimitiveGroups(DegreeAction, 8), G -> List(NormalHallSubgroups(G), Size)); [ [ 1, 56, 8 ], [ 1, 168, 56, 8 ], [ 1, 1344 ], [ 1, 168 ], [ 1, 336 ], [ 1, 20160 ], [ 1, 40320 ] ] gap> List(NormalHallSubgroups(PrimitiveGroup(8,2)), Size); [ 1, 168, 56, 8 ] +#@fi + +# gap> grps := [ [ (1,2,3,4,5,6) ], [ (1,3,5)(2,4,6), (1,4)(2,3)(5,6) ], > [ (1,2,3,4,5,6), (1,4)(2,3)(5,6) ], [ (1,4)(2,5), (1,3,5)(2,4,6) ], > [ (2,4,6), (1,4)(2,5)(3,6) ], [ (3,6), (1,3,5)(2,4,6) ], diff --git a/tst/testinstall/opers/SimpleGroup.tst b/tst/testinstall/opers/SimpleGroup.tst index cd2940f33d..72494f41d4 100644 --- a/tst/testinstall/opers/SimpleGroup.tst +++ b/tst/testinstall/opers/SimpleGroup.tst @@ -31,6 +31,7 @@ M11 rec( name := "M(11)", series := "Spor", shortname := "M11" ) # +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> SimpleGroup("J1"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last2); J_1 175560 @@ -39,10 +40,12 @@ gap> SimpleGroup("J_2"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last2) J_2 604800 rec( name := "HJ = J(2) = F(5-)", series := "Spor", shortname := "J2" ) +#@fi gap> SimpleGroup("J5"); Error, illegal parameter for Janko groups # +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> SimpleGroup("CO3"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last2); Co_3 495766656000 @@ -51,6 +54,7 @@ gap> SimpleGroup("CO(2)"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last Co(2) 42305421312000 rec( name := "Co(2)", series := "Spor", shortname := "Co2" ) +#@fi gap> SimpleGroup("CO4"); Error, illegal parameter for Conway groups @@ -59,6 +63,7 @@ gap> SimpleGroup("Fi20"); Error, illegal parameter for Fischer groups # +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> SimpleGroup("SuZ"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last2); Suz 448345497600 @@ -78,6 +83,7 @@ Sz(8) 29120 rec( name := "2B(2,8) = 2C(2,8) = Sz(8)", parameter := 8, series := "2B", shortname := "Sz(8)" ) +#@fi gap> SimpleGroup("Sz(9)"); Error, illegal parameter for Suzuki groups gap> SimpleGroup("Suz(16)"); @@ -105,6 +111,7 @@ gap> SimpleGroup("Ree(16)"); Error, illegal parameter for Ree groups # +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> SimpleGroup("HE"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last2); He 4030387200 @@ -122,6 +129,7 @@ gap> SimpleGroup("T"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last2); 17971200 rec( name := "2F(4,2)' = Ree(2)' = Tits", parameter := 2, series := "2F", shortname := "2F4(2)'" ) +#@fi # # linear groups @@ -263,6 +271,7 @@ Error, Can't do yet # gap> SimpleGroup("G3(3)"); Error, G(n,q) needs n=2 +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> SimpleGroup("G2(2)"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last2); PSU(3,3) 6048 @@ -280,15 +289,18 @@ gap> SimpleGroup("G2(5)"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last G_2(5) 5859000000 rec( name := "G(2,5)", parameter := 5, series := "G", shortname := "G2(5)" ) +#@fi # gap> SimpleGroup("3D(3,4)"); Error, 3D(n,q) needs n=4 +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> SimpleGroup("3D(4,2)"); Size(last); IsomorphismTypeInfoFiniteSimpleGroup(last2); 3D(4, 2) 211341312 rec( name := "3D(4,2)", parameter := 2, series := "3D", shortname := "3D4(2)" ) +#@fi gap> g:=SimpleGroup("3D(4,169)"); 3D4(169) gap> Size(g); diff --git a/tst/testinstall/opers/Socle.tst b/tst/testinstall/opers/Socle.tst index af4b16c56c..13d482d33a 100644 --- a/tst/testinstall/opers/Socle.tst +++ b/tst/testinstall/opers/Socle.tst @@ -4,34 +4,34 @@ Group(()) gap> D := DihedralGroup(8);; gap> Socle(D) = ClosureSubgroup(TrivialSubgroup(D), Union(Set(MinimalNormalSubgroups(D), GeneratorsOfGroup))); true -gap> IdGroup(Socle(D)); -[ 2, 1 ] +gap> Size(Socle(D)); +2 gap> Socle(D) = Center(D); true gap> D := DihedralGroup(IsFpGroup, 8);; gap> Socle(D) = ClosureSubgroup(TrivialSubgroup(D), Union(Set(MinimalNormalSubgroups(D), GeneratorsOfGroup))); true -gap> IdGroup(Socle(D)); -[ 2, 1 ] +gap> Size(Socle(D)); +2 gap> Socle(D) = Center(D); true gap> D := DihedralGroup(IsPermGroup, 8);; gap> Socle(D) = ClosureSubgroup(TrivialSubgroup(D), Union(Set(MinimalNormalSubgroups(D), GeneratorsOfGroup))); true -gap> IdGroup(Socle(D)); -[ 2, 1 ] +gap> Size(Socle(D)); +2 gap> Socle(D) = Center(D); true gap> D := Group((1,3),(1,2,3,4));; gap> Socle(D) = ClosureSubgroup(TrivialSubgroup(D), Union(Set(MinimalNormalSubgroups(D), GeneratorsOfGroup))); true -gap> IdGroup(Socle(D)); -[ 2, 1 ] +gap> Size(Socle(D)); +2 gap> Socle(D) = Center(D); true gap> DDD := DirectProduct(D, D, D);; -gap> IdGroup(Socle(DDD)); -[ 8, 5 ] +gap> StructureDescription(Socle(DDD)); +"C2 x C2 x C2" gap> Socle(DDD) = ClosureSubgroup(TrivialSubgroup(DDD), Union(Set(MinimalNormalSubgroups(DDD), GeneratorsOfGroup))); true gap> Socle(DDD) = Center(DDD); @@ -39,22 +39,23 @@ true gap> Q := QuaternionGroup(8);; gap> Socle(Q) = ClosureSubgroup(TrivialSubgroup(Q), Union(Set(MinimalNormalSubgroups(Q), GeneratorsOfGroup))); true -gap> IdGroup(Socle(Q)); -[ 2, 1 ] +gap> Size(Socle(Q)); +2 gap> Socle(Q) = Center(Q); true gap> Socle(SymmetricGroup(4)) = Group((1,2)(3,4),(1,3)(2,4)); true -gap> IdGroup(Socle(SymmetricGroup(5))); -[ 60, 5 ] -gap> IdGroup(Socle(AlternatingGroup(5))); -[ 60, 5 ] +gap> AlternatingGroup(5) = Socle(SymmetricGroup(5)); +true +gap> AlternatingGroup(5) = Socle(AlternatingGroup(5)); +true gap> G := Group((1,2),(3,4),(5,6),(7,8));; gap> IsElementaryAbelian(G); true gap> Socle(G)=G; true -gap> Socle(PrimitiveGroup(8,3)) = Group([ (1,7)(2,8)(3,5)(4,6), (1,3)(2,4)(5,7)(6,8), (1,2)(3,4)(5,6)(7,8) ]); +gap> G:=Group([ (2,7,4,8,6,5,3), (2,3)(6,7), (1,2)(3,4)(5,6)(7,8) ]);; # = PrimitiveGroup(8,3) +gap> Socle(G) = Group([ (1,7)(2,8)(3,5)(4,6), (1,3)(2,4)(5,7)(6,8), (1,2)(3,4)(5,6)(7,8) ]); true gap> k := 5;; P := SylowSubgroup(SymmetricGroup(4*k), 2);; A := Group((4*k+1, 4*k+2, 4*k+3));; G := ClosureGroup(P, A);; gap> Socle(G) = Group([ (21,22,23), (1,2)(3,4)(5,6)(7,8)(9,10)(11,12)(13,14)(15,16), (17,18)(19,20) ]); @@ -62,17 +63,19 @@ true gap> G := Group([ (1,2,3,5,4), (1,3)(2,4)(6,7) ]);; gap> Socle(G) = Group((1,2,3),(3,4,5),(6,7)); true -gap> G := SmallGroup(24,12);; -gap> IdGroup(Socle(G)); -[ 4, 2 ] +gap> G := SymmetricGroup(IsPcGroup, 4);; +gap> StructureDescription(Socle(G)); +"C2 x C2" +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> A := DihedralGroup(16);; -gap> B := SmallGroup(27, 3);; -gap> C := SmallGroup(125, 4);; +gap> B := ExtraspecialGroup( 27, 3 );; +gap> C := ExtraspecialGroup( 125, 25 );; gap> D := DirectProduct(A, B, C, SmallGroup(1536, 2));; -gap> IdGroup(Socle(D)); -[ 1440, 5958 ] +gap> StructureDescription(Socle(D)); +"C30 x C6 x C2 x C2 x C2" gap> Socle(D) = Center(D); true +#@fi gap> Socle(FittingSubgroup(SymmetricGroup(4))) = Group([ (1,4)(2,3), (1,3)(2,4) ]); true gap> G := Group([ (4,8)(6,10), (4,6,10,8,12), (2,4,12)(6,10,8), (3,9)(4,6,10,8,12) diff --git a/tst/testinstall/opers/StructureDescription.tst b/tst/testinstall/opers/StructureDescription.tst index 204f6a4b91..ceb2bd0e7c 100644 --- a/tst/testinstall/opers/StructureDescription.tst +++ b/tst/testinstall/opers/StructureDescription.tst @@ -1,6 +1,7 @@ gap> START_TEST("StructureDescription.tst"); ## Examples from manual +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> l := AllSmallGroups(12);; gap> List(l, StructureDescription);; l; [ C3 : C4, C12, A4, D12, C6 x C2 ] @@ -42,9 +43,15 @@ gap> List(AllSmallGroups(60), G -> StructureDescription(G:recompute)); [ "C5 x (C3 : C4)", "C3 x (C5 : C4)", "C3 : (C5 : C4)", "C60", "A5", "C3 x (C5 : C4)", "C3 : (C5 : C4)", "S3 x D10", "C5 x A4", "C6 x D10", "C10 x S3", "D60", "C30 x C2" ] +#@fi + +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> List(AllPrimitiveGroups(DegreeAction, 8), StructureDescription); [ "(C2 x C2 x C2) : C7", "(C2 x C2 x C2) : (C7 : C3)", "(C2 x C2 x C2) : PSL(3,2)", "PSL(3,2)", "PSL(3,2) : C2", "A8", "S8" ] +#@fi + +# gap> StructureDescription(AbelianGroup([0,0,0,2,3,6]):short); "Z^3x6^2" gap> G := Group([ (4,8)(6,10), (4,6,10,8,12), (2,4,12)(6,10,8), (3,9)(4,6,10,8,12)(7,11), (3,5)(4,6,10,8,12)(9,11), (1,3,11,9,5)(4,6,10,8,12) ]);; @@ -71,6 +78,7 @@ gap> G := PerfectGroup(IsPermGroup,1344,1);; StructureDescription(G); "(C2 x C2 x C2) : PSL(3,2)" gap> G := PerfectGroup(IsPermGroup,1344,2);; StructureDescription(G); "(C2 x C2 x C2) . PSL(3,2)" +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> StructureDescription(SmallGroup(32,15):recompute); "C4 . D8 = C4 . (C4 x C2)" gap> List(AllSmallNonabelianSimpleGroups([1..1000000]), StructureDescription); @@ -84,6 +92,9 @@ gap> List(AllSmallNonabelianSimpleGroups([1..1000000]), StructureDescription); "PSL(2,89)", "PSL(3,5)", "M22", "PSL(2,97)", "PSL(2,101)", "PSL(2,103)", "HJ", "PSL(2,107)", "PSL(2,109)", "PSL(2,113)", "PSL(2,121)", "PSL(2,125)", "O(5,4)" ] +#@fi + +# gap> G := FactorGroup(Sp(6,3), Center(Sp(6,3)));; gap> StructureDescription(G); "PSp(6,3)" @@ -91,8 +102,13 @@ gap> StructureDescription(Omega(1,8,2)); "O+(8,2)" gap> StructureDescription(Omega(-1,8,2)); "O-(8,2)" + +#@if IsPackageMarkedForLoading( "primgrp", "" ) gap> List(AllPrimitiveGroups(DegreeAction, 819, Size, 211341312, IsSimple, true), StructureDescription); [ "3D(4,2)" ] +#@fi + +# gap> G := Ree(27);; gap> HasIsFinite(G) and IsFinite(G) and HasIsSimpleGroup(G) and IsSimple(G); true @@ -102,6 +118,8 @@ gap> StructureDescription(AbelianGroup([0,0,0,2,3,4,5,6,7,8,9,10])); "Z x Z x Z x C2520 x C60 x C6 x C2 x C2" gap> StructureDescription(AbelianGroup([0,0,0,2,3,4,5,6,7,8,9,10]):short); "Z^3x2520x60x6x2^2" + +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> infolevel:=InfoLevel(InfoWarning);; SetInfoLevel(InfoWarning,2); gap> StructureDescription(SmallGroup(48,16):recompute,nice); #I Warning! Non-unique semidirect product: @@ -112,6 +130,9 @@ gap> StructureDescription(SmallGroup(64,17):recompute,nice); #I [ [ "C4 x C2", "C8" ], [ "C8 x C2", "C4" ] ] "(C4 x C2) : C8" gap> SetInfoLevel(InfoWarning,infolevel); +#@fi + +# gap> F := FreeGroup("r", "s");; r := F.1;; s := F.2;; gap> G := F/[s^2, r^3, s*r*s*r];; gap> StructureDescription(G); diff --git a/tst/testinstall/opers/SubdirectProducts.tst b/tst/testinstall/opers/SubdirectProducts.tst index b44c999c4c..98e23013fa 100644 --- a/tst/testinstall/opers/SubdirectProducts.tst +++ b/tst/testinstall/opers/SubdirectProducts.tst @@ -4,30 +4,43 @@ gap> H := SymmetricGroup(4);; gap> A := CyclicGroup(6);; # -gap> Set(SubdirectProducts(G, G), IdGroup); -[ [ 6, 1 ], [ 18, 4 ], [ 36, 10 ] ] -gap> Set(SubdirectProducts(H, H), IdGroup); -[ [ 24, 12 ], [ 96, 227 ], [ 288, 1026 ], [ 576, 8653 ] ] -gap> Set(SubdirectProducts(A, A), IdGroup); -[ [ 6, 2 ], [ 12, 5 ], [ 18, 5 ], [ 36, 14 ] ] +gap> SortedList(List(SubdirectProducts(G, G), StructureDescription)); +[ "(C3 x C3) : C2", "S3", "S3 x S3" ] +gap> SortedList(List(SubdirectProducts(A, A), StructureDescription)); +[ "C6", "C6", "C6 x C2", "C6 x C2", "C6 x C3", "C6 x C6" ] -# -gap> Set(SubdirectProducts(G, H), IdGroup); +# for the next couple tests, StructureDescription gives different outputs +# depending on which packages are loaded; e.g. for SubdirectProducts(H, H): +# [ "((C2 x C2 x C2 x C2) : C3) : C2", "(A4 x A4) : C2", "S4", "S4 x S4" ] +# [ "(C2 x C2) : ((C3 x A4) : C2)", "(C2 x C2) : S4", "S4", "S4 x S4" ] +# thus we use IdGroup if available, and else fall back to a weaker size test. +#@if IsPackageMarkedForLoading( "smallgrp", "" ) +gap> SortedList(List(SubdirectProducts(H, H), IdGroup)); +[ [ 24, 12 ], [ 96, 227 ], [ 288, 1026 ], [ 576, 8653 ] ] +gap> SortedList(List(SubdirectProducts(G, H), IdGroup)); [ [ 24, 12 ], [ 72, 43 ], [ 144, 183 ] ] -gap> Set(SubdirectProducts(H, G), IdGroup); +gap> SortedList(List(SubdirectProducts(H, G), IdGroup)); [ [ 24, 12 ], [ 72, 43 ], [ 144, 183 ] ] +#@else +gap> SortedList(List(SubdirectProducts(H, H), Size)); +[ 24, 96, 288, 576 ] +gap> SortedList(List(SubdirectProducts(G, H), Size)); +[ 24, 72, 144 ] +gap> SortedList(List(SubdirectProducts(H, G), Size)); +[ 24, 72, 144 ] +#@fi # -gap> Set(SubdirectProducts(G, A), IdGroup); -[ [ 18, 3 ], [ 36, 12 ] ] -gap> Set(SubdirectProducts(A, G), IdGroup); -[ [ 18, 3 ], [ 36, 12 ] ] +gap> SortedList(List(SubdirectProducts(G, A), StructureDescription)); +[ "C3 x S3", "C6 x S3" ] +gap> SortedList(List(SubdirectProducts(A, G), StructureDescription)); +[ "C3 x S3", "C6 x S3" ] # -gap> Set(SubdirectProducts(H, A), IdGroup); -[ [ 72, 42 ], [ 144, 188 ] ] -gap> Set(SubdirectProducts(A, H), IdGroup); -[ [ 72, 42 ], [ 144, 188 ] ] +gap> SortedList(List(SubdirectProducts(H, A), StructureDescription)); +[ "C3 x S4", "C6 x S4" ] +gap> SortedList(List(SubdirectProducts(A, H), StructureDescription)); +[ "C3 x S4", "C6 x S4" ] # gap> STOP_TEST("SubdirectProducts.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/testinstall/pgroups.tst b/tst/testinstall/pgroups.tst index f9b082a100..665c31764b 100644 --- a/tst/testinstall/pgroups.tst +++ b/tst/testinstall/pgroups.tst @@ -203,6 +203,7 @@ gap> IsRegularPGroup(G); false # +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> G:=SmallGroup(243,11);; gap> HasIsPowerfulPGroup(G); false @@ -268,6 +269,7 @@ gap> IsRegularPGroup(DirectProduct(List([[27,3],[243,22],[27,3]],SmallGroup))); true gap> IsRegularPGroup(DirectProduct(List([[27,3],[243,25]],SmallGroup))); false +#@fi # gap> STOP_TEST("pgroups.tst"); diff --git a/tst/testinstall/random.tst b/tst/testinstall/random.tst index f474932867..70e83cceb4 100644 --- a/tst/testinstall/random.tst +++ b/tst/testinstall/random.tst @@ -64,11 +64,11 @@ gap> randomTest(AlternatingGroup(5), Random); # gap> randomTest(Group((1,2),(3,4)), Random); -gap> randomTest(PrimitiveGroup(5,2), Random); -gap> randomTest(PrimitiveGroup(5,3), Random); +gap> randomTest(Group((2,4)(3,5), (1,2,3,5,4)), Random); +gap> randomTest(Group((2,3,4,5), (1,2,3,5,4)), Random); gap> randomTest(Group((1,2),(3,4))*(1,2,3), Random); -gap> randomTest(PrimitiveGroup(5,2)*(1,2,6), Random); -gap> randomTest(PrimitiveGroup(5,3)*(1,4,6), Random); +gap> randomTest(Group((2,4)(3,5), (1,2,3,5,4))*(1,2,6), Random); +gap> randomTest(Group((2,3,4,5), (1,2,3,5,4))*(1,4,6), Random); # # pc groups diff --git a/tst/testinstall/sylowhall.tst b/tst/testinstall/sylowhall.tst index a9d7fdeede..1723aaf466 100644 --- a/tst/testinstall/sylowhall.tst +++ b/tst/testinstall/sylowhall.tst @@ -2,20 +2,26 @@ gap> START_TEST("sylowhall.tst"); gap> G := GL(3,4);; PrimeDivisors(Size(G)); [ 2, 3, 5, 7 ] +#@if IsPackageMarkedForLoading( "smallgrp", "" ) gap> IdGroup(SylowSubgroup(G, 2)); [ 64, 242 ] gap> IdGroup(SylowSubgroup(G, 3)); [ 81, 7 ] -gap> IdGroup(SylowSubgroup(G, 5)); -[ 5, 1 ] -gap> IdGroup(SylowSubgroup(G, 7)); -[ 7, 1 ] +#@fi +gap> StructureDescription(SylowSubgroup(G, 5)); +"C5" +gap> StructureDescription(SylowSubgroup(G, 7)); +"C7" gap> SylowSystem(G); fail gap> HallSystem(G); fail -gap> fine := true;; for p in PrimeDivisors(Size(G)) do fine := fine and HasHallSubgroup(G, [p]); od; fine; +#@if IsPackageMarkedForLoading( "smallgrp", "" ) +gap> ForAll(PrimeDivisors(Size(G)), p -> HasHallSubgroup(G, [p])); true +#@fi + +# gap> G := GL(4,3);; PrimeDivisors(Size(G)); [ 2, 3, 5, 13 ] gap> HallSubgroup(G, [2, 3, 5, 13]) = G; @@ -24,13 +30,13 @@ gap> fine := true;; for p in PrimeDivisors(Size(G)) do fine := fine and HallSubg true gap> IsTrivial(HallSubgroup(G, [7, 11, 17])); true + +# gap> D := DihedralGroup(24);; -gap> IdGroup(SylowSubgroup(D,2)); -[ 8, 3 ] -gap> PCore(D, 2)=D; -false -gap> IdGroup(PCore(D, 2)); -[ 4, 1 ] +gap> StructureDescription(SylowSubgroup(D,2)); +"D8" +gap> StructureDescription(PCore(D, 2)); +"C4" gap> HasHallSubgroup(D,[2]) and HallSubgroup(D,[2]) = SylowSubgroup(D,2); true gap> SylowComplement(D,2)=HallSubgroup(D,[3]); @@ -39,14 +45,20 @@ gap> SylowComplement(D,2)=SylowSubgroup(D,3); true gap> SylowComplement(D,5)=D; true + +# gap> A := AlternatingGroup(4);; gap> SylowComplement(A, 3)=Group((1,2)(3,4), (1,3)(2,4)); true -gap> G := SmallGroup(8,4);; SylowComplement(G,5)=G; + +# +gap> G := QuaternionGroup(8);; SylowComplement(G,5)=G; true gap> IsTrivial(SylowComplement(G,2)); true -gap> G := SmallGroup(1080, 248);; + +# +gap> G := PcGroupCode(13145332246515941463, 1080);; # SmallGroup(1080, 248) gap> List(SylowSystem(G), Size); [ 8, 27, 5 ] gap> fine := true;; for p in PrimeDivisors(Size(G)) do fine := fine and HasSylowSubgroup(G, p); od; fine; @@ -55,15 +67,14 @@ gap> HasHallSubgroup(G,[2]) and HasHallSubgroup(G,[2]) and HasHallSubgroup(G,[5] true gap> HasHallSubgroup(G, [2, 5]); false -gap> IdGroup(HallSubgroup(G, [2,5])); -[ 40, 10 ] +gap> StructureDescription(HallSubgroup(G, [2,5])); +"C5 x D8" gap> PCore(G,2) = SylowSubgroup(G,2); true -gap> G := SmallGroup(1080, 248);; IsNilpotentGroup(G); +gap> IsNilpotentGroup(G); true gap> PCore(G,2) = SylowSubgroup(G,2); true -gap> G := SmallGroup(1080, 248);; gap> List(HallSystem(G), Size); [ 1, 8, 216, 1080, 40, 27, 135, 5 ] gap> fine := true;; for pi in Combinations(PrimeDivisors(Size(G))) do fine := fine and HasHallSubgroup(G, pi); od; fine; @@ -72,27 +83,31 @@ gap> HasSylowComplement(G, 2); false gap> SylowComplement(G, 2)=HallSubgroup(G, [3,5]); true -gap> IdGroup(HallSubgroup(AlternatingGroup(5), [2,3])); -[ 12, 3 ] -gap> IdGroup(SylowSubgroup(Group((1,2),(1,2,3,4,5)), 2)); -[ 8, 3 ] -gap> IdGroup(PCore(Group(()), 2)); -[ 1, 1 ] +gap> StructureDescription(HallSubgroup(AlternatingGroup(5), [2,3])); +"A4" +gap> StructureDescription(SylowSubgroup(Group((1,2),(1,2,3,4,5)), 2)); +"D8" +gap> StructureDescription(PCore(Group(()), 2)); +"1" gap> PCore(Group((1,2),(1,2,3,4,5)), 2) = PCore(Group((1,2),(1,2,3,4,5)), 7); true gap> G := Group((1,3),(1,2,3,4), (5,6,7));; gap> PCore(G, 2) = Group((1,3),(1,2,3,4)); true + +# gap> F := FreeGroup("x", "y");; x := F.1;; y := F.2;; gap> G := F/[x*y*x^(-1)*y^(-1), x^30, (x*y)^70];; -gap> IdGroup(SylowSubgroup(G, 2)); -[ 4, 2 ] -gap> IdGroup(HallSubgroup(G, [2,3])); -[ 12, 5 ] +gap> StructureDescription(SylowSubgroup(G, 2)); +"C2 x C2" +gap> StructureDescription(HallSubgroup(G, [2,3])); +"C6 x C2" gap> IsAbelian(G); true -gap> IdGroup(SylowSubgroup(G, 5)); -[ 25, 2 ] -gap> IdGroup(HallSubgroup(G, [5,7])); -[ 175, 2 ] +gap> StructureDescription(SylowSubgroup(G, 5)); +"C5 x C5" +gap> StructureDescription(HallSubgroup(G, [5,7])); +"C35 x C5" + +# gap> STOP_TEST("sylowhall.tst"); 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 b/tst/testspecial/method-not-found-where.g index 16ce4149c4..49079f4b75 100644 --- a/tst/testspecial/method-not-found-where.g +++ b/tst/testspecial/method-not-found-where.g @@ -1,5 +1,5 @@ # test method-not-found traceback rendering while preserving helper access -f := a -> a + a;; +f := a -> IsDiagonalMat(a);; f(()); ShowMethods(1); Where(5); diff --git a/tst/testspecial/method-not-found-where.g.out b/tst/testspecial/method-not-found-where.g.out index c7496f32b2..5f80b728c7 100644 --- a/tst/testspecial/method-not-found-where.g.out +++ b/tst/testspecial/method-not-found-where.g.out @@ -1,19 +1,20 @@ gap> # test method-not-found traceback rendering while preserving helper access -gap> f := a -> a + a;; +gap> f := a -> IsDiagonalMat(a);; gap> f(()); Error, no method found! For debugging hints type ?Recovery from NoMethodFound -Error, no 1st choice method found for `+' on 2 arguments +Error, no 1st choice method found for `IsDiagonalMatrix' on 1 arguments Stack trace: -*[1] a + a +*[1] IsDiagonalMat( a ) @ *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 + with 2 arguments: -#I Total: 138 entries +#I Searching Method for IsDiagonalMatrix with 1 argument: +#I Total: 3 entries brk> Where(5); -*[1] a + a +Stack trace: +*[1] IsDiagonalMat( a ) @ *stdin*:3 ( ) called from read-eval loop at *errin*:2 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-err-eof-sentinel.g b/tst/testspecial/syntax-err-eof-sentinel.g new file mode 100644 index 0000000000..06ea34bcd4 --- /dev/null +++ b/tst/testspecial/syntax-err-eof-sentinel.g @@ -0,0 +1,33 @@ +# Regression test for a 0xFF byte leak in syntax-error context lines. +# +# When a syntax error fires after the scanner has advanced past EOF +# (e.g. parsing "h := ;" via READ_ALL_COMMANDS from a string with no +# trailing newline), the input-line buffer is replaced with the +# scanner's end-of-input sentinel (0xFF). Before the fix in +# src/scanner.c the SyntaxErrorOrWarning() pretty-printer would dump +# that sentinel verbatim alongside the error message — visible as a +# stray `ÿ` glyph in any UTF-8 / log-file consumer of *errout* +# (e.g. the JupyterKernel package). +errFile := Filename(DirectoryTemporary(), "syntax.log");; +errStream := OutputTextFile(errFile, false);; +SetPrintFormattingStatus(errStream, false);; + +MakeReadWriteGlobal("ERROR_OUTPUT");; +saved := ERROR_OUTPUT;; +ERROR_OUTPUT := errStream;; +MakeReadOnlyGlobal("ERROR_OUTPUT");; + +READ_ALL_COMMANDS(InputTextString("h := ;"), false, false, IdFunc);; + +MakeReadWriteGlobal("ERROR_OUTPUT");; +ERROR_OUTPUT := saved;; +MakeReadOnlyGlobal("ERROR_OUTPUT");; +CloseStream(errStream);; + +inStream := InputTextFile(errFile);; +captured := ReadAll(inStream);; +CloseStream(inStream);; + +Print("contains-eof-sentinel: ", '\377' in captured, "\n"); +Print("contains-error-message: ", + PositionSublist(captured, "expression expected") <> fail, "\n"); diff --git a/tst/testspecial/syntax-err-eof-sentinel.g.out b/tst/testspecial/syntax-err-eof-sentinel.g.out new file mode 100644 index 0000000000..5dc7161cb8 --- /dev/null +++ b/tst/testspecial/syntax-err-eof-sentinel.g.out @@ -0,0 +1,36 @@ +gap> # Regression test for a 0xFF byte leak in syntax-error context lines. +gap> # +gap> # When a syntax error fires after the scanner has advanced past EOF +gap> # (e.g. parsing "h := ;" via READ_ALL_COMMANDS from a string with no +gap> # trailing newline), the input-line buffer is replaced with the +gap> # scanner's end-of-input sentinel (0xFF). Before the fix in +gap> # src/scanner.c the SyntaxErrorOrWarning() pretty-printer would dump +gap> # that sentinel verbatim alongside the error message — visible as a +gap> # stray `ÿ` glyph in any UTF-8 / log-file consumer of *errout* +gap> # (e.g. the JupyterKernel package). +gap> errFile := Filename(DirectoryTemporary(), "syntax.log");; +gap> errStream := OutputTextFile(errFile, false);; +gap> SetPrintFormattingStatus(errStream, false);; +gap> +gap> MakeReadWriteGlobal("ERROR_OUTPUT");; +gap> saved := ERROR_OUTPUT;; +gap> ERROR_OUTPUT := errStream;; +gap> MakeReadOnlyGlobal("ERROR_OUTPUT");; +gap> +gap> READ_ALL_COMMANDS(InputTextString("h := ;"), false, false, IdFunc);; +gap> +gap> MakeReadWriteGlobal("ERROR_OUTPUT");; +gap> ERROR_OUTPUT := saved;; +gap> MakeReadOnlyGlobal("ERROR_OUTPUT");; +gap> CloseStream(errStream);; +gap> +gap> inStream := InputTextFile(errFile);; +gap> captured := ReadAll(inStream);; +gap> CloseStream(inStream);; +gap> +gap> Print("contains-eof-sentinel: ", '\377' in captured, "\n"); +contains-eof-sentinel: false +gap> Print("contains-error-message: ", +> PositionSublist(captured, "expression expected") <> fail, "\n"); +contains-error-message: true +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;