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:
-
+GAP – Groups, Algorithms,
- and Programming, Version 4.16dev
+ and Programming, Version 4.17dev
https://www.gap-system.orgthis yearGAP
@@ -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(
@@ -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.
returnreturn 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,
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.
+
+ 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 \leqNumberRows( 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 );
+