From ebc233dc821fed0bcdfa55f869e5940eb4b5c5bb Mon Sep 17 00:00:00 2001 From: cdwensley Date: Mon, 20 Apr 2026 18:50:55 +0100 Subject: [PATCH 01/52] starting a PR of matrix examples --- doc/ref/matobj.xml | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index 2818815902..834d44c3d3 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -21,6 +21,53 @@ cf. Chapters and . + +
+Some Elementary Examples +Just to give a flavour of these new objects, we construct here a vector +and a matrix in these new forms. +The elements should all belong to a semiring R +(the BaseDomain). +It is also necessary to specify their type, or filter. +The simplest of these use plain lists, namely +and . +Other available types are listed in Sections + and +. +

+To construct these objects we use the operations + and , although operations +Vector and Matrix are also available and are more flexible. +NewMatrix requires the number of columns as third input. +

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

+ dom := Integers;; +gap> filt1 := IsPlistVectorRep;; +gap> filt2 := IsPlistMatrixRep;; +gap> v1 := NewVector( filt1, dom, [3,4,7,8] ); + +gap> Print( v1 ); +NewVector(IsPlistVectorRep,Integers,[ 3, 4, 7, 8 ]) +gap> M := NewMatrix( filt2, dom, 4, [ [1,2,3,4], [6,7,8,9] ] );; +gap> Display( M ); +<2x4-matrix over Integers: +[[ 1, 2, 3, 4 ] + [ 6, 7, 8, 9 ] +]> +gap> v2 := NewVector( filt1, dom, [-7..-4] );; +gap> Print( v1 + v2 ); +NewVector(IsPlistVectorRep,Integers,[ -4, -2, 2, 4 ]) +gap> Print( (v1+v2) * TransposedMat(M) ); +NewVector(IsPlistVectorRep,Integers,[ 14, 14 ]) +]]> + +

+ +
Categories of Vector and Matrix Objects From a9fc8bc24b629f9c6e9c19f22663ec84f852e236 Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Wed, 22 Apr 2026 12:37:35 +0100 Subject: [PATCH 02/52] Update doc/ref/matobj.xml Co-authored-by: Thomas Breuer --- doc/ref/matobj.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index 834d44c3d3..219068cb5e 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -29,7 +29,7 @@ and a matrix in these new forms. The elements should all belong to a semiring R (the BaseDomain). It is also necessary to specify their type, or filter. -The simplest of these use plain lists, namely +The simplest of these use plain lists, namely and . Other available types are listed in Sections and From 8f97abc295ea943c19a4414bcee5451070d1c83e Mon Sep 17 00:00:00 2001 From: Chris Wensley Date: Wed, 22 Apr 2026 12:37:50 +0100 Subject: [PATCH 03/52] Update doc/ref/matobj.xml Co-authored-by: Thomas Breuer --- doc/ref/matobj.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index 219068cb5e..cd418da620 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -30,7 +30,7 @@ The elements should all belong to a semiring R (the BaseDomain). It is also necessary to specify their type, or filter. The simplest of these use plain lists, namely -and . +and . Other available types are listed in Sections and . From dc94e93cb54e9181d5431e5f77f4b643035e3fe5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 09:16:30 +0200 Subject: [PATCH 04/52] build(deps): bump actions/upload-pages-artifact from 4 to 5 (#6336) Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 4 to 5. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](https://github.com/actions/upload-pages-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-gh-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-gh-pages.yml b/.github/workflows/update-gh-pages.yml index 0029894b91..e1ebb2c57b 100644 --- a/.github/workflows/update-gh-pages.yml +++ b/.github/workflows/update-gh-pages.yml @@ -67,7 +67,7 @@ jobs: mv doc/dev/bigpic.* public/doc/dev/ cp dev/index.html public/ - name: Upload artifact - uses: actions/upload-pages-artifact@v4 + uses: actions/upload-pages-artifact@v5 with: path: ./public From 7dff94aaeac42d5e005391e81c3b7a037f954545 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:42:07 +0000 Subject: [PATCH 05/52] build(deps): bump julia-actions/setup-julia from 2 to 3 (#6335) Bumps [julia-actions/setup-julia](https://github.com/julia-actions/setup-julia) from 2 to 3. - [Release notes](https://github.com/julia-actions/setup-julia/releases) - [Commits](https://github.com/julia-actions/setup-julia/compare/v2...v3) --- updated-dependencies: - dependency-name: julia-actions/setup-julia dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gapjl.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gapjl.yml b/.github/workflows/gapjl.yml index f7ff5e2675..5e3a5ae291 100644 --- a/.github/workflows/gapjl.yml +++ b/.github/workflows/gapjl.yml @@ -48,7 +48,7 @@ jobs: with: path: 'GAPROOT' - name: "Set up Julia" - uses: julia-actions/setup-julia@v2 + uses: julia-actions/setup-julia@v3 with: version: ${{ matrix.julia-version }} - name: Install GAP.jl From e2485f9b0e2a6be5cff135f326384da3e9cbe42f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 20 Apr 2026 16:06:39 +0200 Subject: [PATCH 06/52] Improve CosetLeadersMatFFE documentation (#6338) Codex wrote most of this and I edited it. Co-authored-by: Codex --- lib/listcoef.gd | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/listcoef.gd b/lib/listcoef.gd index a97e54b8f6..c682bfd9f4 100644 --- a/lib/listcoef.gd +++ b/lib/listcoef.gd @@ -684,13 +684,30 @@ DeclareOperation("AClosestVectorCombinationsMatFFEVecFFECoords", ## ## ## -## returns a list of representatives of minimal weight for the cosets of a -## code. -## mat must be a check matrix for the code, -## the code is defined over the finite field f. -## All rows of mat must have the same length, and all elements must -## lie in the field f. -## The rows of mat must be linearly independent. +## Let C be the linear code over f with check matrix +## mat, that is, C is the right null space of mat: +## +## C = \{ v \mid mat \cdot v = 0 \}. +## +## For each syndrome s, the solutions of the non-homogeneous system +## mat * v = s form one coset of C. Equivalently, two vectors +## lie in the same coset if their difference lies in C, just as in +## group theory. +##

+## returns, for each coset of C, a +## vector of smallest Hamming weight in that coset. Such a vector is called +## a coset leader. +##

+## If L := CosetLeadersMatFFE( mat, f ) and +## q := Size( f ), then L[i] is the coset leader whose +## syndrome is the vector with number i-1; in other words, +## NumberFFVector( mat * L[i], q ) = i - 1 +## for all valid indices i. +##

+## Thus the list is indexed by syndromes, not by codewords. +##

+## All rows of mat must have the same length, all entries must lie in +## f, and the rows of mat must be linearly independent. ## ## ## <#/GAPDoc> From f7518bf69ccea48989ed92867d37298b5bf8820b Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 20 Apr 2026 22:29:56 +0200 Subject: [PATCH 07/52] Allow 'shifting' ranges (#6334) So far adding an integer to a range produced a plain list. Add a kernel method to ensure this again produces a range, if possible. If not, fall back to the current behavior. AI-assisted with Codex for the kernel change and tests. Co-authored-by: Codex --- src/range.c | 51 ++++++++++++++++++++++++++++++++ tst/testinstall/kernel/range.tst | 48 ++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/src/range.c b/src/range.c index 3c80522a0b..7ae0c93305 100644 --- a/src/range.c +++ b/src/range.c @@ -56,6 +56,8 @@ #include "error.h" #include "gaputils.h" #include "io.h" +#include "integer.h" +#include "listoper.h" #include "lists.h" #include "modules.h" #include "opers.h" @@ -818,6 +820,45 @@ Obj Range3Check ( } +/**************************************************************************** +** +*F ShiftRange( , ) +** +** 'ShiftRange' preserves the range representation when shifting +** by the integer keeps both endpoints in the small integer range. +** Otherwise it falls back to the generic scalar/list implementation. +*/ +static Obj ShiftRange(Obj offset, Obj range) +{ + Obj low; + Obj high; + Obj shifted; + + low = SUM(offset, INTOBJ_INT(GET_LOW_RANGE(range))); + high = SUM(offset, GET_ELM_RANGE(range, GET_LEN_RANGE(range))); + if (!IS_INTOBJ(low) || !IS_INTOBJ(high)) { + return SumSclList(offset, range); + } + + shifted = NEW_RANGE(GET_LEN_RANGE(range), INT_INTOBJ(low), + GET_INC_RANGE(range)); + if (!IS_MUTABLE_OBJ(range)) { + MakeImmutableNoRecurse(shifted); + } + return shifted; +} + +static Obj SumIntRange(Obj opL, Obj opR) +{ + return ShiftRange(opL, opR); +} + +static Obj SumRangeInt(Obj opL, Obj opR) +{ + return ShiftRange(opR, opL); +} + + /**************************************************************************** ** *F * * * * * * * * * * * * * * GAP level functions * * * * * * * * * * * * * @@ -1178,6 +1219,16 @@ static Int InitKernel ( LtFuncs[ T_RANGE_SSORT ][ T_RANGE_NSORT ] = LtRange; LtFuncs[ T_RANGE_SSORT ][ T_RANGE_SSORT ] = LtRange; + SumFuncs[ T_INT ][ T_RANGE_NSORT ] = SumIntRange; + SumFuncs[ T_INT ][ T_RANGE_NSORT + IMMUTABLE ] = SumIntRange; + SumFuncs[ T_INT ][ T_RANGE_SSORT ] = SumIntRange; + SumFuncs[ T_INT ][ T_RANGE_SSORT + IMMUTABLE ] = SumIntRange; + + SumFuncs[ T_RANGE_NSORT ][ T_INT ] = SumRangeInt; + SumFuncs[ T_RANGE_NSORT + IMMUTABLE ][ T_INT ] = SumRangeInt; + SumFuncs[ T_RANGE_SSORT ][ T_INT ] = SumRangeInt; + SumFuncs[ T_RANGE_SSORT + IMMUTABLE ][ T_INT ] = SumRangeInt; + // install the list functions in the tables LenListFuncs [ T_RANGE_NSORT ] = LenRange; LenListFuncs [ T_RANGE_NSORT +IMMUTABLE ] = LenRange; diff --git a/tst/testinstall/kernel/range.tst b/tst/testinstall/kernel/range.tst index ce1b1b3a50..b713bfc4ed 100644 --- a/tst/testinstall/kernel/range.tst +++ b/tst/testinstall/kernel/range.tst @@ -12,6 +12,54 @@ gap> START_TEST("kernel/range.tst"); gap> TNAM_OBJ([1..10]{[]}); "empty plain list" +# +# SumRangeInt / SumIntRange +# +gap> r := 5 + [1..5]; +[ 6 .. 10 ] +gap> IsRangeRep(r); +true +gap> r := [1..5] + 5; +[ 6 .. 10 ] +gap> IsRangeRep(r); +true +gap> r := 5 + [1,3..9]; +[ 6, 8 .. 14 ] +gap> IsRangeRep(r); +true +gap> r := [1,3..9] + 5; +[ 6, 8 .. 14 ] +gap> IsRangeRep(r); +true +gap> r := 5 + [9,7..1]; +[ 14, 12 .. 6 ] +gap> IsRangeRep(r); +true +gap> r := [9,7..1] + 5; +[ 14, 12 .. 6 ] +gap> IsRangeRep(r); +true +gap> r := 1 + [INTOBJ_MAX-1..INTOBJ_MAX];; +gap> r = [INTOBJ_MAX, INTOBJ_MAX+1]; +true +gap> IsRangeRep(r); +false +gap> r := [INTOBJ_MAX-1..INTOBJ_MAX] + 1;; +gap> r = [INTOBJ_MAX, INTOBJ_MAX+1]; +true +gap> IsRangeRep(r); +false +gap> r := -1 + [-INTOBJ_MAX-1..-INTOBJ_MAX];; +gap> r = [-INTOBJ_MAX-2, -INTOBJ_MAX-1]; +true +gap> IsRangeRep(r); +false +gap> r := [-INTOBJ_MAX-1..-INTOBJ_MAX] + -1;; +gap> r = [-INTOBJ_MAX-2, -INTOBJ_MAX-1]; +true +gap> IsRangeRep(r); +false + # # UnbRange # From 0b3d102fa44c7598c8587fd8da780da4b0705b20 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 21 Apr 2026 00:41:23 +0200 Subject: [PATCH 08/52] Re-enable Codecov comments but delay PR notifications (#6332) Switch Codecov to manual notifications and send them once after the coverage-uploading test matrix finishes. This avoids noisy intermediate PR comments and temporary dropped-coverage reports while uploads are still in flight. Co-authored-by: Codex --- .codecov.yml | 6 ++++-- .github/workflows/CI.yml | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.codecov.yml b/.codecov.yml index a302704acc..32dc8a6220 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,3 +1,7 @@ +codecov: + notify: + manual_trigger: true # needed for codecov-notify CI step + coverage: precision: 2 round: down @@ -14,8 +18,6 @@ coverage: default: informational: true -comment: false - ignore: - "extern" - "hpcgap/extern" diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9a7626a9c1..ca0f05b997 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -280,6 +280,18 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} + codecov-notify: + name: Finalize Codecov notifications + runs-on: ubuntu-slim + needs: test + if: ${{ always() }} + + steps: + - name: "Send Codecov notifications" + uses: codecov/codecov-action@v6 + with: + token: ${{ secrets.CODECOV_TOKEN }} + run_command: send-notifications cross_compile: # The host should always be linux From f2e48061d1efbdde31e2820c0e802b5a87516619 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 22 Apr 2026 00:12:07 +0200 Subject: [PATCH 09/52] PlainListCopy for list not knowing they are small (#6333) --- src/lists.c | 3 ++- tst/testbugfix/2026-04-19-PlainListCopy.tst | 6 ++++++ tst/testinstall/list.tst | 8 ++++---- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 tst/testbugfix/2026-04-19-PlainListCopy.tst diff --git a/src/lists.c b/src/lists.c index bc1b4a7589..dc329b0966 100644 --- a/src/lists.c +++ b/src/lists.c @@ -1649,7 +1649,8 @@ Obj PLAIN_LIST_COPY(Obj list) Obj FuncPlainListCopy(Obj self, Obj list) { - RequireSmallList(SELF_NAME, list); + if (!IS_LIST(list)) + RequireArgument(SELF_NAME, list, "must be a list"); return PLAIN_LIST_COPY(list); } diff --git a/tst/testbugfix/2026-04-19-PlainListCopy.tst b/tst/testbugfix/2026-04-19-PlainListCopy.tst new file mode 100644 index 0000000000..9acb71775e --- /dev/null +++ b/tst/testbugfix/2026-04-19-PlainListCopy.tst @@ -0,0 +1,6 @@ +# Fix PlainListCopy for lists which are small but do not know it yet know they +# are in filter `IsSmallList`; this is e.g. needed for the semigroups test +# suite +gap> l:=RightTransversal(Group([ (1,2) ]),Group([ () ]));; +gap> PlainListCopy(l); +[ (), (1,2) ] diff --git a/tst/testinstall/list.tst b/tst/testinstall/list.tst index 65a8e0fcd7..f4742a9834 100644 --- a/tst/testinstall/list.tst +++ b/tst/testinstall/list.tst @@ -336,15 +336,15 @@ true gap> checkPlainListCopy(NewZeroVector(Is8BitVectorRep, GF(3), 10)); true gap> PlainListCopy(6); -Error, PlainListCopy: must be a small list (not the integer 6) +Error, PlainListCopy: must be a list (not the integer 6) gap> PlainListCopy((1,2,3)); -Error, PlainListCopy: must be a small list (not a permutation (small)) +Error, PlainListCopy: must be a list (not a permutation (small)) #@if IsHPCGAP gap> PlainListCopy(Group((1,2))); -Error, PlainListCopy: must be a small list (not an atomic component object) +Error, PlainListCopy: must be a list (not an atomic component object) #@else gap> PlainListCopy(Group((1,2))); -Error, PlainListCopy: must be a small list (not a component object) +Error, PlainListCopy: must be a list (not a component object) #@fi # Check TNUM behaviours From 155efe1f194a754894eb4ff604fc2aefc97c7800 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 22 Apr 2026 02:25:33 +0200 Subject: [PATCH 10/52] Faster {Copy,Extract}Sub{Matrix,Vector} for plist matrices/vectors (#6329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... by avoiding some method dispatch, providing optimized methods using `{...}` syntax, and turning ExtractSubVector, CopySubVector, ExtractSubMatrix, and CopySubMatrix into kernel ops. Then run some benchmarks via `benchmark/matobj/bench-submat.g` and the new `benchmark/matobj/bench-subvec.g`. Before: +----------------------------------------------------------------+ | Testing submatrix extraction for integer matrix: list of lists | +----------------------------------------------------------------+ Testing m{}{}: 129 µs per iteration; 7749 iterations per second; (200 iterations) Testing ExtractSubMatrix: 720 µs per iteration; 1388 iterations per second; (200 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 342 µs per iteration; 2921 iterations per second; (200 iterations) Testing CopySubMatrix: 1032 µs per iteration; 969 iterations per second; (200 iterations) +------------------------------------------------+ | Testing submatrix extraction for GF(2) rowlist | +------------------------------------------------+ Testing m{}{}: 167 µs per iteration; 5999 iterations per second; (200 iterations) Testing ExtractSubMatrix: 3288 µs per iteration; 304 iterations per second; (92 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 1992 µs per iteration; 502 iterations per second; (151 iterations) Testing CopySubMatrix: 2606 µs per iteration; 384 iterations per second; (116 iterations) +-------------------------------------------------------------+ | Testing subvector extraction for integer vector: plain list | +-------------------------------------------------------------+ Testing x{}:=v{}: 393 µs per iteration; 2542 iterations per second; (200 iterations) Testing CopySubVector: 2324 µs per iteration; 430 iterations per second; (130 iterations) +---------------------------------------------------+ | Testing subvector extraction for GF(2) row vector | +---------------------------------------------------+ Testing x{}:=v{}: 441 µs per iteration; 2266 iterations per second; (200 iterations) Testing CopySubVector: 2458 µs per iteration; 407 iterations per second; (123 iterations) After: +----------------------------------------------------------------+ | Testing submatrix extraction for integer matrix: list of lists | +----------------------------------------------------------------+ Testing m{}{}: 136 µs per iteration; 7355 iterations per second; (200 iterations) Testing ExtractSubMatrix: 140 µs per iteration; 7135 iterations per second; (200 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 301 µs per iteration; 3319 iterations per second; (200 iterations) Testing CopySubMatrix: 299 µs per iteration; 3347 iterations per second; (200 iterations) +------------------------------------------------+ | Testing submatrix extraction for GF(2) rowlist | +------------------------------------------------+ Testing m{}{}: 154 µs per iteration; 6490 iterations per second; (200 iterations) Testing ExtractSubMatrix: 146 µs per iteration; 6854 iterations per second; (200 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 1895 µs per iteration; 528 iterations per second; (159 iterations) Testing CopySubMatrix: 1935 µs per iteration; 517 iterations per second; (156 iterations) +-------------------------------------------------------------+ | Testing subvector extraction for integer vector: plain list | +-------------------------------------------------------------+ Testing x{}:=v{}: 428 µs per iteration; 2336 iterations per second; (200 iterations) Testing CopySubVector: 453 µs per iteration; 2209 iterations per second; (200 iterations) +---------------------------------------------------+ | Testing subvector extraction for GF(2) row vector | +---------------------------------------------------+ Testing x{}:=v{}: 427 µs per iteration; 2344 iterations per second; (200 iterations) Testing CopySubVector: 460 µs per iteration; 2172 iterations per second; (200 iterations) So overall the Copy/Extract methods are now more or less on par with the code using `{...}` syntax. But actually this `ExtractSubMatrix` for a GF(2) rowlist is now *faster* than the optimized one for a compressed GF(2) matrix: +----------------------------------------------------------+ | Testing submatrix extraction for GF(2) compressed matrix | +----------------------------------------------------------+ Testing m{}{}: 1057 µs per iteration; 946 iterations per second; (200 iterations) Testing ExtractSubMatrix: 1618 µs per iteration; 618 iterations per second; (186 iterations) A substantial part of that is due to the the `ExtractSubMatrix` method for `IsGF2MatrixRep` calling `ConvertToMatrixRepNC(mm,2)`; after removing that, it went down from 1618 to 392 µs (which is still worse). --- AI assistance: Codex implemented the kernel plumbing, method cleanup, and test updates. It also created `benchmark/matobj/bench-subvec.g`. Co-authored-by: Codex --- benchmark/matobj/bench-submat.g | 41 ++++--- benchmark/matobj/bench-subvec.g | 81 ++++++++++++++ lib/matobj.gi | 31 +++--- lib/matobj2.gd | 17 +-- src/lists.c | 100 ++++++++++++++++++ tst/testinstall/MatrixObj/CopySubVector.tst | 3 +- .../MatrixObj/ExtractSubMatrix.tst | 13 +++ .../MatrixObj/ExtractSubvector.tst | 2 + 8 files changed, 247 insertions(+), 41 deletions(-) create mode 100644 benchmark/matobj/bench-subvec.g create mode 100644 tst/testinstall/MatrixObj/ExtractSubMatrix.tst diff --git a/benchmark/matobj/bench-submat.g b/benchmark/matobj/bench-submat.g index 0b10bf85b2..b5ee2697de 100644 --- a/benchmark/matobj/bench-submat.g +++ b/benchmark/matobj/bench-submat.g @@ -7,13 +7,15 @@ TestExtractingSubmatrix := function(m) rows := [2..NrRows(m)-2]; cols := [3..NrCols(m)-1]; - PrintHeadline("m{}{}"); - MyBench(function() - local u, x; - for u in [1..QuoInt(100000,NrRows(m)*NrCols(m))] do - x:=m{rows}{cols}; - od; - end); + if not IsPlistMatrixRep(m) then + PrintHeadline("m{}{}"); + MyBench(function() + local u, x; + for u in [1..QuoInt(100000,NrRows(m)*NrCols(m))] do + x:=m{rows}{cols}; + od; + end); + fi; PrintHeadline("ExtractSubMatrix"); MyBench(function() @@ -32,13 +34,15 @@ TestCopyingSubmatrix := function(m) rows := [2..NrRows(m)-2]; cols := [3..NrCols(m)-1]; - PrintHeadline("m{}{}:=n{}{}"); - MyBench(function() - local u; - for u in [1..QuoInt(100000,NrRows(m)*NrCols(m))] do - x{rows}{cols}:=m{rows}{cols}; - od; - end); + if not IsPlistMatrixRep(m) then + PrintHeadline("m{}{}:=n{}{}"); + MyBench(function() + local u; + for u in [1..QuoInt(100000,NrRows(m)*NrCols(m))] do + x{rows}{cols}:=m{rows}{cols}; + od; + end); + fi; PrintHeadline("CopySubMatrix"); MyBench(function() @@ -62,18 +66,21 @@ for dim in [10, 100] do PrintBoxed(Concatenation("Now testing in dimension ", String(dim))); m:=IdentityMat(dim);; - RunMatTest("integer matrix", m); + RunMatTest("integer matrix: list of lists", m); + + m:=IdentityMatrix(Integers, dim);; + RunMatTest("integer matrix: IsPlistMatrixRep", m); m:=IdentityMat(dim,GF(2));; RunMatTest("GF(2) rowlist", m); - m:=IdentityMat(dim,GF(2));; ConvertToMatrixRep(m);; + m:=IdentityMatrix(GF(2), dim);; RunMatTest("GF(2) compressed matrix", m); m:=IdentityMat(dim,GF(7));; RunMatTest("GF(7) rowlist", m); - m:=IdentityMat(dim,GF(7));; ConvertToMatrixRep(m);; + m:=IdentityMatrix(GF(8), dim);; RunMatTest("GF(7) compressed matrix", m); # TODO: also add cvec matrices diff --git a/benchmark/matobj/bench-subvec.g b/benchmark/matobj/bench-subvec.g new file mode 100644 index 0000000000..8e2ede2ea9 --- /dev/null +++ b/benchmark/matobj/bench-subvec.g @@ -0,0 +1,81 @@ +ReadGapRoot("benchmark/matobj/bench.g"); + + +TestExtractingSubvector := function(v) + local cols; + + cols := [3..Length(v)-1]; + + if not IsPlistVectorRep(v) then + PrintHeadline("v{}"); + MyBench(function() + local u, x; + for u in [1..QuoInt(100000, Length(v))] do + x := v{cols}; + od; + end); + fi; + + PrintHeadline("ExtractSubVector"); + MyBench(function() + local u, x; + for u in [1..QuoInt(100000, Length(v))] do + x := ExtractSubVector(v, cols); + od; + end); +end; + +TestCopyingSubvector := function(v) + local x, cols; + + x := ShallowCopy(v); + cols := [3..Length(v)-1]; + + if not IsPlistVectorRep(v) then + PrintHeadline("x{}:=v{}"); + MyBench(function() + local u; + for u in [1..QuoInt(100000, Length(v))] do + x{cols} := v{cols}; + od; + end); + fi; + + PrintHeadline("CopySubVector"); + MyBench(function() + local u; + for u in [1..QuoInt(100000, Length(v))] do + CopySubVector(v, x, cols, cols); + od; + end); +end; + +RunVecTest := function(desc, v) + Print("\n"); + PrintBoxed(Concatenation("Testing subvector extraction for ", desc)); + TestExtractingSubvector(v); + Print(TextAttr.2, "...now testing subvector copying...\n", TextAttr.reset); + TestCopyingSubvector(v); +end; + +for dim in [10, 100] do + PrintBoxed(Concatenation("Now testing in dimension ", String(dim))); + + v := [1..dim] * 0;; + RunVecTest("integer vector: plain list", v); + + v := Vector(IsPlistVectorRep, Integers, [1..dim]);; + RunVecTest("integer vector: IsPlistVectorRep", v); + + v := [1..dim] * One(GF(2));; + RunVecTest("GF(2) row vector", v); + + v := NewVector(IsGF2VectorRep, GF(2), [1..dim] * One(GF(2)));; + RunVecTest("GF(2) compressed vector", v); + + v := [1..dim] * One(GF(7));; + RunVecTest("GF(7) row vector", v); + + v := NewVector(Is8BitVectorRep, GF(7), [1..dim] * One(GF(7)));; + RunVecTest("GF(7) 8-bit vector", v); +od; diff --git a/lib/matobj.gi b/lib/matobj.gi index 652dddccad..35ae1ccbe0 100644 --- a/lib/matobj.gi +++ b/lib/matobj.gi @@ -749,9 +749,9 @@ InstallMethod( \{\}, return Vector( Unpack( v ){ poss }, v ); end ); -InstallMethod( ExtractSubVector, - "generic method for a vector object and a list", - [ IsVectorObj, IsList ], +InstallOtherMethod( ExtractSubVector, + "generic method for a row vector or vector object and a list", + [ IsRowVectorOrVectorObj, IsList ], { v, l } -> v{ l } ); InstallMethod( ExtractSubMatrix, @@ -759,20 +759,10 @@ InstallMethod( ExtractSubMatrix, [ IsMatrixObj, IsList, IsList ], { M, rowpos, colpos } -> Matrix( Unpack( M ){ rowpos }{ colpos }, M ) ); -# Hack from recog package -InstallOtherMethod( ExtractSubMatrix, "hack: for lists of compressed vectors", -[ IsList, IsList, IsList ], -function( m, poss1, poss2 ) - local i,n; - n := []; - for i in poss1 do - Add(n,ShallowCopy(m[i]{poss2})); - od; - if IsFFE(m[1,1]) then - ConvertToMatrixRep(n); - fi; - return n; -end ); +InstallOtherMethod( ExtractSubMatrix, + "generic method for a matrix and two lists", + [ IsMatrix, IsList, IsList ], + { M, rowpos, colpos } -> M{ rowpos }{ colpos } ); InstallMethod( CopySubVector, "generic method for row vectors and vector objects", @@ -788,6 +778,13 @@ InstallMethod( CopySubVector, od; end ); +InstallMethod( CopySubVector, + "generic method for row vectors", + [ IsRowVector, IsRowVector and IsMutable, IsList, IsList ], + function(src, dst, scols, dcols) + dst{dcols} := src{scols}; +end ); + ############################################################################# ## diff --git a/lib/matobj2.gd b/lib/matobj2.gd index c7cd9f0c4a..21f4af9a32 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -434,7 +434,8 @@ DeclareGlobalFunction( "ConcatenationOfVectors" ); ## ## <#/GAPDoc> ## -DeclareOperation( "ExtractSubVector", [ IsVectorObj, IsList ] ); +DeclareOperationKernel( "ExtractSubVector", + [ IsRowVectorOrVectorObj, IsList ], EXTRACT_SUB_VECTOR ); ############################################################################# @@ -896,9 +897,9 @@ DeclareOperation( "Randomize", [ IsRandomSource, IsMatrixOrMatrixObj and IsMutab ## ## <#/GAPDoc> ## -DeclareOperation( "CopySubVector", +DeclareOperationKernel( "CopySubVector", [ IsRowVectorOrVectorObj, IsRowVectorOrVectorObj and IsMutable, - IsList, IsList ] ); + IsList, IsList ], COPY_SUB_VECTOR ); ############################################################################# @@ -956,7 +957,8 @@ DeclareOperation( "DistanceOfVectors", [ IsVectorObj, IsVectorObj ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "ExtractSubMatrix", [ IsMatrixOrMatrixObj, IsList, IsList ] ); +DeclareOperationKernel( "ExtractSubMatrix", + [ IsMatrixOrMatrixObj, IsList, IsList ], EXTRACT_SUB_MATRIX ); ############################################################################# @@ -1005,8 +1007,11 @@ DeclareOperation( "MutableCopyMatrix", [ IsMatrixOrMatrixObj ] ); ## ## <#/GAPDoc> ## -DeclareOperation( "CopySubMatrix", - [ IsMatrixOrMatrixObj, IsMatrixOrMatrixObj, IsList, IsList, IsList, IsList ] ); +DeclareOperationKernel( "CopySubMatrix", + [ IsMatrixOrMatrixObj, IsMatrixOrMatrixObj, IsList, IsList, IsList, IsList ], + COPY_SUB_MATRIX ); +#T We intentionally keep the second argument declaration broad, mirroring +#T the pre-existing operation declaration for compatibility with packages. ############################################################################# diff --git a/src/lists.c b/src/lists.c index dc329b0966..feb5c1584c 100644 --- a/src/lists.c +++ b/src/lists.c @@ -1611,6 +1611,99 @@ void AsssListLevel ( } +/**************************************************************************** +** +*F FuncEXTRACT_SUB_VECTOR( , , ) . . `EXTRACT_SUB_VECTOR' +*/ +static Obj ExtractSubVectorOper; + +static Obj FuncEXTRACT_SUB_VECTOR(Obj self, Obj vec, Obj poss) +{ + if (IS_PLIST(vec)) { + CheckIsPossList("List Elements", poss); + return ELMS_LIST(vec, poss); + } + + return DoOperation2Args(ExtractSubVectorOper, vec, poss); +} + + +/**************************************************************************** +** +*F FuncCOPY_SUB_VECTOR( , , , , ) +*/ +static Obj CopySubVectorOper; + +static Obj FuncCOPY_SUB_VECTOR( + Obj self, Obj src, Obj dst, Obj scols, Obj dcols) +{ + if (IS_PLIST(src) && IS_PLIST(dst)) { + Obj rhss; + + CheckIsPossList("List Assignments", scols); + CheckIsPossList("List Assignments", dcols); + rhss = ELMS_LIST(src, scols); + AsssListCheck(dst, dcols, rhss); + return 0; + } + + return DoOperation4Args(CopySubVectorOper, src, dst, scols, dcols); +} + + +/**************************************************************************** +** +*F FuncEXTRACT_SUB_MATRIX( , , , ) +*/ +static Obj ExtractSubMatrixOper; + +static Obj FuncEXTRACT_SUB_MATRIX(Obj self, Obj mat, Obj rows, Obj cols) +{ + if (IS_PLIST(mat)) { + Obj submat; + + CheckIsPossList("List Elements", rows); + CheckIsPossList("List Elements", cols); + submat = ELMS_LIST(mat, rows); + ElmsListLevel(submat, cols, 1); + return submat; + } + + return DoOperation3Args(ExtractSubMatrixOper, mat, rows, cols); +} + + +/**************************************************************************** +** +*F FuncCOPY_SUB_MATRIX( , , , , , , +*F ) +*/ +static Obj CopySubMatrixOper; + +static Obj FuncCOPY_SUB_MATRIX( + Obj self, Obj src, Obj dst, Obj srows, Obj drows, Obj scols, Obj dcols) +{ + if (IS_PLIST(src) && IS_PLIST(dst)) { + Obj srcsub; + Obj dstsub; + + CheckIsPossList("List Assignments", srows); + CheckIsPossList("List Assignments", drows); + CheckIsPossList("List Assignments", scols); + CheckIsPossList("List Assignments", dcols); + + srcsub = ELMS_LIST(src, srows); + ElmsListLevel(srcsub, scols, 1); + dstsub = ELMS_LIST(dst, drows); + AsssListLevel(dstsub, dcols, srcsub, 1); + return 0; + } + + return DoOperation6Args(CopySubMatrixOper, src, dst, srows, drows, scols, + dcols); +} + + /**************************************************************************** ** *F PLAIN_LIST() . . . . . . . . . . . convert a list to a plain list @@ -1953,6 +2046,13 @@ static StructGVarOper GVarOpers[] = { GVAR_OPER_4ARGS(ASS_MAT, mat, row, col, obj, &AssMatOper), GVAR_OPER_3ARGS(ELM_MAT, mat, row, col, &ElmMatOper), + GVAR_OPER_2ARGS(EXTRACT_SUB_VECTOR, vec, poss, &ExtractSubVectorOper), + GVAR_OPER_4ARGS(COPY_SUB_VECTOR, src, dst, scols, dcols, + &CopySubVectorOper), + GVAR_OPER_3ARGS(EXTRACT_SUB_MATRIX, mat, rows, cols, + &ExtractSubMatrixOper), + GVAR_OPER_6ARGS(COPY_SUB_MATRIX, src, dst, srows, drows, scols, dcols, + &CopySubMatrixOper), GVAR_OPER_3ARGS(SWAP_MAT_ROWS, mat, row1, row2, &SwapMatRows), GVAR_OPER_3ARGS(SWAP_MAT_COLS, mat, col1, col2, &SwapMatCols), diff --git a/tst/testinstall/MatrixObj/CopySubVector.tst b/tst/testinstall/MatrixObj/CopySubVector.tst index 5c702e6089..33cea42c90 100644 --- a/tst/testinstall/MatrixObj/CopySubVector.tst +++ b/tst/testinstall/MatrixObj/CopySubVector.tst @@ -79,7 +79,8 @@ gap> l4; # gap> CopySubVector( l1, l3, [1,2], [1] ); -Error, source and destination index lists must be of equal length +Error, List Assignments: must have the same length as (lengths a\ +re 2 and 1) # gap> STOP_TEST("CopySubVector.tst"); diff --git a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst new file mode 100644 index 0000000000..35517c5f25 --- /dev/null +++ b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst @@ -0,0 +1,13 @@ +gap> START_TEST("ExtractSubMatrix.tst"); +gap> IsBoundGlobal("EXTRACT_SUB_MATRIX"); +true +gap> EXTRACT_SUB_MATRIX = ExtractSubMatrix; +true +gap> m1 := [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; +[ [ 1, 2, 3 ], [ 4, 5, 6 ] ] +gap> ExtractSubMatrix( m1, [ 2, 1 ], [ 3, 1 ] ); +[ [ 6, 4 ], [ 3, 1 ] ] +gap> m2 := IdentityMatrix( Integers, 4 );; +gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); +[ [ 0, 1 ], [ 1, 0 ] ] +gap> STOP_TEST("ExtractSubMatrix.tst"); diff --git a/tst/testinstall/MatrixObj/ExtractSubvector.tst b/tst/testinstall/MatrixObj/ExtractSubvector.tst index 42af85ac22..81224516ab 100644 --- a/tst/testinstall/MatrixObj/ExtractSubvector.tst +++ b/tst/testinstall/MatrixObj/ExtractSubvector.tst @@ -1,6 +1,8 @@ gap> START_TEST("ExtractSubVector.tst"); gap> l1 := [1,2,3,4,5,6]; [ 1, 2, 3, 4, 5, 6 ] +gap> ExtractSubVector( l1, [1,2,4] ); +[ 1, 2, 4 ] gap> v3 := Vector(GF(5), l1*One(GF(5))); [ Z(5)^0, Z(5), Z(5)^3, Z(5)^2, 0*Z(5), Z(5)^0 ] gap> ExtractSubVector( v3, [1,2,4] ); From 5e7673dbc26597b1797eb7a2ed2ac1228076aab7 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Wed, 22 Apr 2026 16:33:35 +0100 Subject: [PATCH 11/52] not using New variants --- doc/ref/matobj.xml | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index cd418da620..c7d6857083 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -24,21 +24,13 @@ cf. Chapters and .

Some Elementary Examples -Just to give a flavour of these new objects, we construct here a vector +Just to give a flavour of these new objects, we construct here two vectors and a matrix in these new forms. The elements should all belong to a semiring R (the BaseDomain). -It is also necessary to specify their type, or filter. -The simplest of these use plain lists, namely -and . -Other available types are listed in Sections - and -. -

To construct these objects we use the operations - and , although operations -Vector and Matrix are also available and are more flexible. -NewMatrix requires the number of columns as third input. +Vector and Matrix which are described in Section +.

Basic arithmetic operations for vectors and matrices are available: see Sections and @@ -46,25 +38,34 @@ see Sections and

dom := Integers;; -gap> filt1 := IsPlistVectorRep;; -gap> filt2 := IsPlistMatrixRep;; -gap> v1 := NewVector( filt1, dom, [3,4,7,8] ); - +gap> v1 := Vector( dom, [3,4,7,8] );; gap> Print( v1 ); NewVector(IsPlistVectorRep,Integers,[ 3, 4, 7, 8 ]) -gap> M := NewMatrix( filt2, dom, 4, [ [1,2,3,4], [6,7,8,9] ] );; +gap> M := Matrix( dom, [ [1,2,3,4], [6,7,8,9] ] );; gap> Display( M ); <2x4-matrix over Integers: [[ 1, 2, 3, 4 ] [ 6, 7, 8, 9 ] ]> -gap> v2 := NewVector( filt1, dom, [-7..-4] );; +gap> v2 := Vector( [-7..-4], v1 ); + gap> Print( v1 + v2 ); NewVector(IsPlistVectorRep,Integers,[ -4, -2, 2, 4 ]) -gap> Print( (v1+v2) * TransposedMat(M) ); -NewVector(IsPlistVectorRep,Integers,[ 14, 14 ]) +gap> Display( (v1+v2) * TransposedMat(M) ); + ]]> +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 +. +

From 91d94672208a5be0a5f7b19498a8be074f593f1a Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Thu, 23 Apr 2026 15:28:18 -0700 Subject: [PATCH 12/52] doc: fix IrreducibleModules description to say 'at most' dim (#6337) The GAPDoc description for IrreducibleModules claimed the second entry was 'a list of all irreducible modules of G over the field F in dimension dim'. The actual behaviour is to return all irreducible constituents of dimension at most dim, matching: Updated the description to match this, and also added a one-line note that passing 0 imposes no bound (already the implementation behavior, previously only discoverable by reading the code). Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Claude (Anthropic AI) --- lib/grpreps.gd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/grpreps.gd b/lib/grpreps.gd index 125cbbaf99..78433fcbf3 100644 --- a/lib/grpreps.gd +++ b/lib/grpreps.gd @@ -49,8 +49,10 @@ DeclareSynonym( "AbsolutelyIrreducibleModules", AbsolutIrreducibleModules ); ## ## returns a list of length 2. The first entry is a generating system of ## G. The second entry is a list of all irreducible modules of -## G over the field F in dimension dim, given as MeatAxe modules +## G over the field F of dimension at most dim, +## given as MeatAxe modules ## (see ). +## Pass 0 for dim to impose no dimension bound. ##
## ## <#/GAPDoc> From 89631b23bb45e270139f73e5531b4605ba37fe08 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 24 Apr 2026 16:36:36 +0200 Subject: [PATCH 13/52] Fix PartitionsGreatestLE for zero, improve docs (#6341) Return the empty partition from PartitionsGreatestLE(0, m) for every nonnegative m. Also clarify the documentation. Co-authored-by: Codex --- lib/combinat.gd | 22 ++++++++++++++++++++-- lib/combinat.gi | 12 ++++-------- tst/testinstall/combinat.tst | 22 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/lib/combinat.gd b/lib/combinat.gd index fb3ced6991..f89bbc550a 100644 --- a/lib/combinat.gd +++ b/lib/combinat.gd @@ -970,7 +970,7 @@ DeclareGlobalFunction("NrPartitions"); ############################################################################# ## -#F PartitionsGreatestLE( , ) . . . set of partitions of n parts <= n +#F PartitionsGreatestLE( , ) . . . partitions of n with parts <= m ## ## <#GAPDoc Label="PartitionsGreatestLE"> ## @@ -979,6 +979,16 @@ DeclareGlobalFunction("NrPartitions"); ## ## returns the set of all (unordered) partitions of the integer n ## having parts less or equal to the integer m. +## For n = 0 and m \geq 0, this returns the empty partition +## [[]]. +## Negative arguments yield the empty list. +## PartitionsGreatestLE( 6, 3 ); +## [ [ 1, 1, 1, 1, 1, 1 ], [ 2, 1, 1, 1, 1 ], [ 2, 2, 1, 1 ], [ 2, 2, 2 ], +## [ 3, 1, 1, 1 ], [ 3, 2, 1 ], [ 3, 3 ] ] +## gap> List( [ 0 .. 3 ], m -> PartitionsGreatestLE( 0, m ) ); +## [ [ [ ] ], [ [ ] ], [ [ ] ], [ [ ] ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -988,7 +998,7 @@ DeclareGlobalFunction("PartitionsGreatestLE"); ############################################################################# ## -#F PartitionsGreatestEQ( , ) . . . . set of partitions of n parts = n +#F PartitionsGreatestEQ( , ) . . . . partitions of n with max part m ## ## <#GAPDoc Label="PartitionsGreatestEQ"> ## @@ -997,6 +1007,14 @@ DeclareGlobalFunction("PartitionsGreatestLE"); ## ## returns the set of all (unordered) partitions of the integer n ## having greatest part equal to the integer m. +## Since partitions use positive parts, this returns the empty list if +## n \leq 0 or m \leq 0. +## PartitionsGreatestEQ( 6, 3 ); +## [ [ 3, 1, 1, 1 ], [ 3, 2, 1 ], [ 3, 3 ] ] +## gap> PartitionsGreatestEQ( 0, 1 ); +## [ ] +## ]]> ## ## ## <#/GAPDoc> diff --git a/lib/combinat.gi b/lib/combinat.gi index 4973b1a09d..672992d0d5 100644 --- a/lib/combinat.gi +++ b/lib/combinat.gi @@ -1887,7 +1887,7 @@ end); ############################################################################# ## -#F PartitionsGreatestLE( , ) . . . set of partitions of n parts <= m +#F PartitionsGreatestLE( , ) . . . partitions of n with parts <= m ## ## returns the set of all (unordered) partitions of the integer having ## parts less or equal to the integer . @@ -1984,11 +1984,8 @@ function(n,m) parts := []; else if n = 0 then - if m = 0 then - parts := [ [ ] ]; - else - parts := [ ]; - fi; + # The empty partition satisfies every nonnegative upper bound. + parts := [ [ ] ]; else if m = 0 then parts := [ ]; @@ -2003,7 +2000,7 @@ end); ############################################################################# ## -#F PartitionsGreatestEQ( , ) . . . . set of partitions of n parts = n +#F PartitionsGreatestEQ( , ) . . . . partitions of n with max part m ## ## returns the set of all (unordered) partitions of the integer having ## greatest part equal to the integer . @@ -2041,7 +2038,6 @@ BindGlobal( "GPartitionsGreatestEQ", function(n,m) # This works exactly as `GPartitionsGreatestLE' for n-m and m and # adds a part m to all partitions. This is however done effectively # during the work. - # This is the same as `Partitions(n,m)' in the GAP library. # n and m must be a natural numbers >= 1. local B,j,k,l,p,res; if m > n then return []; fi; # a special case diff --git a/tst/testinstall/combinat.tst b/tst/testinstall/combinat.tst index b34d4bbe92..f1bf71034f 100644 --- a/tst/testinstall/combinat.tst +++ b/tst/testinstall/combinat.tst @@ -388,6 +388,28 @@ gap> NrPartitions( 100 ); gap> NrPartitions( 100, 10 ); 2977866 +#F PartitionsGreatestLE( , ) . . . partitions with largest part <= m +gap> List( [0..3], m -> PartitionsGreatestLE( 0, m ) ); +[ [ [ ] ], [ [ ] ], [ [ ] ], [ [ ] ] ] +gap> Print(PartitionsGreatestLE( 6, 3 ),"\n"); +[ [ 1, 1, 1, 1, 1, 1 ], [ 2, 1, 1, 1, 1 ], [ 2, 2, 1, 1 ], [ 2, 2, 2 ], + [ 3, 1, 1, 1 ], [ 3, 2, 1 ], [ 3, 3 ] ] +gap> Partitions( 6 ) = PartitionsGreatestLE( 6, 6 ); +true +gap> List( [1..4], k -> +> Difference( PartitionsGreatestLE( 6, k ), +> PartitionsGreatestLE( 6, k-1 ) ) +> = PartitionsGreatestEQ( 6, k ) ); +[ true, true, true, true ] +gap> Difference( PartitionsGreatestLE( 0, 1 ), +> PartitionsGreatestLE( 0, 0 ) ) +> = PartitionsGreatestEQ( 0, 1 ); +true +gap> Print(PartitionsGreatestEQ( 6, 3 ),"\n"); +[ [ 3, 1, 1, 1 ], [ 3, 2, 1 ], [ 3, 3 ] ] +gap> PartitionsGreatestEQ( 0, 1 ); +[ ] + #F OrderedPartitions( ) . . . . set of ordered partitions of an integer gap> OrderedPartitions( 0 ); [ [ ] ] From d75e271c0a3226ba8278840c6ac9a9cd8eefec4a Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 28 Apr 2026 13:44:47 +0200 Subject: [PATCH 14/52] Avoid some uses of IdGroup (#6343) --- grp/clasmax.grp | 2 +- grp/simple.gi | 18 +++++++++--------- lib/grpnames.gi | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/grp/clasmax.grp b/grp/clasmax.grp index 4d9daf2c2b..29ba01297a 100644 --- a/grp/clasmax.grp +++ b/grp/clasmax.grp @@ -25895,7 +25895,7 @@ local l,a,gf,conj,r,gp; (r^2=q and IsPrime(r) and r mod 10 in [3,7]) then # are the SL(2,5) in class S included ? (Depends on package status) - if not ForAny(l,x->Size(x)=120 and IdGroup(x)=[120,5]) then + if not ForAny(l,x->Size(x)=120 and IsPerfectGroup(x)) then # An A5, and its GL-conjugate gf:=GF(q); a:=Filtered(IrreducibleModules(TransitiveGroup(24,201),gf)[2], diff --git a/grp/simple.gi b/grp/simple.gi index c27d3078f4..c9a595c680 100644 --- a/grp/simple.gi +++ b/grp/simple.gi @@ -968,15 +968,15 @@ local nam,e,efactors,par,expo,prime,result,aut,i,classical,classaut,shortname, local s; if IsCyclic(gp) then return String(Size(gp)); - elif IdGroup(gp)=[4,2] then + elif Size(gp)=4 then return "2^2"; - elif IdGroup(gp)=[6,1] then + elif Size(gp)=6 then return "3.2"; - elif IdGroup(gp)=[8,3] then + elif Size(gp)=8 and IsDihedralGroup(gp) then return "2^2.2"; - elif IdGroup(gp)=[9,2] then + elif Size(gp)=9 then return "3^2"; - elif IdGroup(gp)=[18,3] then + elif Size(gp)=18 and Size(DerivedSubgroup(gp))=3 then return "3^2.2"; elif Size(gp)<=31 or Size(gp) in [33..47] then s:=StructureDescription(gp); @@ -1163,18 +1163,18 @@ local nam,e,efactors,par,expo,prime,result,aut,i,classical,classaut,shortname, if efactors<>fail and Size(classaut)<>Product(efactors) then Error("outer automorphism efactor fail"); fi; - if IdGroup(classaut)=[4,2] then + if Size(classaut)=4 and not IsCyclic(classaut) then # subgroup classes V4 e:=[[2,"2_1"],[2,"2_2"],[2,"2_3"],[4,"2^2"]]; - elif IdGroup(classaut)=[6,1] then + elif Size(classaut)=6 and not IsCyclic(classaut) then # subgroup classes S_3 e:=[ [ 2, "2" ], [ 3, "3" ], [ 6, "3.2" ] ]; - elif IdGroup(classaut)=[12,4] then + elif Size(classaut)=12 and IsDihedralGroup(classaut) then # subgroup classes 2\times S_3 (since S3 cannot act on C2) e:=[ [ 2, "2_1" ], [ 2, "2_2" ], [ 2, "2_3" ], [ 3, "3" ], [ 4, "2^2" ], [ 6, "3.2_1" ], [ 6, "3.2_2" ], [ 6, "6" ], [ 12, "3.2^2" ] ]; - elif IdGroup(classaut)=[24,12] then + elif Size(classaut)=24 and Size(DerivedSubgroup(classaut))=12 then # subgroup classes S_4 e:=[ [ 2, "2_1" ],[ 2, "2_2" ], [ 3, "3" ], [ 4, "4" ], [ 4, "(2^2)_{111}" ], [4,"(2^2)_{122}"], diff --git a/lib/grpnames.gi b/lib/grpnames.gi index 33d793ac5c..af9fdb5b01 100644 --- a/lib/grpnames.gi +++ b/lib/grpnames.gi @@ -1208,7 +1208,7 @@ InstallMethod( IsAlternatingGroup, SetAlternatingDegree(G,0); return true; elif Size(G) = 3 then SetAlternatingDegree(G,3); return true; - elif Size(G) = 12 and IdGroup(G) = [ 12, 3 ] then + elif Size(G) = 12 and Size(DerivedSubgroup(G)) = 4 then SetAlternatingDegree(G,4); return true; else return false; fi; fi; From 549080bf753ccf8f00b07e3539613272d45ac7fb Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 24 Apr 2026 09:16:59 +0100 Subject: [PATCH 15/52] adding a few examples --- doc/ref/matobj.xml | 6 +++--- lib/matobj1.gd | 38 ++++++++++++++++++++++++++++---------- lib/matobj2.gd | 12 ++++++++++++ 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index c7d6857083..5f6d2a5e28 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -26,7 +26,7 @@ cf. Chapters and . Some Elementary Examples Just to give a flavour of these new objects, we construct here two vectors and a matrix in these new forms. -The elements should all belong to a semiring R +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 @@ -60,8 +60,8 @@ gap> Display( (v1+v2) * TransposedMat(M) ); 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. +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 . diff --git a/lib/matobj1.gd b/lib/matobj1.gd index ff53201b9c..f93b224566 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 +## m := [ [1,2,3,4], [6,7,8,9] ];; +## gap> [ IsMatrix( m ), IsMatrixObj( m ), IsMatrixOrMatrixObj( m ) ]; +## [ true, false, true ] +## m := Matrix( Integers, [ [1,2,3,4], [6,7,8,9] ] );; +## gap> [ IsMatrix( m ), IsMatrixObj( m ), IsMatrixOrMatrixObj( m ) ]; +## [ false, true, true ] ## ]]> ## ## @@ -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. +##

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

+## BaseDomain( v ); +## Rationals +## ]]> ## ## ## <#/GAPDoc> @@ -317,6 +327,14 @@ DeclareAttribute( "BaseDomain", IsVecOrMatObj ); ## are synonyms of ## and ## , respectively. +##

+## NumberRows( m ); +## 2 +## gap> NrCols( m ); +## 4 +## ]]> ## ## ## <#/GAPDoc> diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 21f4af9a32..cb6b40918a 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -198,6 +198,11 @@ 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. +##

+## ConstructingFilter( v ); +## ## ## ## <#/GAPDoc> @@ -222,6 +227,13 @@ 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. +##

+## ConstructingFilter( m ); +## +## gap> CompatibleVectorFilter( m ); +## ## ## ## <#/GAPDoc> From 7247dc759594c38d32a1162f44e84ecf287ca7bb Mon Sep 17 00:00:00 2001 From: cdwensley Date: Sun, 26 Apr 2026 21:22:16 +0100 Subject: [PATCH 16/52] a few more examples --- doc/ref/matobj.xml | 13 +++++- lib/matobj2.gd | 106 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 92 insertions(+), 27 deletions(-) diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index 5f6d2a5e28..81a02e9ff6 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -36,6 +36,9 @@ Basic arithmetic operations for vectors and matrices are available: see Sections and .

+Note that if M2, like M 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] );; @@ -55,6 +58,12 @@ gap> Display( (v1+v2) * TransposedMat(M) ); +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. @@ -103,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">
diff --git a/lib/matobj2.gd b/lib/matobj2.gd index cb6b40918a..eb38616f28 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -203,6 +203,7 @@ DeclareAttribute( "Length", IsVectorObj ); ## v := Vector( Rationals, [3,4,7,8] );; ## gap> ConstructingFilter( v ); ## +## ]]> ## ## ## <#/GAPDoc> @@ -565,27 +566,25 @@ DeclareOperation( "ScalarProduct", [ IsVectorObj, IsVectorObj ] ); ############################################################################# ## -#O ZeroVector( , , ) #O ZeroVector( , ) #O ZeroVector( , ) #O ZeroVector( , ) +#O ZeroVector( , , ) ## ## <#GAPDoc Label="VectorObj_ZeroVector"> ## ## ZeroVector -## ## ## ## +## ## ## 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 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 @@ -597,6 +596,11 @@ DeclareOperation( "ScalarProduct", [ IsVectorObj, IsVectorObj ] ); ## 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. @@ -604,33 +608,40 @@ DeclareOperation( "ScalarProduct", [ IsVectorObj, IsVectorObj ] ); ## 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( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); DeclareOperation( "ZeroVector", [ IsSemiring, IsInt ] ); DeclareOperation( "ZeroVector", [ IsInt, IsVecOrMatObj ] ); +DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); #DeclareOperation( "ZeroVector", [ IsInt, IsVectorObj ] ); #DeclareOperation( "ZeroVector", [ IsInt, IsMatrixOrMatrixObj ] ); ############################################################################# ## -#O Vector( , , ) -#O Vector( , , ) #O Vector( , ) #O Vector( , ) #O Vector( , ) #O Vector( , ) +#O Vector( , , ) +#O Vector( , , ) ## ## <#GAPDoc Label="Vector"> ## ## Vector -## -## ## ## ## +## +## ## ## 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. -##

## 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 +## value is guessed from R, with base domain R ## and entries given by the last argument. ##

## In the remaining cases with two arguments, @@ -676,6 +684,13 @@ DeclareOperation( "ZeroVector", [ IsInt, IsVecOrMatObj ] ); ## In this situation, the result is a row vector that is equal to ## v1 and whose internal representation fits to that of v2. ##

+## 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. @@ -691,17 +706,39 @@ DeclareOperation( "ZeroVector", [ IsInt, IsVecOrMatObj ] ); ## 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( IsZmodnZVectorRep, ZmodnZ(8), [ 1, 4, 7 ] );; +## Print( v4 ); +## NewVector(IsZmodnZVectorRep,Monoid( ... ),[ 1, 4, 7 ]) +## gap> BaseDomain( v4 ); +## (Integers mod 8) +## gap> v5 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 );; Print( v5 ); +## NewVector(IsZmodnZVectorRep,Monoid( ... ),[ 3, 4, 7, 8 ]) +## gap> v5[4]; +## ZmodnZObj( 0, 8 ) +## ]]> ## ## ## <#/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 ] ); +DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsList ] ); +DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsVectorObj ] ); ############################################################################# @@ -716,6 +753,10 @@ DeclareOperation( "Vector", [ IsList ] ); ## ## ## +## 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 @@ -736,6 +777,15 @@ DeclareOperation( "Vector", [ IsList ] ); ##

## 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> @@ -760,6 +810,10 @@ DeclareTagBasedOperation( "NewZeroVector", ## ## ## +## These three operations are constructors, and should only be used +## when , or +## do not give the desired result. +##

## For a filter filt, a semiring R, ## a positive integer ncols, and a list list, ## returns a matrix object which has @@ -2105,6 +2159,7 @@ DeclareOperationKernel( "SwapMatrixColumns", [ IsMatrixOrMatrixObj and IsMutable ## representation. ## If both of the matrices are lists-of-lists, then the operation is delegated ## row by row to . +##

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

## mat1 := [ [ 1, 2 ], [ 3, 4 ] ]; ## [ [ 1, 2 ], [ 3, 4 ] ] From 75b618b24d22b2f77a07b73b7248da675f16329a Mon Sep 17 00:00:00 2001 From: cdwensley Date: Tue, 28 Apr 2026 16:28:42 +0100 Subject: [PATCH 17/52] reordering Vector, ZeroVector, NewVector --- doc/ref/matobj.xml | 14 +++--- lib/matobj1.gd | 108 ++++++++++++++++++++++----------------------- lib/matobj2.gd | 30 +++++++------ 3 files changed, 78 insertions(+), 74 deletions(-) diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index 81a02e9ff6..e8f5bbcedc 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -25,7 +25,7 @@ cf. Chapters and .

Some Elementary Examples Just to give a flavour of these new objects, we construct here two vectors -and a matrix in these new forms. +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 @@ -36,7 +36,7 @@ Basic arithmetic operations for vectors and matrices are available: see Sections and .

-Note that if M2, like M had been defined over the integers +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> M := Matrix( dom, [ [1,2,3,4], [6,7,8,9] ] );; -gap> Display( M ); +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 ] @@ -54,12 +54,12 @@ gap> v2 := Vector( [-7..-4], v1 ); gap> Print( v1 + v2 ); NewVector(IsPlistVectorRep,Integers,[ -4, -2, 2, 4 ]) -gap> Display( (v1+v2) * TransposedMat(M) ); +gap> Display( (v1+v2) * TransposedMat( m1 ) ); -gap> M2 := Matrix( Rationals, [ [8,5], [7,4] ] );; -gap> Display( M2^(-1) ); +gap> m2 := Matrix( Rationals, [ [8,5], [7,4] ] );; +gap> Display( m2^(-1) ); <2x2-matrix over Rationals: [[ -4/3, 5/3 ] [ 7/3, -8/3 ] diff --git a/lib/matobj1.gd b/lib/matobj1.gd index f93b224566..c19130890f 100644 --- a/lib/matobj1.gd +++ b/lib/matobj1.gd @@ -110,11 +110,11 @@ DeclareCategory( "IsVectorObj", IsVector and IsVecOrMatObj and IsRowVectorOrVect ## argument. ##

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

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

## IsRowListMatrix( m ); +## gap> m1 := Matrix( Integers, [ [1,2,3,4], [6,7,8,9] ] );; +## gap> IsRowListMatrix( m1 ); ## true -## gap> Print( m[2] ); +## gap> Print( m1[2] ); ## NewVector(IsPlistVectorRep,Integers,[ 6, 7, 8, 9 ]) ## ]]> ## @@ -289,7 +289,7 @@ DeclareCategory( "IsRowListMatrix", IsMatrixObj ); ## . ##

## v := Vector( Rationals, [ 3, 4, 7, 8 ] );; ## gap> BaseDomain( v ); ## Rationals ## ]]> @@ -302,52 +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. -##

-## NumberRows( m ); -## 2 -## gap> NrCols( m ); -## 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 ); - - ############################################################################# ## #A OneOfBaseDomain( ) @@ -392,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 eb38616f28..4440bb4693 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -200,7 +200,7 @@ DeclareAttribute( "Length", IsVectorObj ); ## otherwise all vector or matrix objects with this filter are immutable. ##

## v := Vector( Rationals, [3,4,7,8] );; ## gap> ConstructingFilter( v ); ## ## ]]> @@ -230,11 +230,12 @@ DeclareAttribute( "ConstructingFilter", IsVecOrMatObj ); ## these vector objects, of fail if no such filter is known. ##

## ConstructingFilter( m ); +## gap> m1 := Matrix( Integers, [ [1,2,3,4], [6,7,8,9] ] );; +## gap> ConstructingFilter( m1 ); ## -## gap> CompatibleVectorFilter( m ); +## gap> CompatibleVectorFilter( m1 ); ## +## ]]> ## ## ## <#/GAPDoc> @@ -718,13 +719,13 @@ DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); ## true ## gap> Print( Vector( v0, v1 ) ); ## NewVector(IsPlistVectorRep,Integers,[ 6, 7, 8, 9 ]) -## gap> v4 := Vector( IsZmodnZVectorRep, ZmodnZ(8), [ 1, 4, 7 ] );; -## Print( v4 ); -## NewVector(IsZmodnZVectorRep,Monoid( ... ),[ 1, 4, 7 ]) -## gap> BaseDomain( v4 ); -## (Integers mod 8) -## gap> v5 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 );; Print( v5 ); +## gap> v4 := Vector( IsGF2VectorRep, GF(2), [ 0, 1, 2 ]*Z(2)^0 );; +## gap> Print( v4 ); +## [ 0*Z(2), Z(2)^0, 0*Z(2) ] +##. gap> v5 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 );; Print( v5 ); ## NewVector(IsZmodnZVectorRep,Monoid( ... ),[ 3, 4, 7, 8 ]) +## gap> BaseDomain( v5 ); +## (Integers mod 8) ## gap> v5[4]; ## ZmodnZObj( 0, 8 ) ## ]]> @@ -754,7 +755,8 @@ DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsVectorObj ] ); ## ## ## These two operations are constructors, and should only be used -## when or +## when or +## ## do not give the desired result. ##

## For a filter filt, a semiring R, and a list list @@ -811,8 +813,10 @@ DeclareTagBasedOperation( "NewZeroVector", ## ## ## These three operations are constructors, and should only be used -## when , or -## do not give the desired result. +## when , +## or +## +## do not give the desired result. ##

## For a filter filt, a semiring R, ## a positive integer ncols, and a list list, From 318b1a16401866511644eca20e5ec9f78e344e0c Mon Sep 17 00:00:00 2001 From: cdwensley Date: Tue, 28 Apr 2026 16:39:09 +0100 Subject: [PATCH 18/52] reordering Vector, ZeroVector, NewVector --- lib/matobj2.gd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 4440bb4693..51168efc77 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -717,12 +717,12 @@ DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); ## NewVector(IsPlistVectorRep,Integers,[ 11, 12, 13 ]) ## gap> v0 := [6..9];; IsVector( v0 ); ## true -## gap> Print( Vector( v0, v1 ) ); +## gap> Print( Vector( v0, v1 ) ); ## NewVector(IsPlistVectorRep,Integers,[ 6, 7, 8, 9 ]) ## gap> v4 := Vector( IsGF2VectorRep, GF(2), [ 0, 1, 2 ]*Z(2)^0 );; ## gap> Print( v4 ); ## [ 0*Z(2), Z(2)^0, 0*Z(2) ] -##. gap> v5 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 );; Print( v5 ); +##. gap> v5 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 );; Print( v5 ); ## NewVector(IsZmodnZVectorRep,Monoid( ... ),[ 3, 4, 7, 8 ]) ## gap> BaseDomain( v5 ); ## (Integers mod 8) @@ -757,7 +757,7 @@ DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsVectorObj ] ); ## These two operations are constructors, and should only be used ## when or ## -## do not give the desired result. +## do not give the desired result. ##

## For a filter filt, a semiring R, and a list list ## of elements that belong to R, @@ -814,9 +814,9 @@ DeclareTagBasedOperation( "NewZeroVector", ## ## These three operations are constructors, and should only be used ## when , -## or +## or ## -## do not give the desired result. +## do not give the desired result. ##

## For a filter filt, a semiring R, ## a positive integer ncols, and a list list, From 797154753e81971f9c7e9286e6eb1236a262e999 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Tue, 28 Apr 2026 19:01:25 +0100 Subject: [PATCH 19/52] reordering Vector, ZeroVector, NewVector --- lib/matobj2.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 51168efc77..234591062f 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -722,7 +722,7 @@ DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); ## gap> v4 := Vector( IsGF2VectorRep, GF(2), [ 0, 1, 2 ]*Z(2)^0 );; ## gap> Print( v4 ); ## [ 0*Z(2), Z(2)^0, 0*Z(2) ] -##. gap> v5 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 );; Print( v5 ); +## gap> v5 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 );; Print( v5 ); ## NewVector(IsZmodnZVectorRep,Monoid( ... ),[ 3, 4, 7, 8 ]) ## gap> BaseDomain( v5 ); ## (Integers mod 8) From 4bec05ff4cc1418a5abcfa820bec73234dfc955e Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 30 Apr 2026 23:13:19 +0200 Subject: [PATCH 20/52] Refine SetSize and remove some immediate methods (#6347) The removed methods mostly were already obsolete due to the custom SetSize. Only the "non emptiness" was not recorded right, which the new code in `SetSize` now handles. --- lib/coll.gi | 42 +++++++++++++++++++--------------------- lib/modfree.gi | 13 ------------- tst/testinstall/coll.tst | 13 ++++++------- 3 files changed, 26 insertions(+), 42 deletions(-) diff --git a/lib/coll.gi b/lib/coll.gi index 6736ccf5a8..7a53bdbb12 100644 --- a/lib/coll.gi +++ b/lib/coll.gi @@ -92,10 +92,6 @@ InstallMethod( PrintObj, ## #M IsEmpty() . . . . . . . . . . . . . . . test if a collection is empty ## -InstallImmediateMethod( IsEmpty, - IsCollection and HasSize, 0, - C -> Size( C ) = 0 ); - InstallMethod( IsEmpty, "for a collection", [ IsCollection ], @@ -111,10 +107,6 @@ InstallMethod( IsEmpty, ## #M IsTrivial() . . . . . . . . . . . . . test if a collection is trivial ## -InstallImmediateMethod( IsTrivial, - IsCollection and HasSize, 0, - C -> Size( C ) = 1 ); - InstallMethod( IsTrivial, "for a collection", [ IsCollection ], @@ -143,10 +135,6 @@ InstallMethod( IsNonTrivial, ## #M IsFinite() . . . . . . . . . . . . . . test if a collection is finite ## -InstallImmediateMethod( IsFinite, - IsCollection and HasSize, 0, - C -> not IsIdenticalObj( Size( C ), infinity ) ); - InstallMethod( IsFinite, "for a collection", [ IsCollection ], @@ -2879,17 +2867,27 @@ local filt; fi; # some sanity checks - Assert(0, not HasIsEmpty(obj) or (IsEmpty(obj) = (sz=0))); - Assert(0, not HasIsNonTrivial(obj) or (IsNonTrivial(obj) = (sz<>1))); - Assert(0, not HasIsTrivial(obj) or (IsTrivial(obj) = (sz=1))); - Assert(0, not HasIsFinite(obj) or (IsFinite(obj) = (sz<>infinity))); - - if sz=0 then filt:=IsEmpty; - elif sz=1 then filt:=IsTrivial; - elif sz=infinity then filt:=IsNonTrivial and HasIsFinite; - else filt:=IsNonTrivial and IsFinite; + Assert(1, not HasIsEmpty(obj) or (IsEmpty(obj) = (sz=0))); + Assert(1, not HasIsNonTrivial(obj) or (IsNonTrivial(obj) = (sz<>1))); + Assert(1, not HasIsTrivial(obj) or (IsTrivial(obj) = (sz=1))); + Assert(1, not HasIsFinite(obj) or (IsFinite(obj) = (sz<>infinity))); + + filt:=HasSize; + if sz=0 then + filt:=filt and IsEmpty; + else + filt:=filt and HasIsEmpty; + fi; + if sz=1 then + filt:=filt and IsTrivial; + else + filt:=filt and IsNonTrivial; + fi; + if sz=infinity then + filt:=filt and HasIsFinite; + else + filt:=filt and IsFinite; fi; - filt:=filt and HasSize; obj!.Size:=sz; SetFilterObj(obj,filt); end); diff --git a/lib/modfree.gi b/lib/modfree.gi index c88e380f42..86252154e8 100644 --- a/lib/modfree.gi +++ b/lib/modfree.gi @@ -104,16 +104,6 @@ InstallMethod( \in, ## ring is needed since all generator dependent questions are handled in the ## `IsTrivial' call.) ## -InstallImmediateMethod( IsFinite, - IsFreeLeftModule and HasIsFiniteDimensional, 0, - function( V ) - if not IsFiniteDimensional( V ) then - return false; - else - TryNextMethod(); - fi; - end ); - InstallMethod( IsFinite, "for a free left module", [ IsFreeLeftModule ], @@ -136,9 +126,6 @@ InstallMethod( IsFinite, ## #M IsTrivial( ) ## -InstallImmediateMethod( IsTrivial, IsFreeLeftModule and HasDimension, 0, - V -> Dimension( V ) = 0 ); - InstallMethod( IsTrivial, "for a free left module", [ IsFreeLeftModule ], diff --git a/tst/testinstall/coll.tst b/tst/testinstall/coll.tst index 88b68bdd7a..cc30a2ba9f 100644 --- a/tst/testinstall/coll.tst +++ b/tst/testinstall/coll.tst @@ -46,13 +46,12 @@ gap> List(props, p -> p(M0)); gap> N1:=Magma([[[1,0],[0,0]]]);; gap> ForAll(props, prop -> not Tester(prop)(N1)); true - -#gap> Size(N1); -#1 -#gap> ForAll(props, prop -> Tester(prop)(N1)); -#true -#gap> List(props, p -> p(N1)); -#[ false, true, false, true ] +gap> Size(N1); +1 +gap> ForAll(props, prop -> Tester(prop)(N1)); +true +gap> List(props, p -> p(N1)); +[ false, true, false, true ] # ... immediate methods for a collection which knows its size, # applied to collection with size greater than 1 From ae0135dbb12d4fa7a8aa34662350e87f9672f077 Mon Sep 17 00:00:00 2001 From: Christopher Jefferson Date: Mon, 4 May 2026 05:43:08 +0800 Subject: [PATCH 21/52] Fix HexSHA256 to always return 64 hex digits (#6358) When the SHA256 digest's leading byte(s) were zero, HexStringInt dropped those leading zero hex digits, so HexSHA256 returned a string shorter than 64 characters. Left-pad the result to 64 hex digits, since a SHA256 digest is always 256 bits. --- lib/files.gi | 8 +++++++- tst/testinstall/sha256.tst | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/files.gi b/lib/files.gi index f9c3dfd1f8..d710bc4d81 100644 --- a/lib/files.gi +++ b/lib/files.gi @@ -412,5 +412,11 @@ function(str) GAP_SHA256_UPDATE(s, str); res := GAP_SHA256_FINAL(s); res := Sum([0..7], i -> res[8-i]*2^(32*i));; - return LowercaseString(HexStringInt(res)); + res := LowercaseString(HexStringInt(res)); + # HexStringInt drops leading zero digits, but a SHA256 digest is always + # 256 bits = 64 hex digits, so left-pad with '0' if the top byte(s) were 0. + if Length(res) < 64 then + res := Concatenation(ListWithIdenticalEntries(64 - Length(res), '0'), res); + fi; + return res; end); diff --git a/tst/testinstall/sha256.tst b/tst/testinstall/sha256.tst index 3d0fcc1d0c..7f6988cb3a 100644 --- a/tst/testinstall/sha256.tst +++ b/tst/testinstall/sha256.tst @@ -32,6 +32,17 @@ gap> HexSHA256("abcd\r\n"); gap> HexSHA256(""); "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +# Inputs whose SHA256 starts with one or more zero hex digits: the result +# must still be 64 hex characters (the digest is always 256 bits). +gap> HexSHA256("39"); +"0b918943df0962bc7a1824c0555a389347b4febdc7cf9d1254406d80ce44e3f9" +gap> HexSHA256("286"); +"00328ce57bbc14b33bd6695bc8eb32cdf2fb5f3a7d89ec14a42825e15d39df60" +gap> HexSHA256("886"); +"000f21ac06aceb9cdd0575e82d0d85fc39bed0a7a1d71970ba1641666a44f530" +gap> ForAll(["", "abcd", "39", "286", "886"], s -> Length(HexSHA256(s)) = 64); +true + # gap> HexSHA256(InputTextString("abcd")); "88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589" From 361fc32fe0ef54c88e43db8e9c1e447232e10537 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 30 Apr 2026 15:04:45 +0100 Subject: [PATCH 22/52] examples for Matrix --- lib/matobj2.gd | 121 +++++++++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 44 deletions(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 234591062f..ea427ce20e 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -615,7 +615,7 @@ DeclareOperation( "ScalarProduct", [ IsVectorObj, IsVectorObj ] ); ## 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); +## 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 ]) @@ -674,17 +674,17 @@ DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); ## 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 ## @@ -719,15 +719,17 @@ DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); ## true ## gap> Print( Vector( v0, v1 ) ); ## NewVector(IsPlistVectorRep,Integers,[ 6, 7, 8, 9 ]) -## gap> v4 := Vector( IsGF2VectorRep, GF(2), [ 0, 1, 2 ]*Z(2)^0 );; -## gap> Print( v4 ); +## 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> v5 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 );; Print( v5 ); -## NewVector(IsZmodnZVectorRep,Monoid( ... ),[ 3, 4, 7, 8 ]) -## gap> BaseDomain( v5 ); +## gap> v6 := Vector( IsZmodnZVectorRep, ZmodnZ(8), v1 ); +## +## gap> BaseDomain( v6 ); ## (Integers mod 8) -## gap> v5[4]; -## ZmodnZObj( 0, 8 ) +## gap> v7 := Vector( IsZmodnZVectorRep, ZmodnZ(12), v0 ); +## ## ]]> ## ## @@ -1317,63 +1319,56 @@ 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"> ## ## Matrix -## -## -## -## ## +## ## -## ## +## ## -## ## +## +## +## +## ## ## 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 -## M, respectively. +## value is guessed from R, with base domain R +## and entries given by the argument list. ## 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 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 @@ -1381,12 +1376,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. @@ -1404,6 +1406,37 @@ DeclareOperation( "CompanionMatrix", ## Default methods for ## ## delegate to . +## m1 := Matrix( Integers, [ [3,4,5], [6,7,8] ] );; Print( m1 ); +## NewMatrix(IsPlistMatrixRep,Integers,3,[ [ 3, 4, 5 ], [ 6, 7, 8 ] ]) +## gap> m2 := Matrix( Rationals, [10..30], 7 );; Display( m2 ); +## <3x7-matrix over Rationals: +## [[ 10 .. 16 ] +## [ 17 .. 23 ] +## [ 24 .. 30 ] +## ]> +gap> Print( Matrix( Integers, m2 ) ); +NewMatrix(IsPlistMatrixRep,Integers,7, +[ [ 10 .. 16 ], [ 17 .. 23 ], [ 24 .. 30 ] ]) +gap> m3 := Matrix( [[7,6],[4,3]], m2 );; Print(m3); +NewMatrix(IsPlistMatrixRep,Rationals,2,[ [ 7, 6 ], [ 4, 3 ] ]) +gap> m4 := Matrix( [-7..-2], 3, m2 );; Print(m4); +NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ -7, -6, -5 ], [ -4, -3, -2 ] ]) +gap> m0 := [[-1,-2],[-3,-4]];; IsMatrix(m0); +true +gap> Print( Matrix( m0, m1 ) ); +NewMatrix(IsPlistMatrixRep,Integers,2,[ [ -1, -2 ], [ -3, -4 ] ]) +gap> Print( Matrix( [-9..-4], 3, m1 ) ); +NewMatrix(IsPlistMatrixRep,Integers,3,[ [ -9, -8, -7 ], [ -6, -5, -4 ] ]) +gap> m5 := Matrix( [ [0,1,2], [7,8,9] ] );; Print( m5 ); +NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 0, 1, 2 ], [ 7, 8, 9 ] ]) +gap> m6 := Matrix( IsGF2MatrixRep, GF(2), [[1,0,1],[0,1,0]]*Z(2)^0 );; +gap> Display( m6 ); + 1 . 1 + . 1 . +gap> m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 ); + +## ]]> ## ## ## <#/GAPDoc> From ba798f833e132025332fe8c569e612cf676d7b4d Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 1 May 2026 08:54:58 +0100 Subject: [PATCH 23/52] examples for Matrix --- lib/matobj2.gd | 79 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index ea427ce20e..c7fb9ef3ac 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -857,6 +857,11 @@ DeclareTagBasedOperation( "NewZeroVector", ##

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

+## Matrix( IsPlistMatrixRep, Integers, [ [4,5,6], [7,8,9] ] ); +## <2x3-matrix over Integers> +## ]]> ## ## ## <#/GAPDoc> @@ -1198,6 +1203,20 @@ DeclareSynonym( "SetMatElm", ASS_MAT ); ## 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> @@ -1245,6 +1264,21 @@ DeclareOperation( "ZeroMatrix", [ IsOperation, IsSemiring, IsInt, IsInt ] ); ## 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> @@ -1406,6 +1440,7 @@ 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 ] ]) @@ -1415,27 +1450,29 @@ DeclareOperation( "CompanionMatrix", ## [ 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 ); - +## 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 ); +## ## ]]> ## ## From f3e317d3fd91318c74f120bbf0c57ea625afbc62 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Mon, 4 May 2026 12:33:47 +0100 Subject: [PATCH 24/52] added alternative versions of NewMatrix --- lib/matobj2.gd | 34 ++++++++++++++++++++++++++++++---- lib/matobjplist.gi | 11 +++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index c7fb9ef3ac..29210efb02 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -803,6 +803,8 @@ DeclareTagBasedOperation( "NewZeroVector", ############################################################################# ## #O NewMatrix( , , , ) +#O NewMatrix( , , , ) +#O NewMatrix( , , ) #O NewZeroMatrix( , , , ) #O NewIdentityMatrix( , , ) ## @@ -810,15 +812,21 @@ DeclareTagBasedOperation( "NewZeroVector", ## ## NewMatrix, NewZeroMatrix, NewIdentityMatrix ## +## +## ## ## ## ## ## These three operations are constructors, and should only be used -## when , +## by those implementing new material for matrix objects. +## Most users should find +## , ## or ## -## do not give the desired result. +## sufficient for their requirements. ##

## For a filter filt, a semiring R, ## a positive integer ncols, and a list list, @@ -838,6 +846,10 @@ DeclareTagBasedOperation( "NewZeroVector", ## 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. ##

@@ -859,8 +871,16 @@ DeclareTagBasedOperation( "NewZeroVector", ## . ##

## Matrix( IsPlistMatrixRep, Integers, [ [4,5,6], [7,8,9] ] ); -## <2x3-matrix over Integers> +## gap> 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 ); +## ## ]]> ## ## @@ -869,6 +889,12 @@ DeclareTagBasedOperation( "NewZeroVector", DeclareTagBasedOperation( "NewMatrix", [ IsOperation, IsSemiring, IsInt, IsList] ); +DeclareOperation( "NewMatrix", + [ IsOperation, IsSemiring, IsList, IsInt] ); + +DeclareOperation( "NewMatrix", + [ IsOperation, IsSemiring, IsList] ); + DeclareTagBasedOperation( "NewZeroMatrix", [ IsOperation, IsSemiring, IsInt, IsInt ] ); diff --git a/lib/matobjplist.gi b/lib/matobjplist.gi index cafe1dd7d6..c3277ff899 100644 --- a/lib/matobjplist.gi +++ b/lib/matobjplist.gi @@ -188,6 +188,17 @@ InstallTagBasedMethod( NewZeroVector, return MakeIsPlistVectorRep(basedomain, list, false); end ); +# these two methods align NewMatrix with Matrix +InstallMethod( NewMatrix, [ IsOperation, IsSemiring, IsList, IsInt ], + function( filter, basedomain, list, ncols ) + return NewMatrix( filter, basedomain, ncols, list ); + end); + +InstallMethod( NewMatrix, [ IsOperation, IsSemiring, IsList ], + function( filter, basedomain, list ) + return NewMatrix( filter, basedomain, Length( list[1] ), list ); + end); + InstallTagBasedMethod( NewMatrix, IsPlistMatrixRep, function( filter, basedomain, ncols, list ) From 375569abe5ad623922745190750924f8645eabad Mon Sep 17 00:00:00 2001 From: cdwensley Date: Mon, 4 May 2026 12:45:21 +0100 Subject: [PATCH 25/52] remove trailing spaces --- lib/matobj2.gd | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 29210efb02..006e976705 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -872,12 +872,12 @@ DeclareTagBasedOperation( "NewZeroVector", ##

## m1 := NewMatrix( IsPlistMatrixRep, Integers, 3, [ [4,5,6], [7,8,9] ] );; -## gap> Display( m1 ); +## gap> Display( m1 ); ## <2x3-matrix over Integers: ## [[ 4, 5, 6 ] ## [ 7, 8, 9 ] ## ]> -## gap> NewZeroMatrix( IsPlistMatrixRep, Rationals, 5, 3 ); +## gap> NewZeroMatrix( IsPlistMatrixRep, Rationals, 5, 3 ); ## <5x3-matrix over Rationals> ## gap> NewIdentityMatrix( IsGF2MatrixRep, GF(2), 4 ); ## @@ -1232,9 +1232,9 @@ DeclareSynonym( "SetMatElm", ASS_MAT ); ##

## m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 );; -## gap> z7 := ZeroMatrix( 2, 2, m7 );; Print( z7 ); +## gap> z7 := ZeroMatrix( 2, 2, m7 );; Print( z7 ); ## NewMatrix(IsZmodnZMatrixRep,Monoid( ... ),2, -## [ [ ZmodnZObj( 0, 8 ), ZmodnZObj( 0, 8 ) ], +## [ [ 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 ] ]) @@ -1293,9 +1293,9 @@ DeclareOperation( "ZeroMatrix", [ IsOperation, IsSemiring, IsInt, IsInt ] ); ##

## m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 );; -## gap> id7 := IdentityMatrix( 2, m7 );; Print( id7 ); +## gap> id7 := IdentityMatrix( 2, m7 );; Print( id7 ); ## NewMatrix(IsZmodnZMatrixRep,Monoid( ... ),2, -## [ [ ZmodnZObj( 1, 8 ), ZmodnZObj( 0, 8 ) ], +## [ [ 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 ] ]) @@ -1476,12 +1476,12 @@ DeclareOperation( "CompanionMatrix", ## [ 17 .. 23 ] ## [ 24 .. 30 ] ## ]> -## gap> Print( Matrix( Integers, m2 ) ); +## 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); +## 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 @@ -1492,12 +1492,12 @@ DeclareOperation( "CompanionMatrix", ## 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 ); +## gap> Display( m6 ); ## 1 . 1 ## . 1 . ## gap> m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 ); ## -## gap> m8 := Matrix( IsZmodnZMatrixRep, ZmodnZ(12), m0 ); +## gap> m8 := Matrix( IsZmodnZMatrixRep, ZmodnZ(12), m0 ); ## ## ]]> ## From 4bf9641b46884a804e47a6f85baf454efc346d4a Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 4 May 2026 16:09:00 +0100 Subject: [PATCH 26/52] Fix garbled result produced by CosetLeadersMatFFE (#6325) When invoked on compressed matrices over small finite fields, CosetLeadersMatFFE sometimes would produce incorrect output with gaps in it (i.e., undefined entries) AI assistance: Codex investigated the 8-bit fast path, added a regression test, and prepared the fix. Co-authored-by: Codex --- src/vec8bit.c | 24 +++++++++++++---- tst/testbugfix/2026-04-15-issue-5923.tst | 33 ++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 tst/testbugfix/2026-04-15-issue-5923.tst diff --git a/src/vec8bit.c b/src/vec8bit.c index 397649b2c3..60243625c4 100644 --- a/src/vec8bit.c +++ b/src/vec8bit.c @@ -2482,6 +2482,7 @@ static UInt CosetLeadersInner8Bits(Obj veclis, UInt elts; UInt1 * ptr, *ptrw; const UInt1 * gettab; + const Obj * gapseq; const UInt1 * feltffe; Obj x; Obj vp; @@ -2491,6 +2492,7 @@ static UInt CosetLeadersInner8Bits(Obj veclis, elts = ELS_BYTE_FIELDINFO_8BIT(info); settab = SETELT_FIELDINFO_8BIT(info); gettab = GETELT_FIELDINFO_8BIT(info); + gapseq = GAPSEQ_FELT_FIELDINFO_8BIT(info); ptrw = BYTES_VEC8BIT(w); if (weight == 1) { for (i = pos; i <= len; i++) { @@ -2498,13 +2500,21 @@ static UInt CosetLeadersInner8Bits(Obj veclis, u = ELM_PLIST(vp, 1); AddVec8BitVec8BitInner(w, w, u, 1, lenw); ptr = BYTES_VEC8BIT(v) + (i - 1) / elts; - *ptr = settab[*ptr + 256 * (elts + ((i - 1) % elts))]; + // Keep the coefficient vector in the same sorted field-element + // order that NumberFFVector uses for list indices. + feltffe = FELT_FFE_FIELDINFO_8BIT(info); + x = ELM_PLIST(felts, 2); + *ptr = settab[*ptr + 256 * (elts * feltffe[VAL_FFE(x)] + + ((i - 1) % elts))]; sy = 0; for (j = 0; j < lenw; j++) { UInt xxxx; sy *= q; xxxx = gettab[ptrw[j / elts] + 256 * (j % elts)]; - sy += xxxx; + // The packed 8-bit representation uses a different internal + // field ordering, so translate back to GAP's sequence before + // using the syndrome number as a plain-list position. + sy += INT_INTOBJ(gapseq[xxxx]); } if ((Obj)0 == ELM_PLIST(leaders, sy + 1)) { UInt k; @@ -2517,10 +2527,13 @@ static UInt CosetLeadersInner8Bits(Obj veclis, wc = ZeroVec8Bit(q, lenw, 1); settab = SETELT_FIELDINFO_8BIT(info); gettab = GETELT_FIELDINFO_8BIT(info); + gapseq = GAPSEQ_FELT_FIELDINFO_8BIT(info); ptr = BYTES_VEC8BIT(v) + (i - 1) / elts; ptrw = BYTES_VEC8BIT(w); - for (k = 2; k < q; k++) { - qk = FFE_FELT_FIELDINFO_8BIT(info, k); + for (k = 3; k <= q; k++) { + // Record scalar multiples in the same order as the GAP + // fallback, namely the sorted field elements in 'felts'. + qk = ELM_PLIST(felts, k); MultVec8BitFFEInner(wc, w, qk, 1, lenw); ptrw = BYTES_VEC8BIT(wc); sy = 0; @@ -2528,11 +2541,12 @@ static UInt CosetLeadersInner8Bits(Obj veclis, UInt xxxx; sy *= q; xxxx = gettab[ptrw[j / elts] + 256 * (j % elts)]; - sy += xxxx; + sy += INT_INTOBJ(gapseq[xxxx]); } vc = ZeroVec8Bit(q, len, 0); settab = SETELT_FIELDINFO_8BIT(info); gettab = GETELT_FIELDINFO_8BIT(info); + gapseq = GAPSEQ_FELT_FIELDINFO_8BIT(info); ptr = BYTES_VEC8BIT(v) + (i - 1) / elts; ptrw = BYTES_VEC8BIT(w); MultVec8BitFFEInner(vc, v, qk, 1, len); diff --git a/tst/testbugfix/2026-04-15-issue-5923.tst b/tst/testbugfix/2026-04-15-issue-5923.tst new file mode 100644 index 0000000000..781733cd55 --- /dev/null +++ b/tst/testbugfix/2026-04-15-issue-5923.tst @@ -0,0 +1,33 @@ +# Regression test for issue #5923: the 8-bit kernel path for +# CosetLeadersMatFFE must not leave holes in the result list. +gap> F := GF(4);; +gap> M := One(F)*[[1,0,Z(4)],[0,1,Z(4)^2]];; +gap> L := CosetLeadersMatFFE(M, F);; +gap> Length(L) = Size(F)^2; +true +gap> ForAll([1..Length(L)], i -> IsBound(L[i])); +true +gap> List(L, v -> NumberFFVector(M * v, Size(F))) = [0..Length(L)-1]; +true + +# some additional tests "because we can" for other cases +gap> F := GF(2);; +gap> M := One(F)*[[1,0,1,0,1,0],[1,1,1,0,0,0]];; +gap> L := CosetLeadersMatFFE(M, F);; +gap> Length(L) = Size(F)^2; +true +gap> ForAll([1..Length(L)], i -> IsBound(L[i])); +true +gap> List(L, v -> NumberFFVector(M * v, Size(F))) = [0..Length(L)-1]; +true + +# some additional tests "because we can" for other cases +gap> F := GF(257);; +gap> M := One(F)*[[1,0,1,0,1,0],[1,1,1,0,0,0]];; +gap> L := CosetLeadersMatFFE(M, F);; +gap> Length(L) = Size(F)^2; +true +gap> ForAll([1..Length(L)], i -> IsBound(L[i])); +true +gap> List(L, v -> NumberFFVector(M * v, Size(F))) = [0..Length(L)-1]; +true From 99d2b4d334ece172fff77f690e9f7c1a390789bd Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 4 May 2026 16:09:32 +0100 Subject: [PATCH 27/52] Fix crash in `CosetLeadersMatFFE` (#6326) Reject matrices with dependent rows before building the internal search tables for CosetLeadersMatFFE. This avoids a crash in the 8-bit path and restores correct behaviour for square full-rank inputs. AI assistance: Codex reproduced the crash, traced it to the internal row-independence assumption, added a regression test, and prepared the fix. Co-authored-by: Codex --- lib/listcoef.gi | 9 ++++++--- src/vec8bit.c | 2 ++ src/vecgf2.c | 2 ++ tst/testbugfix/2026-04-15-CosetLeadersMatFFE-errors.tst | 8 ++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 tst/testbugfix/2026-04-15-CosetLeadersMatFFE-errors.tst diff --git a/lib/listcoef.gi b/lib/listcoef.gi index 8519d78cf5..106ab14463 100644 --- a/lib/listcoef.gi +++ b/lib/listcoef.gi @@ -1516,10 +1516,14 @@ InstallMethod(CosetLeadersMatFFE,"generic",IsCollsElms, q := Size(f); n := Length(mat[1]); m := Length(mat); + # The search below assumes the rows form a basis for an m-dimensional + # syndrome space, so reject dependent input before building the column data. + if RankMat(mat) <> m then + Error("CosetLeadersMatFFE: must have linearly independent rows"); + fi; tofind := q^m; t := TransposedMat(mat); - vl := []; - vl[m+1] := false; + vl := EmptyPlist(m); felts := AsSSortedList(f); Assert(2, felts[1] = Zero(f)); nzfelts := felts{[2..q]}; @@ -1537,7 +1541,6 @@ InstallMethod(CosetLeadersMatFFE,"generic",IsCollsElms, Add(vl[i], v*fds[j]); fi; od; - Add(vl[i],false); od; v := ListWithIdenticalEntries(n, felts[1]); w := ZeroOp(t[1]); diff --git a/src/vec8bit.c b/src/vec8bit.c index 60243625c4..9137672f8c 100644 --- a/src/vec8bit.c +++ b/src/vec8bit.c @@ -2604,8 +2604,10 @@ static Obj FuncCOSET_LEADERS_INNER_8BITS( Obj v, w; UInt lenv, lenw, q; + RequirePlainList(SELF_NAME, veclis); RequireSmallInt(SELF_NAME, weight); RequireSmallInt(SELF_NAME, tofind); + RequirePlainList(SELF_NAME, leaders); lenv = LEN_PLIST(veclis); q = LEN_PLIST(felts); diff --git a/src/vecgf2.c b/src/vecgf2.c index 69f1c9e8a1..6c3e64a1c2 100644 --- a/src/vecgf2.c +++ b/src/vecgf2.c @@ -3262,8 +3262,10 @@ static Obj FuncCOSET_LEADERS_INNER_GF2( Obj v, w; UInt lenv, lenw; + RequirePlainList(SELF_NAME, veclis); RequireSmallInt(SELF_NAME, weight); RequireSmallInt(SELF_NAME, tofind); + RequirePlainList(SELF_NAME, leaders); lenv = LEN_PLIST(veclis); NEW_GF2VEC(v, TYPE_LIST_GF2VEC, lenv); diff --git a/tst/testbugfix/2026-04-15-CosetLeadersMatFFE-errors.tst b/tst/testbugfix/2026-04-15-CosetLeadersMatFFE-errors.tst new file mode 100644 index 0000000000..75303e5941 --- /dev/null +++ b/tst/testbugfix/2026-04-15-CosetLeadersMatFFE-errors.tst @@ -0,0 +1,8 @@ +# Regression test for square matrices and invalid dependent input in +# CosetLeadersMatFFE. +gap> M := IdentityMat(2, GF(2));; +gap> L := CosetLeadersMatFFE(M, GF(2));; +gap> Length(L); +4 +gap> CosetLeadersMatFFE(L, GF(2)); +Error, CosetLeadersMatFFE: must have linearly independent rows From 509f33ff9f52b3c28c43cfe825e4782fa22cf37f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 4 May 2026 19:28:42 +0100 Subject: [PATCH 28/52] Fix MinimalGeneratingSet for pc groups (#6340) It sometimes produced incorrect results, where at least one generator was simply redundant. Revisit the pc-group candidates when a layer contracts. This drops generators that were only needed earlier. Later layer adjustments can change the induced pcgs. AI-assisted by Codex for investigation, testing, and implementation. Co-authored-by: Codex --- lib/grppcatr.gi | 29 +++++++++++++++++++++++- tst/testbugfix/2026-04-20-issue-5771.tst | 29 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tst/testbugfix/2026-04-20-issue-5771.tst diff --git a/lib/grppcatr.gi b/lib/grppcatr.gi index b0f171adf7..0f9a42d7bf 100644 --- a/lib/grppcatr.gi +++ b/lib/grppcatr.gi @@ -541,6 +541,27 @@ RedispatchOnCondition( MaximalNormalSubgroups, true, [ IsSolvableGroup ], 0); +############################################################################# +## +#F ReduceMinGens( , , ) +## +BindGlobal( "ReduceMinGens", function( pcgs, pcgsN, min ) + local i, new; + + # Later layer refinements can make a previously appended generator + # redundant. Re-test the current candidates against the bottom layer. + i := 1; + while i <= Length( min ) do + new := min{Filtered([1..Length( min )], j -> j <> i)}; + if Length( InducedPcgsByPcSequenceAndGenerators( pcgs, pcgsN, new ) ) + = Length( pcgs ) then + Remove( min, i ); + else + i := i + 1; + fi; + od; +end ); + ############################################################################# ## #F ModifyMinGens( , , , ) @@ -551,7 +572,8 @@ BindGlobal( "ModifyMinGens", function( pcgs, pcgsS, pcgsL, min ) # set up pcgsF := pcgsS mod pcgsL; - # try to modify mingens + # Try to absorb a generator from the current factor into one of the + # existing candidates before growing the generating set. for g in pcgsF do for i in [1..Length( min )] do new := ShallowCopy( min ); @@ -598,8 +620,13 @@ BindGlobal( "MinimalGensLayer", function( pcgs, pcgsS, pcgsN, min ) pcgsV := InducedPcgsByPcSequenceAndGenerators( pcgs, pcgsL, min ); pcgsU := InducedPcgsByPcSequenceAndGenerators( pcgs, pcgsN, min ); if Length( pcgs ) = Length( pcgsV ) then + # Once the current candidates span the whole layer, continue with + # the next smaller layer and revisit any earlier append decisions. pcgsS := pcgsL; Remove(series); + ReduceMinGens( pcgs, pcgsN, min ); + pcgsV := InducedPcgsByPcSequenceAndGenerators( pcgs, pcgsS, min ); + pcgsU := InducedPcgsByPcSequenceAndGenerators( pcgs, pcgsN, min ); fi; od; return min; diff --git a/tst/testbugfix/2026-04-20-issue-5771.tst b/tst/testbugfix/2026-04-20-issue-5771.tst new file mode 100644 index 0000000000..ea28b64c29 --- /dev/null +++ b/tst/testbugfix/2026-04-20-issue-5771.tst @@ -0,0 +1,29 @@ +## Regression test for #5771. The MinimalGeneratingSet method for pc-groups +## greedily appended a fifth generator, even though later adjustments make +## that generator redundant. The minimal generating set for this group has +## size 4, but GAP gave one of size 5, with one redundant generator. + +gap> START_TEST("2026-04-20-issue-5771.tst"); +gap> G := function() +> local f, g, g1, g2, g3, g4, g5, g6, g7, g8, g9, rws, rels, x; +> f := FreeGroup(IsSyllableWordsFamily, 9); +> g := GeneratorsOfGroup(f); +> g1 := g[1]; g2 := g[2]; g3 := g[3]; g4 := g[4]; g5 := g[5]; +> g6 := g[6]; g7 := g[7]; g8 := g[8]; g9 := g[9]; +> rws := SingleCollector(f, [ 2, 2, 2, 2, 3, 3, 3, 3, 3 ]); +> rels := [ +> [5,1,g5], [9,1,g9], [5,2,g5], [6,2,g6], [7,2,g7], +> [8,2,g8], [9,2,g9], [6,3,g6], [7,3,g7], [8,3,g8], +> [5,4,g5], [6,4,g6], [7,4,g7], [8,4,g8], [9,4,g9] +> ]; +> for x in rels do +> SetCommutator(rws, x[1], x[2], x[3]); +> od; +> return GroupByRwsNC(rws); +> end();; +gap> m := MinimalGeneratingSet(G);; +gap> Length(m) = 4 and +> ForAll([1..Length(m)], +> i -> Index(G, SubgroupNC(G, m{Filtered([1..Length(m)], j -> j <> i)})) > 1); +true +gap> STOP_TEST("2026-04-20-issue-5771.tst"); From 99c4a09294d639a9eb2ecc084578a6cd461e8d50 Mon Sep 17 00:00:00 2001 From: Kamil Zabielski <50334623+limakzi@users.noreply.github.com> Date: Mon, 4 May 2026 20:48:24 +0100 Subject: [PATCH 29/52] Add `WhereDepth` user preference (#6261) ... to control depth of initial stack trace in break loops --- doc/ref/mloop.xml | 11 ++++++++++- lib/error.g | 7 +++++-- lib/init.g | 10 ++++++++++ tst/testspecial/run_gap.sh | 1 + tst/testspecial/stack-trace-depth.g | 5 ++++- tst/testspecial/stack-trace-depth.g.out | 18 ++++++++++++++++-- 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/doc/ref/mloop.xml b/doc/ref/mloop.xml index ca1a723482..b39f2f50e8 100644 --- a/doc/ref/mloop.xml +++ b/doc/ref/mloop.xml @@ -739,12 +739,21 @@ is an example in the &GAP; code where the idea is actually used. Backtrace Stack trace shows the last nr commands on the execution stack during whose execution -the error occurred. If not given, nr defaults to 5. (Assume, for the +the error occurred. If not given, nr defaults to the value of the +WhereDepth user preference (initially 5). +If nr or the WhereDepth preference is not a non-negative integer, +it is treated as 5. +(Assume, for the following example, that after the last example has been set back to its default value.). acts the same as while also showing the arguments and local variables of each function.

+ acts the same as while also +showing the arguments and local variables of each function. +

+The following example assumes that is set to its default +value. StabChain(SymmetricGroup(1000)); # After this we typed ^C Error, user interrupt diff --git a/lib/error.g b/lib/error.g index fe1040a6ac..f43ab34778 100644 --- a/lib/error.g +++ b/lib/error.g @@ -180,6 +180,9 @@ end); BIND_GLOBAL("WHERE_INTERNAL", function(depth, showlocals) local activecontext; + if not IsInt(depth) or depth < 0 then + depth := 5; + fi; if ErrorLVars = fail or ErrorLVars = GetBottomLVars() then PrintTo(ERROR_OUTPUT, "not in any function "); else @@ -192,7 +195,7 @@ end); BIND_GLOBAL("WhereWithVars", function(arg) local depth; if LEN_LIST(arg) = 0 then - depth := 5; + depth := UserPreference("WhereDepth"); else depth := arg[1]; fi; @@ -203,7 +206,7 @@ end); BIND_GLOBAL("Where", function(arg) local depth; if LEN_LIST(arg) = 0 then - depth := 5; + depth := UserPreference("WhereDepth"); else depth := arg[1]; fi; diff --git a/lib/init.g b/lib/init.g index 810305951f..03601c810a 100644 --- a/lib/init.g +++ b/lib/init.g @@ -582,6 +582,16 @@ DeclareUserPreference( rec( default:= 3, check:= val -> IsInt( val ) and 0 <= val, ) ); +DeclareUserPreference( rec( + name:= "WhereDepth", + description:= [ + "The number of stack frames shown by Where and WhereWithVars \ +when called without an explicit depth argument, e.g. in the default OnBreak \ +handler." + ], + default:= 5, + check:= val -> IsInt( val ) and 0 <= val, + ) ); DeclareUserPreference( rec( name:= "ReproducibleBehaviour", description:= [ diff --git a/tst/testspecial/run_gap.sh b/tst/testspecial/run_gap.sh index 9ba7c29a65..aa7f088494 100755 --- a/tst/testspecial/run_gap.sh +++ b/tst/testspecial/run_gap.sh @@ -18,6 +18,7 @@ GAPROOT=$("$gap" --print-gaproot) ( echo "LogTo(\"${outfile}.tmp\");" ; cat "$gfile" ; echo "QUIT;" ) | "$gap" -r -A -b -m 256m -o 512m -x 800 \ -c 'SetUserPreference("UseColorsInTerminal",false);' \ + -c 'SetUserPreference("WhereDepth", 5);' \ 2>/dev/null >/dev/null sed -E -e "s:${GAPROOT//:/\\:}:GAPROOT/:g" -e "s;(GAPROOT(/[^/]+)+):[0-9]+;\1:LINE;g" < "${outfile}.tmp" > "${outfile}" rm "${outfile}.tmp" diff --git a/tst/testspecial/stack-trace-depth.g b/tst/testspecial/stack-trace-depth.g index dde6f2571b..28e525dbf2 100644 --- a/tst/testspecial/stack-trace-depth.g +++ b/tst/testspecial/stack-trace-depth.g @@ -32,5 +32,8 @@ f1 := function() return f2(); end;; f1(); -Where(12); +SetUserPreference("WhereDepth", 12); +Where(); +SetUserPreference("WhereDepth", 5); +Where(); quit; diff --git a/tst/testspecial/stack-trace-depth.g.out b/tst/testspecial/stack-trace-depth.g.out index 0005d8c5c7..7a30baca80 100644 --- a/tst/testspecial/stack-trace-depth.g.out +++ b/tst/testspecial/stack-trace-depth.g.out @@ -47,7 +47,8 @@ Stack trace: ... at *stdin*:35 you can 'quit;' to quit to outer loop, or you can 'return;' to continue -brk> Where(12); +brk> SetUserPreference("WhereDepth", 12); +brk> Where(); * [1] Error( "foo" ); @ *stdin*:3 [2] f11( ) @@ -71,6 +72,19 @@ brk> Where(12); [11] f2( ) @ *stdin*:33 ( ) - called from read-eval loop at *errin*:1 + called from read-eval loop at *errin*:2 +brk> SetUserPreference("WhereDepth", 5); +brk> Where(); +*[1] Error( "foo" ); + @ *stdin*:3 + [2] f11( ) + @ *stdin*:6 + [3] f10( ) + @ *stdin*:9 + [4] f9( ) + @ *stdin*:12 + [5] f8( ) + @ *stdin*:15 +... at *errin*:4 brk> quit; gap> QUIT; From 7e2e2da418513f75628bb2c40fffc21da78f9f9d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 4 May 2026 22:02:55 +0100 Subject: [PATCH 30/52] doc: streamline Matrix argument variants (#6361) --- doc/ref/matobj.xml | 2 +- lib/matobj2.gd | 34 +++++++++------------------------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/doc/ref/matobj.xml b/doc/ref/matobj.xml index e8f5bbcedc..27fdfc1310 100644 --- a/doc/ref/matobj.xml +++ b/doc/ref/matobj.xml @@ -486,7 +486,7 @@ and then set the entries in this matrix. Functions like , , -and +and admit different kinds of inputs. ZeroMatrix( R, m, n ) can be used, for example, if we want to leave the decision about the representation of the result diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 006e976705..1405092d67 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -1394,36 +1394,20 @@ DeclareOperation( "CompanionMatrix", ## <#GAPDoc Label="MatObj_Matrix"> ## ## Matrix -## -## -## -## -## -## -## -## -## -## -## +## +## +## +## +## ## ## a matrix object ## ## If a semiring R is given as the first argument then ## a matrix object is returned whose ## -## value is guessed from R, with base domain R -## and entries given by the argument list. +## 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. @@ -1456,7 +1440,7 @@ DeclareOperation( "CompanionMatrix", ## 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, M, M1) is mutable. +## 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 , From db03c9979ea957b6018be6b65dc7e72227a48e24 Mon Sep 17 00:00:00 2001 From: Kamil Zabielski <50334623+limakzi@users.noreply.github.com> Date: Tue, 5 May 2026 16:16:11 +0100 Subject: [PATCH 31/52] Document DirectProductElement (#6260) --- doc/ref/mapping.xml | 1 + lib/tuples.gd | 53 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/doc/ref/mapping.xml b/doc/ref/mapping.xml index 5a69256cc6..e23f858f8c 100644 --- a/doc/ref/mapping.xml +++ b/doc/ref/mapping.xml @@ -40,6 +40,7 @@ section . Direct Products and their Elements <#Include Label="IsDirectProductElement"> +<#Include Label="DirectProductElement"> <#Include Label="DirectProductFamily">

diff --git a/lib/tuples.gd b/lib/tuples.gd index bf644d6751..743a031bcc 100644 --- a/lib/tuples.gd +++ b/lib/tuples.gd @@ -147,13 +147,66 @@ BindGlobal( "EmptyDirectProductElementsFamily", #O DirectProductElementNC( , ) . . . . omits check on object #O families and objlist length ## +## <#GAPDoc Label="DirectProductElement"> ## ## ## ## ## +## returns a direct product element +## whose components are the entries of the list objlist. +## If the optional argument fam is given, it must be the family of +## direct product elements with the appropriate component families; +## otherwise the family is determined from objlist. +##

+## does the same but omits the checks +## that fam is consistent with objlist. +##

+## Direct product elements behave like lists: they can be indexed with +## elm[i] to access the i-th component, and +## returns the number of components. +## Arithmetic operations (multiplication, powering, one, inverse, +## addition, zero, additive inverse) are performed componentwise. +## a := (1,2,3);; b := (1,2);; +## gap> elm := DirectProductElement([a, b]); +## DirectProductElement( [ (1,2,3), (1,2) ] ) +## gap> elm[1]; +## (1,2,3) +## gap> elm[2]; +## (1,2) +## gap> Length(elm); +## 2 +## gap> elm2 := DirectProductElement([b, a]);; +## gap> elm * elm2; +## DirectProductElement( [ (2,3), (1,3) ] ) +## gap> One(elm); +## DirectProductElement( [ (), () ] ) +## gap> Inverse(elm); +## DirectProductElement( [ (1,3,2), (1,2) ] ) +## ]]> +##

+## The following example shows in the +## context of a direct product K = G \times H built with +## , where G is a permutation group and +## H is a pc group. The projections of K are +## used to move between the direct product and its component groups. +## G := DihedralGroup(IsPermGroup, 8);; +## gap> H := CyclicGroup(IsPcGroup, 4);; +## gap> K := DirectProduct(G, H);; +## gap> proj1 := Projection(K, 1);; proj2 := Projection(K, 2);; +## gap> g := (1,2,3,4);; h := GeneratorsOfGroup(H)[1];; +## gap> elm := DirectProductElement([g, h]); +## DirectProductElement( [ (1,2,3,4), f1 ] ) +## gap> Image(proj1, elm) = g; +## true +## gap> Image(proj2, elm) = h; +## true +## ]]> ## ## +## <#/GAPDoc> ## DeclareOperation( "DirectProductElement", [ IsList ]); DeclareOperation( "DirectProductElementNC", From c818f506da7f39c06ae914c4ef0bf6c96bddfce7 Mon Sep 17 00:00:00 2001 From: Thomas Breuer Date: Wed, 6 May 2026 01:47:49 +0200 Subject: [PATCH 32/52] Reset the options stack after an error also when the break loop is disabled (`-T` command line option) (#6355) --- lib/error.g | 12 ++++++++---- lib/package.gi | 5 +++-- tst/testinstall/error.tst | 10 ++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/error.g b/lib/error.g index f43ab34778..de03ee813f 100644 --- a/lib/error.g +++ b/lib/error.g @@ -32,13 +32,14 @@ ERROR_OUTPUT := MakeImmutable("*errout*"); Unbind(OnQuit); BIND_GLOBAL( "OnQuit", function() if not IsEmpty(OptionsStack) then + if IsBound(ResetMethodReordering) and IsFunction(ResetMethodReordering) + and ValueOption( "ReadingPackageFiles" ) = true then + ResetMethodReordering(); + fi; repeat PopOptions(); until IsEmpty(OptionsStack); - Info(InfoWarning,1,"Options stack has been reset"); - fi; - if IsBound(ResetMethodReordering) and IsFunction(ResetMethodReordering) then - ResetMethodReordering(); + Info(InfoWarning,2,"Options stack has been reset"); fi; if REREADING = true then MakeReadWriteGlobal("REREADING"); @@ -373,6 +374,9 @@ BIND_GLOBAL("ErrorInner", function(options, earlyMessage) ErrorLVars := errorLVars; ErrorTracebackLVars := errorTracebackLVars; SET_ERROR_LVARS(kernelErrorLVars); + if IsBound(OnQuit) and IsFunction(OnQuit) then + OnQuit(); + fi; if ErrorLevel = 0 then LEAVE_ALL_NAMESPACES(); fi; JUMP_TO_CATCH(0); fi; diff --git a/lib/package.gi b/lib/package.gi index fbd23eda01..1930c9d6fd 100644 --- a/lib/package.gi +++ b/lib/package.gi @@ -1750,7 +1750,7 @@ InstallGlobalFunction( LoadPackage, function( arg ) "start reading file 'init.g'", info.PackageName ); GAPInfo.PackageCurrent:= info; - ReadPackage( pkgname, "init.g" ); + ReadPackage( pkgname, "init.g" : ReadingPackageFiles:= true ); Unbind( GAPInfo.PackageCurrent ); LogPackageLoadingMessage( PACKAGE_DEBUG, "finish reading file 'init.g'", @@ -1766,7 +1766,8 @@ InstallGlobalFunction( LoadPackage, function( arg ) # (We have delayed this until now because it uses functionality # from the package GAPDoc.) # Note that no banners are printed during autoloading. - LoadPackage_ReadImplementationParts( secondrun, banner ); + LoadPackage_ReadImplementationParts( secondrun, banner + : ReadingPackageFiles:= true ); secondrun:= []; od; diff --git a/tst/testinstall/error.tst b/tst/testinstall/error.tst index 9cb0d353f7..cf590212f9 100644 --- a/tst/testinstall/error.tst +++ b/tst/testinstall/error.tst @@ -34,3 +34,13 @@ gap> if false then Stabilizer; fi; Syntax error: found an expression when a statement was expected in stream:1 if false then Stabilizer; fi; ^ + +# +gap> oldBreakOnError:= BreakOnError;; +gap> BreakOnError:= false;; +gap> PushOptions( rec( test:= true ) ); +gap> Error( "!" ); +Error, ! +gap> Length( OptionsStack ) = 0; +true +gap> BreakOnError:= oldBreakOnError;; From 7a617cc1464061e59308889fcd1d1ab81dbba2bd Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 6 May 2026 01:25:32 +0100 Subject: [PATCH 33/52] Guard some `IdGroup` calls by `ID_AVAILABLE` (#6353) ... instead of hardcoding assumptions about the availability of IdGroup. --- lib/grplatt.gi | 13 ++++++------- lib/grpnames.gi | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/grplatt.gi b/lib/grplatt.gi index 610b9826e5..5563219bf7 100644 --- a/lib/grplatt.gi +++ b/lib/grplatt.gi @@ -2759,15 +2759,14 @@ local fgi,inducedfactorautos,projs,psubs,info,n,l,nl,emb,u,pos, fi; fgi:=function(gp,nor) - local idx,hom,l,f; - idx:=Index(gp,nor); + local hom,l,f; hom:=NaturalHomomorphismByNormalSubgroup(gp,nor); - if idx>1000 or idx=512 or not uselib then - l:=[idx,fail]; + f:=Image(hom); + if uselib and Size(f) < 1000 and ID_AVAILABLE(Size(f)) <> fail then + l:=ShallowCopy(IdGroup(f)); else - l:=ShallowCopy(IdGroup(gp/nor)); + l:=[Size(f),fail]; fi; - f:=Image(hom,gp); Add(l,hom); Add(l,f); Add(l,AutomorphismGroup(f)); @@ -2835,7 +2834,7 @@ local fgi,inducedfactorautos,projs,psubs,info,n,l,nl,emb,u,pos, for k in no do hom:=NaturalHomomorphismByNormalSubgroup(j[1],k.representative); f:=Image(hom); - if Size(f)<1000 and Size(f)<>512 and uselib then + if uselib and Size(f) < 1000 and ID_AVAILABLE(Size(f)) <> fail then myid:=ShallowCopy(IdGroup(f)); else myid:=[Size(f),fail]; diff --git a/lib/grpnames.gi b/lib/grpnames.gi index af9fdb5b01..32aa8f6368 100644 --- a/lib/grpnames.gi +++ b/lib/grpnames.gi @@ -1861,7 +1861,7 @@ BindGlobal( "StructureDescriptionForFiniteGroups", # for finite groups # fetch name from precomputed list, if available if ValueOption("recompute") <> true and Size(G) <= 2000 then - if IsBound(NAMES_OF_SMALL_GROUPS[Size(G)]) then + if IsBound(NAMES_OF_SMALL_GROUPS[Size(G)]) and ID_AVAILABLE(Size(G)) <> fail then i := IdGroup(G)[2]; if IsBound(NAMES_OF_SMALL_GROUPS[Size(G)][i]) then name := ShallowCopy(NAMES_OF_SMALL_GROUPS[Size(G)][i]); From 9fcabc2f922c730e0e251782c221cc619aaebf65 Mon Sep 17 00:00:00 2001 From: Thomas Breuer Date: Wed, 6 May 2026 02:43:15 +0200 Subject: [PATCH 34/52] Add `RandomMatrix`, `RandomInvertibleMatrix`; and fix a problem with a new feature for matrix groups (#6232) - add a description of the cache `FULLGLNICOCACHE` in the code; it is used only by `NicomorphismFFMatGroupOnFullSpace` - change the keys of `FULLGLNICOCACHE`: take the field of the matrix entries into account (not only its size), take the `ConstructingFilter` of the matrices into account - in `NicomorphismFFMatGroupOnFullSpace`, deal with special cases of matrices in `IsBlockMatrixRep` (which have no `ConstructingFilter`) and in `Is8BitMatrixRep` in the situation that the group itself lives over `GF(2)` - in order to admit the action of `IsMatrixObj` matrices on vectors supported by GAP's `Enumerator`s of vector spaces, add a `\^` method that `Unpack`s the matrix object (Eventually we want to avoid this overhead, but then we need `Enumerator`s consisting of vector objects corresponding to the matrix objects.) - add `Matrix` calls in the function that computes preimages under an action homomorphism with `Source` a matrix group, in order to support matrix group elements of prescribed kinds of `IsMatrixObj`. - add tests for the new supported situations (most of the changes were actually forced by already available tests) * add `\in` methods for matrix object and (`GL` or `SL`) * avoid some `Unpack` hacks - introduce `NormedRowVectors_internal( F, base )`, and `AsListOfFreeLeftModule_internal( F, base, zero )`, in order to admit `IsVectorObj`s in `base` without supporting the whole vector space machinery for these objects - introduce `ExternalSet( G )` for matrix groups `G`, meaning the natural `G`-set (an undocumented method for permutation groups `G` was already available) - change `NicomorphismFFMatGroupOnFullSpace` such that we can act with the `IsMatrixObj` matrices on their `IsVectorObj` vectors, without unpacking the matrices - support `IsMatrixObj` matrices in the `Random` methods for GL and SL * adjust also `IsProjectiveActionHomomorphism` methods * add `RandomMatrix`, `RandomInvertibleMatrix` and fix the `RankMat` method for `IsPlistMatrixRep` --- doc/ref/matrix.xml | 2 + grp/classic.gd | 2 +- lib/grpffmat.gi | 158 +++++++++++++--- lib/matobjplist.gi | 8 +- lib/matrix.gd | 174 +++++++++++++++++- lib/matrix.gi | 111 +++++++++++ lib/methsel.g | 24 +++ lib/modfree.gi | 24 ++- lib/oprt.gi | 96 +++++++--- lib/vspcrow.gi | 60 +++--- tst/testbugfix/2007-07-02-t00180.tst | 2 +- .../MatrixObj/DeterminantMatrix.tst | 29 +++ .../MatrixObj/RandomInvertibleMatrix.tst | 52 ++++++ tst/testinstall/MatrixObj/RandomMatrix.tst | 72 ++++++++ tst/testinstall/MatrixObj/RankMatrix.tst | 23 +++ tst/testinstall/MatrixObj/acthom.tst | 80 ++++++++ tst/testinstall/grpmat.tst | 18 +- 17 files changed, 823 insertions(+), 112 deletions(-) create mode 100644 tst/testinstall/MatrixObj/DeterminantMatrix.tst create mode 100644 tst/testinstall/MatrixObj/RandomInvertibleMatrix.tst create mode 100644 tst/testinstall/MatrixObj/RandomMatrix.tst create mode 100644 tst/testinstall/MatrixObj/RankMatrix.tst create mode 100644 tst/testinstall/MatrixObj/acthom.tst diff --git a/doc/ref/matrix.xml b/doc/ref/matrix.xml index 59f006dbfd..e80f6b2419 100644 --- a/doc/ref/matrix.xml +++ b/doc/ref/matrix.xml @@ -341,7 +341,9 @@ see . Random Matrices <#Include Label="RandomMat"> +<#Include Label="RandomMatrix"> <#Include Label="RandomInvertibleMat"> +<#Include Label="RandomInvertibleMatrix"> <#Include Label="RandomUnimodularMat">

diff --git a/grp/classic.gd b/grp/classic.gd index 0bfd9b3b4b..ae891da7be 100644 --- a/grp/classic.gd +++ b/grp/classic.gd @@ -836,7 +836,7 @@ BindGlobal( "SymplecticGroup", function ( arg ) rep:= filt; filt:= IsMatrixGroup; else - rep:= fail; + rep:= ValueOption( "ConstructingFilter" ); fi; if DescribesInvariantBilinearForm( Last( arg ) ) then form:= Remove( arg ); diff --git a/lib/grpffmat.gi b/lib/grpffmat.gi index 147563c60b..2f63b1c1d3 100644 --- a/lib/grpffmat.gi +++ b/lib/grpffmat.gi @@ -124,31 +124,80 @@ end ); ############################################################################# ## -#M NiceMonomorphism( ) +## the natural G-set of a matrix group consists of the vectors of the +## natural module +## +InstallOtherMethod( ExternalSet, + [ IsFFEMatrixGroup and IsFinite ], + function( G ) + local basis, zero; + + basis:= RowsOfMatrix( One( G ) ); + zero:= Zero( basis[1] ); + return ExternalSet( G, AsListOfFreeLeftModule_internal( + FieldOfMatrixGroup( G ), basis, zero ) ); +end ); + +############################################################################# +## +#V FULLGLNICOCACHE +## +## 'NicomorphismFFMatGroupOnFullSpace' uses a cache of length up to 5, +## as follows. +## +## - If the argument is a matrix group that fits to an entry of this +## cache, in the sense that dimension, field of definition, +## and 'ConstructingFilter' of the matrices in the group are the same as +## for the cached value, the stored mapping is returned. +## - If a new mapping has to be constructed, the first cached entry is +## dropped and the new mapping gets added to the cache. ## MakeThreadLocal("FULLGLNICOCACHE"); # avoid recreating same homom. repeatedly -FULLGLNICOCACHE:=[]; -InstallGlobalFunction( NicomorphismFFMatGroupOnFullSpace, function( grp ) - local field, dim, V, xset, nice; +BindGlobal( "FULLGLNICOCACHE", [] ); - field := FieldOfMatrixGroup( grp ); - dim := DimensionOfMatrixGroup( grp ); + +############################################################################# +## +#M NiceMonomorphism( ) +## +InstallGlobalFunction( NicomorphismFFMatGroupOnFullSpace, function( grp ) + local rep, filt, q, dim, field, xset, nice; + + rep:= Representative( grp ); + field:= FieldOfMatrixGroup( grp ); + q:= Size( field ); + if IsBlockMatrixRep( rep ) then + # There is no support for these matrices acting on vectors. + filt:= IsPlistRep; + elif q = 2 and Is8BitMatrixRep( rep ) then + # We cannot keep both 'field' and 'Is8BitMatrixRep', + # the latter does not admit matrices over GF(2). + filt:= IsGF2MatrixRep; +#TODO: How can we get rid of these hacks? + else + filt:= ConstructingFilter( rep ); + fi; + dim:= DimensionOfMatrixGroup( grp ); #check cache - V:=Size(field); - nice:=First(FULLGLNICOCACHE,x->x[1]=V and x[2]=dim); - if nice<>fail then return nice[3];fi; + nice:= First( FULLGLNICOCACHE, + x -> x[1] = field and x[2] = dim and x[3] = filt ); + + if nice<>fail then return nice[4];fi; if not (HasIsNaturalGL(grp) and IsNaturalGL(grp)) then - grp:=GL(dim,field); # enforce map on full GL + # enforce map on full GL + grp:= GL( dim, field : ConstructingFilter:= filt ); fi; - V := field ^ dim; - xset := ExternalSet( grp, V ); - + xset := ExternalSet( grp ); # STILL: reverse the base to get point sorting compatible with lexicographic # vector arrangement - SetBaseOfGroup( xset, One( grp )); + if IsList( One( grp ) ) then + SetBaseOfGroup( xset, One( grp )); + else + SetBaseOfGroup( xset, RowsOfMatrix( One( grp ) ) ); + fi; nice := ActionHomomorphism( xset,"surjective" ); SetIsInjective( nice, true ); if not HasNiceMonomorphism(grp) then @@ -156,14 +205,14 @@ InstallGlobalFunction( NicomorphismFFMatGroupOnFullSpace, function( grp ) fi; # because we act on the full space we are canonical. SetIsCanonicalNiceMonomorphism(nice,true); - if Size(V)>10^5 then + if q^dim > 10^5 then # store only one big one and have it get thrown out quickly - FULLGLNICOCACHE[1]:=[Size(field),dim,nice]; + FULLGLNICOCACHE[1]:= [ field, dim, filt, nice ]; else if Length(FULLGLNICOCACHE)>4 then - FULLGLNICOCACHE:=FULLGLNICOCACHE{[2..5]}; + Remove( FULLGLNICOCACHE, 1 ); fi; - Add(FULLGLNICOCACHE,[Size(field),dim,nice]); + Add( FULLGLNICOCACHE, [ field, dim, filt, nice ] ); fi; return nice; @@ -190,8 +239,7 @@ local tt; # if the permutation image would be too large, compute the orbit. TryNextMethod(); fi; - return NicomorphismFFMatGroupOnFullSpace( GL( DimensionOfMatrixGroup( grp ), - Size( FieldOfMatrixGroup( Parent(grp) ) ) ) ); + return NicomorphismFFMatGroupOnFullSpace( grp ); end ); ############################################################################# @@ -256,6 +304,25 @@ InstallMethod( \in, "general linear group", IsElmsColls, and Length( mat ) = RankMat( mat ); end ); +InstallMethod( \in, "general linear group", IsElmsColls, + [ IsMatrixObj, IsFFEMatrixGroup and IsFinite and IsNaturalGL ], 0, + function( mat, G ) + local n, F; + n:= NumberRows( mat ); + F:= FieldOfMatrixGroup( G ); + return n = NumberColumns( mat ) + and n = DimensionOfMatrixGroup( G ) + and n = RankMat( mat ) +#TODO: +# Currently we cannot force the rule that all matrices in a matrix +# group consisting of matrix objects have the same 'BaseDomain', +# and that this common 'BaseDomain' is equal to the 'FieldOfMatrixGroup' +# of the group. +# Eventually we want 'true' only if 'F = BaseDomain( mat )' holds. + and ( IsSubset( F, BaseDomain( mat ) ) or + ForAll( Unpack( mat ), row -> IsSubset( F, row ) ) ); +end ); + InstallMethod( \in, "special linear group", IsElmsColls, [ IsMatrix, IsFFEMatrixGroup and IsFinite and IsNaturalSL ], 0, function( mat, G ) @@ -266,6 +333,19 @@ InstallMethod( \in, "special linear group", IsElmsColls, and DeterminantMat(mat)=One(FieldOfMatrixGroup( G )); end ); +InstallMethod( \in, "special linear group", IsElmsColls, + [ IsMatrixObj, IsFFEMatrixGroup and IsFinite and IsNaturalSL ], 0, + function( mat, G ) + local n, F; + n:= NumberRows( mat ); + F:= FieldOfMatrixGroup( G ); + return n = NumberColumns( mat ) + and n = DimensionOfMatrixGroup( G ) + and ( IsSubset( F, BaseDomain( mat ) ) or + ForAll( Unpack( mat ), row -> IsSubset( F, row ) ) ) + and DeterminantMat( mat ) = One( F ); +end ); + ############################################################################# ## @@ -508,10 +588,23 @@ InstallMethodWithRandomSource( Random, "for a random source and natural GL", [ IsRandomSource, IsFFEMatrixGroup and IsFinite and IsNaturalGL ], function(rs, G) - local m; - m := RandomInvertibleMat( rs, DimensionOfMatrixGroup( G ), - FieldOfMatrixGroup( G ) ); - return ImmutableMatrix(FieldOfMatrixGroup(G), m, true); + local d, F, m; + + d:= DimensionOfMatrixGroup( G ); + F:= FieldOfMatrixGroup( G ); + m:= Representative( G ); + if IsMatrix( m ) then + m:= RandomInvertibleMat( rs, d, F ); + m:= ImmutableMatrix(F, m, true); + else + m:= ZeroMatrix( d, d, m ); + repeat + Randomize( rs, m ); + until RankMat( m ) = d; + MakeImmutable( m ); + fi; + + return m; end); @@ -527,11 +620,18 @@ InstallMethodWithRandomSource( Random, "for a random source and natural SL", [ IsRandomSource, IsFFEMatrixGroup and IsFinite and IsNaturalSL ], function(rs, G) - local m; - m:= RandomInvertibleMat( rs, DimensionOfMatrixGroup( G ), - FieldOfMatrixGroup( G ) ); - MultVector(m[1], DeterminantMat(m)^-1); - return ImmutableMatrix(FieldOfMatrixGroup(G), m, true); + local d, m; + + # We assume that all elements in the group have the same + # 'BaseDomain' value, hence we may take any 'Representative'. + # see the section "Groups Consisting of Matrix Objects" + # in the Reference Manual. + d:= DimensionOfMatrixGroup( G ); + m:= RandomInvertibleMatrix( rs, d, Representative( G ) ); + MultMatrixRow( m, 1, DeterminantMatrix( m )^-1 ); + MakeImmutable( m ); + + return m; end); ############################################################################# diff --git a/lib/matobjplist.gi b/lib/matobjplist.gi index c3277ff899..c9af75c590 100644 --- a/lib/matobjplist.gi +++ b/lib/matobjplist.gi @@ -1229,7 +1229,13 @@ InstallMethod( InverseSameMutability, InstallMethod( RankMat, [ "IsPlistMatrixRep" ], - M -> RankMat( List( M![ROWSPOS], x -> x![ELSPOS] ) ) ); + function( M ) + M:= M![ROWSPOS]; + if Length( M ) = 0 then + return 0; + fi; + return RankMat( List( M, x -> x![ELSPOS] ) ); + end ); InstallMethodWithRandomSource( Randomize, "for a random source and a mutable plist matrix", diff --git a/lib/matrix.gd b/lib/matrix.gd index 8056c80165..4fe2262981 100644 --- a/lib/matrix.gd +++ b/lib/matrix.gd @@ -1887,6 +1887,82 @@ DeclareGlobalFunction( "DiagonalMat" ); DeclareGlobalFunction( "ReflectionMat" ); +############################################################################# +## +#O RandomInvertibleMatrix( [, ][, ], ) +#O RandomInvertibleMatrix( [, ], ) +## +## <#GAPDoc Label="RandomInvertibleMatrix"> +## +## +## +## +## +## a matrix or matrix object I with m columns, +## with base domain R or equal to BaseDomain( M ), +## such that I is invertible over its base domain. +## +## +## If a semiring R is given then it will be the base domain +## (see ) +## of the returned matrix. +## In this case, a filter filt can be specified that defines the +## internal representation of the result +## (see ). +## The default value for filt is determined from R. +##

+## If a matrix object M is given then the returned matrix will have +## the same internal representation and the same base domain as M. +##

+## If a random source rs is given (see ) +## then the entries of the result are computed using rs, +## the default random source is . +##

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

+## m:= RandomInvertibleMatrix( GF(9), 2 );; +## gap> RankMatrix( m ); +## 2 +## gap> DimensionsMat( m ); +## [ 2, 2 ] +## gap> BaseDomain( m ); +## GF(3^2) +## gap> Is8BitMatrixRep( m ); +## true +## gap> m1:= RandomInvertibleMatrix( IsPlistMatrixRep, GF(9), 2 );; +## gap> IsPlistMatrixRep( m1 ); +## true +## gap> m2:= RandomInvertibleMatrix( 2, m1 );; +## gap> IsPlistMatrixRep( m2 ); +## true +## gap> m:= RandomInvertibleMatrix( Integers, 2 );; +## gap> IsUnit( Integers, DeterminantMatrix( m ) ); +## true +## ]]> +## +## +## <#/GAPDoc> +## +DeclareTagBasedOperation( "RandomInvertibleMatrix", + [ IsOperation, IsRandomSource, IsSemiring, IsInt ] ); +DeclareOperation( "RandomInvertibleMatrix", + [ IsRandomSource, IsSemiring, IsInt ] ); +DeclareOperation( "RandomInvertibleMatrix", + [ IsOperation, IsSemiring, IsInt ] ); +DeclareOperation( "RandomInvertibleMatrix", + [ IsSemiring, IsInt ] ); + +DeclareOperation( "RandomInvertibleMatrix", + [ IsRandomSource, IsInt, IsMatrixOrMatrixObj ] ); +DeclareOperation( "RandomInvertibleMatrix", + [ IsInt, IsMatrixOrMatrixObj ] ); + + ############################################################################# ## #F RandomInvertibleMat( [rs ,] [, ] ) . . . random invertible matrix @@ -1900,13 +1976,19 @@ DeclareGlobalFunction( "ReflectionMat" ); ## matrix with m rows and columns with elements taken from the ring ## R, which defaults to . ## Optionally, a random source rs can be supplied. +##

+## Note that the result need not be invertible over +## the prescribed ring R. +## Use +## for creating random matrices with this stronger property. +##

## m := RandomInvertibleMat(4); -## [ [ -4, 1, 0, -1 ], [ -1, -1, 1, -1 ], [ 1, -2, -1, -2 ], -## [ 0, -1, 2, -2 ] ] +## gap> m := RandomInvertibleMat( 4, Integers ); +## [ [ 1, -4, 0, 1 ], [ 0, -2, 3, 1 ], [ 0, -2, -1, -1 ], +## [ 0, -2, 2, 4 ] ] ## gap> m^-1; -## [ [ -1/8, -11/24, 1/24, 1/4 ], [ 1/4, -13/12, -1/12, 1/2 ], -## [ -1/8, 5/24, -7/24, 1/4 ], [ -1/4, 3/4, -1/4, -1/2 ] ] +## [ [ 1, -1/14, -19/14, -4/7 ], [ 0, -1/14, -5/14, -1/14 ], +## [ 0, 5/14, -3/14, -1/7 ], [ 0, -3/14, -1/14, 2/7 ] ] ## ]]> ## ## @@ -1939,6 +2021,78 @@ DeclareGlobalFunction( "RandomInvertibleMat" ); DeclareGlobalFunction( "RandomMat" ); +############################################################################# +## +#O RandomMatrix( [, ][, ], , ) +#O RandomMatrix( [, ], , ) +## +## <#GAPDoc Label="RandomMatrix"> +## +## +## +## +## +## a matrix or matrix object with m rows and n columns, +## with base domain R or equal to BaseDomain( M ). +## +## +## If a semiring R is given then it will be the base domain +## (see ) +## of the returned matrix. +## In this case, a filter filt can be specified that defines the +## internal representation of the result +## (see ). +## The default value for filt is determined from R. +##

+## If a matrix object M is given then the returned matrix will have +## the same internal representation and the same base domain as M. +##

+## If a random source rs is given (see ) +## then the entries of the result are computed using rs, +## the default random source is . +##

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

+## m:= RandomMatrix( GF(9), 2, 3 );; +## gap> DimensionsMat( m ); +## [ 2, 3 ] +## gap> BaseDomain( m ); +## GF(3^2) +## gap> Is8BitMatrixRep( m ); +## true +## gap> m1:= RandomMatrix( IsPlistMatrixRep, GF(9), 2, 3 );; +## gap> IsPlistMatrixRep( m1 ); +## true +## gap> m2:= RandomMatrix( 3, 4, m1 );; +## gap> DimensionsMat( m2 ); +## [ 3, 4 ] +## gap> IsPlistMatrixRep( m2 ); +## true +## ]]> +## +## +## <#/GAPDoc> +## +DeclareTagBasedOperation( "RandomMatrix", + [ IsOperation, IsRandomSource, IsSemiring, IsInt, IsInt ] ); +DeclareOperation( "RandomMatrix", + [ IsRandomSource, IsSemiring, IsInt, IsInt ] ); +DeclareOperation( "RandomMatrix", + [ IsOperation, IsSemiring, IsInt, IsInt ] ); +DeclareOperation( "RandomMatrix", + [ IsSemiring, IsInt, IsInt ] ); + +DeclareOperation( "RandomMatrix", + [ IsRandomSource, IsInt, IsInt, IsMatrixOrMatrixObj ] ); +DeclareOperation( "RandomMatrix", + [ IsInt, IsInt, IsMatrixOrMatrixObj ] ); + + ############################################################################# ## #F RandomUnimodularMat( [rs ,] ) . . . . . . . . random unimodular matrix @@ -1955,13 +2109,13 @@ DeclareGlobalFunction( "RandomMat" ); ## from Integers ## m := RandomUnimodularMat(3); -## [ [ -5, 1, 0 ], [ 12, -2, -1 ], [ -14, 3, 0 ] ] +## [ [ 1, -5, 26 ], [ 0, 1, -6 ], [ 0, 0, 1 ] ] ## gap> m^-1; -## [ [ -3, 0, 1 ], [ -14, 0, 5 ], [ -8, -1, 2 ] ] +## [ [ 1, 5, 4 ], [ 0, 1, 6 ], [ 0, 0, 1 ] ] ## gap> RandomUnimodularMat(3:domain:=[-1000..1000]); -## [ [ 312330173, 15560030349, -125721926670 ], -## [ -307290, -15309014, 123693281 ], -## [ -684293792, -34090949551, 275448039848 ] ] +## [ [ 6001314, 239514853714734, -44705745791413 ], +## [ -1448123744, -57795200635226587, 10787546189680040 ], +## [ -671, -26780118200, 4998542420 ] ] ## ]]> ## ## diff --git a/lib/matrix.gi b/lib/matrix.gi index 956cd1b41b..b5780f80f4 100644 --- a/lib/matrix.gi +++ b/lib/matrix.gi @@ -3952,6 +3952,71 @@ InstallGlobalFunction( ReflectionMat, function( arg ) end ); +######################################################################### +## +#M RandomInvertibleMatrix( [, ][, ], ) +#M RandomInvertibleMatrix( [, ], ) +## +InstallTagBasedMethod( RandomInvertibleMatrix, + function( filt, rs, R, m ) + local mat, i, j; + + if IsIntegers( R ) then + # We have a dedicated method for this case. + mat:= RandomUnimodularMat( rs, m ); + if filt <> IsPlistRep then + mat:= Matrix( filt, R, mat ); + fi; + else + # The following works if 'R' is a field or a residue class ring. + # If other rings become important, + # we have to think about a better approach. + mat:= ZeroMatrix( filt, R, m, m ); + repeat + # 'Randomize' does not admit 'R' as an argument, + # and we want to cover also 'IsPlistRep'. + for i in [ 1 .. m ] do + for j in [ 1 .. m ] do + mat[i,j]:= Random( rs, R ); + od; + od; + until IsUnit( DeterminantMat( mat ) ); + fi; + + return mat; + end ); + +InstallMethod( RandomInvertibleMatrix, + [ IsRandomSource, IsSemiring, IsInt ], + function( rs, R, m ) + return RandomInvertibleMatrix( DefaultMatrixRepForBaseDomain( R ), rs, R, m ); + end ); + +InstallMethod( RandomInvertibleMatrix, + [ IsOperation, IsSemiring, IsInt ], + function( filt, R, m ) + return RandomInvertibleMatrix( filt, GlobalMersenneTwister, R, m ); + end ); + +InstallMethod( RandomInvertibleMatrix, + [ IsSemiring, IsInt ], + function( R, m ) + return RandomInvertibleMatrix( DefaultMatrixRepForBaseDomain( R ), GlobalMersenneTwister, R, m ); + end ); + +InstallMethod( RandomInvertibleMatrix, + [ IsRandomSource, IsInt, IsMatrixOrMatrixObj ], + function( rs, m, M ) + return RandomInvertibleMatrix( ConstructingFilter( M ), rs, BaseDomain( M ), m ); + end ); + +InstallMethod( RandomInvertibleMatrix, + [ IsInt, IsMatrixOrMatrixObj ], + function( m, M ) + return RandomInvertibleMatrix( ConstructingFilter( M ), GlobalMersenneTwister, BaseDomain( M ), m ); + end ); + + ######################################################################### ## #F RandomInvertibleMat( [rs ,] [, ] ) . . . make a random invertible matrix @@ -4001,6 +4066,52 @@ InstallGlobalFunction( RandomInvertibleMat, function ( arg ) end ); +######################################################################### +## +#M RandomMatrix( [, ][, ], , ) +#M RandomMatrix( [, ], , ) +## +InstallTagBasedMethod( RandomMatrix, + function( filt, rs, R, m, n ) + local mat; + + mat:= ZeroMatrix( filt, R, m, n ); + Randomize( rs, mat ); + + return mat; + end ); + +InstallMethod( RandomMatrix, + [ IsRandomSource, IsSemiring, IsInt, IsInt ], + function( rs, R, m, n ) + return RandomMatrix( DefaultMatrixRepForBaseDomain( R ), rs, R, m, n ); + end ); + +InstallMethod( RandomMatrix, + [ IsOperation, IsSemiring, IsInt, IsInt ], + function( filt, R, m, n ) + return RandomMatrix( filt, GlobalMersenneTwister, R, m, n ); + end ); + +InstallMethod( RandomMatrix, + [ IsSemiring, IsInt, IsInt ], + function( R, m, n ) + return RandomMatrix( DefaultMatrixRepForBaseDomain( R ), GlobalMersenneTwister, R, m, n ); + end ); + +InstallMethod( RandomMatrix, + [ IsRandomSource, IsInt, IsInt, IsMatrixOrMatrixObj ], + function( rs, m, n, M ) + return RandomMatrix( ConstructingFilter( M ), rs, BaseDomain( M ), m, n ); + end ); + +InstallMethod( RandomMatrix, + [ IsInt, IsInt, IsMatrixOrMatrixObj ], + function( m, n, M ) + return RandomMatrix( ConstructingFilter( M ), GlobalMersenneTwister, BaseDomain( M ), m, n ); + end ); + + ############################################################################# ## #F RandomMat( [rs ,] , [, ] ) . . . . . . . . make a random matrix diff --git a/lib/methsel.g b/lib/methsel.g index 54e1e02fd9..1f8634f7c9 100644 --- a/lib/methsel.g +++ b/lib/methsel.g @@ -253,6 +253,30 @@ BIND_GLOBAL( "NewTagBasedOperation", return method( req1, req2, req3, req4 ); end ); + elif LENGTH( requirements ) = 5 then + InstallEarlyMethod( oper, + function( req1, req2, req3, req4, req5 ) + local method; + + if not ( requirements[1]( req1 ) and + requirements[2]( req2 ) and + requirements[3]( req3 ) and + requirements[4]( req4 ) and + requirements[5]( req5 ) ) then + TryNextMethod(); + fi; + + method:= FIND_OBJ_MAP( methods, req1, fail ); + if method = fail then + # Take the default method if there is one. + method:= FIND_OBJ_MAP( methods, IS_OBJECT, fail ); + fi; + if method = fail then + Error( "no default installed for tag based operation " ); + fi; + + return method( req1, req2, req3, req4, req5 ); + end ); else Error( "tag based operations for ", LENGTH( requirements ), " arguments are currently not supported" ); diff --git a/lib/modfree.gi b/lib/modfree.gi index 86252154e8..85928ad44e 100644 --- a/lib/modfree.gi +++ b/lib/modfree.gi @@ -162,23 +162,25 @@ InstallMethod( Size, ## Either this basis has been entered when the space was constructed, or a ## basis is computed together with the elements list. ## -BindGlobal( "AsListOfFreeLeftModule", function( V ) + +## The vectors in 'base' are assumed to be linearly independent. +BindGlobal( "AsListOfFreeLeftModule_internal", function( F, base, zero ) local elms, # elements list, result - B, # $F$-basis of $V$ new, # intermediate elements list v, # one generator of $V$ i; # loop variable - if not IsFinite( V ) then - Error( "cannot compute elements list of infinite domain " ); + elms:= [ zero ]; + + if IsEmpty( base ) then + return elms; + elif not IsFinite( F ) then + Error( "cannot compute elements list over infinite domain " ); fi; - B := Basis( V ); - elms := [ Zero( V ) ]; -#T check whether we have the elements now ? - for v in BasisVectors( B ) do + for v in base do new:= []; - for i in AsList( LeftActingDomain( V ) ) do + for i in AsList( F ) do Append( new, List( elms, x -> x + i * v ) ); od; elms:= new; @@ -189,6 +191,10 @@ BindGlobal( "AsListOfFreeLeftModule", function( V ) return elms; end ); +BindGlobal( "AsListOfFreeLeftModule", + V -> AsListOfFreeLeftModule_internal( LeftActingDomain( V ), + BasisVectors( Basis( V ) ), Zero( V ) ) ); + InstallMethod( AsList, "for a free left module", [ IsFreeLeftModule ], diff --git a/lib/oprt.gi b/lib/oprt.gi index fe1acea79d..d9d6b34a81 100644 --- a/lib/oprt.gi +++ b/lib/oprt.gi @@ -655,7 +655,7 @@ local xset,surj,G, D, act, fam, filter, hom, i,blockacttest; elif IsExternalSetByActorsRep( xset ) then filter := filter and IsActionHomomorphismByActors; elif IsMatrixGroup( G ) - and IsScalarList( D[ 1 ] ) then + and ( IsScalarList( D[ 1 ] ) or IsVectorObj( D[ 1 ] ) ) then if act in [ OnPoints, OnRight ] then # we act linearly. This might be used to compute preimages by linear # algebra @@ -3380,7 +3380,7 @@ end ); InstallMethod( PreImagesRepresentative,"IsLinearActionHomomorphism", FamRangeEqFamElm, [ IsLinearActionHomomorphism, IsPerm ], 0, function( hom, elm ) - local V, xset,lab,f; + local V, G, Grep, xset,lab,f; # is this method applicable? Test whether the domain contains a vector # space basis (respectively just get this basis). @@ -3393,20 +3393,21 @@ function( hom, elm ) #if not elm in Image( hom ) then return fail; fi; xset:=UnderlyingExternalSet(hom); V := HomeEnumerator(xset); - f:=DefaultFieldOfMatrixGroup(Source(hom)); + G:= Source( hom ); + Grep:= Representative( G ); + f:=DefaultFieldOfMatrixGroup(G); if not IsBound(hom!.linActBasisPositions) then hom!.linActBasisPositions:=List(lab,i->PositionCanonical(V,i)); fi; if not IsBound(hom!.linActInverse) then - lab:=ImmutableMatrix(f,lab); + lab:=ImmutableMatrix(f, Matrix( lab, Grep )); hom!.linActInverse:=Inverse(lab); fi; elm:=OnTuples(hom!.linActBasisPositions,elm); # image points elm:=V{elm}; # the corresponding vectors - f:=DefaultFieldOfMatrixGroup(Source(hom)); - elm:=ImmutableMatrix(f,elm); + elm:=ImmutableMatrix(f, Matrix( elm, Grep )); return hom!.linActInverse*elm; end ); @@ -3415,10 +3416,29 @@ end ); ## #M PreImagesRepresentative( , ) . . . . . . . . . . build matrix ## +## The idea is as follows. +## We have an $F$-basis $(v_1, \ldots, v_n)$. +## The matrix $M \in GL(n, F)$ acts first by right multiplication, +## let $w_i = v_i M$. +## Due to the projective action, we know only the normed vectors $c_i w_i$, +## where $c_i \in F \setminus \{ 0 \}$. +## The data computed by 'LinearActionBasis' (if its result is not 'fail') +## provide a vector $v = \sum_i a_i v_i$ such that all $a_i \not= 0$, +## and we know the normed vector $c w$ where $w = v M$ and $c \in F$. +## +## We can compute the decomposition $c w = \sum_i b_i (c_i w_i)$, +## and get $\sum_i b_i (c_i w_i) = c v M = c \sum_i a_i w_i$, +## which means $c_i = c a_i/b_i$ for all $i$. +## Thus we can reconstruct the matrix $M$ up to the scalar factor $c$. +## +## In the cases that are supported, either $c$ is irrelevant because the +## matrix group contains all scalar matrices, or we know that the preimage +## has determinant $1$ and taking the root in question is unique. +## InstallMethod( PreImagesRepresentative,"IsProjectiveActionHomomorphism", FamRangeEqFamElm, [ IsProjectiveActionHomomorphism, IsPerm ], 0, function( hom, elm ) - local V, mat, xset,lab,f,dim,sol,i; + local V, G, Grep, mat, xset,lab,dim,sol,i; # is this method applicable? Test whether field # finite, that the domain contains a vector @@ -3435,18 +3455,19 @@ function( hom, elm ) #if not elm in Image( hom ) then return fail; fi; xset:=UnderlyingExternalSet(hom); V := HomeEnumerator(xset); - f:=DefaultFieldOfMatrixGroup(Source(hom)); - dim:=DimensionOfMatrixGroup(Source(hom)); + G:= Source( hom ); + Grep:= Representative( G ); + dim:=DimensionOfMatrixGroup(G); elm:=OnTuples(hom!.projActBasisPositions,elm); # image points elm:=V{elm}; # the corresponding vectors - mat:=elm{[1..dim]}; + mat:= Matrix( List( elm{ [ 1 .. dim ] }, ShallowCopy ), Grep ); sol:=SolutionMat(mat,elm[dim+1]); for i in [1..dim] do - mat[i]:=sol[i]*mat[i]; + MultMatrixRow( mat, i, sol[i] ); od; - mat:=hom!.projActInverse*ImmutableMatrix(f,mat); + mat:= hom!.projActInverse * mat; # correct scalar using determinant if needed if hom!.correctionFactors[1]<>fail then @@ -3457,7 +3478,7 @@ function( hom, elm ) fi; fi; - return mat; + return MakeImmutable( mat ); end); ############################################################################# @@ -3467,18 +3488,24 @@ end); InstallMethod(LinearActionBasis,"find basis in domain",true, [IsLinearActionHomomorphism],0, function(hom) -local xset,D,b,t,i,r,pos; +local xset, base, M, D, b, t, i, r, pos, v; xset:=UnderlyingExternalSet(hom); if Size(xset)=0 then return fail; fi; - pos:=[]; # if there is a base, check whether it's full rank, if yes, take it - if HasBaseOfGroup(xset) - and RankMat(BaseOfGroup(xset))=Length(BaseOfGroup(xset)[1]) then - # this implies injectivity - SetIsInjective(hom,true); - return BaseOfGroup(xset); + if HasBaseOfGroup(xset) then + base:= BaseOfGroup(xset); + if IsMatrix( base ) then + M:= base; + elif ForAll( base, IsVectorObj ) then + M:= Matrix( BaseOfGroup( xset ), One( ActingDomain( xset ) ) ); + fi; + if RankMat( M ) = NrCols( M ) then + # this implies injectivity + SetIsInjective(hom,true); + return base; + fi; fi; # otherwise we've to find a basis from the domain. D:=HomeEnumerator(xset); @@ -3486,12 +3513,15 @@ local xset,D,b,t,i,r,pos; t:=[]; r:=Length(D[1]); i:=1; + pos:=[]; while Length(b)Length(t) then + v:= Unpack( D[i] ); +#TODO: try to get rid of 'Unpack' + if RankMat(Concatenation(t,[v]))>Length(t) then # new indep. vector Add(b,D[i]); Add(pos,i); - Add(t,ShallowCopy(D[i])); + Add(t, v); TriangulizeMat(t); # for faster rank tests fi; i:=i+1; @@ -3532,7 +3562,7 @@ end); InstallOtherMethod(LinearActionBasis,"projective with extra vector",true, [IsProjectiveActionHomomorphism],0, function(hom) -local xset,G,D,b,t,i,r,binv,pos,dets,roots,dim,f; +local xset,G,Grep,D,b,t,i,r,binv,pos,dets,roots,dim,f,v; xset:=UnderlyingExternalSet(hom); if Size(xset)=0 then return fail; @@ -3540,6 +3570,7 @@ local xset,G,D,b,t,i,r,binv,pos,dets,roots,dim,f; # will the determinants suffice to get suitable scalars? G:= Source(hom); + Grep:= Representative( G ); dim:=DimensionOfMatrixGroup(G); f:=DefaultFieldOfMatrixGroup(G); @@ -3575,11 +3606,13 @@ local xset,G,D,b,t,i,r,binv,pos,dets,roots,dim,f; i:=1; pos:=[]; while Length(b)Length(t) then + v:= Unpack( D[i] ); +#TODO: try to get rid of 'Unpack' + if RankMat(Concatenation(t,[v]))>Length(t) then # new indep. vector Add(b,D[i]); Add(pos,i); - Add(t,ShallowCopy(D[i])); + Add(t,v); TriangulizeMat(t); # for faster rank tests fi; i:=i+1; @@ -3589,15 +3622,20 @@ local xset,G,D,b,t,i,r,binv,pos,dets,roots,dim,f; fi; # try to find a vector that has nonzero coefficients for all b - binv:=Inverse(ImmutableMatrix(f,b)); + binv:= Inverse( ImmutableMatrix( f, Matrix( b, Grep ) ) ); while i<=Length(D) do - if ForAll(D[i]*binv,x->not IsZero(x)) then + if ForAll( Unpack( D[i] * binv ), x -> not IsZero(x) ) then +#TODO: get rid of 'Unpack'? Add(b,D[i]); Add(pos,i); hom!.projActBasisPositions:=pos; - hom!.projActInverse:=ImmutableMatrix(f,binv*Inverse(DiagonalMat(D[i]*binv))); + hom!.projActInverse:= ImmutableMatrix( f, + binv * Inverse( DiagonalMatrix( D[i] * binv, binv ) ) ); hom!.correctionFactors:=[dets,roots]; - return ImmutableMatrix(f,b); + if IsScalarList( D[1] ) then + b:= ImmutableMatrix(f,b); + fi; + return b; fi; i:=i+1; od; diff --git a/lib/vspcrow.gi b/lib/vspcrow.gi index 812c16179f..05df43d515 100644 --- a/lib/vspcrow.gi +++ b/lib/vspcrow.gi @@ -1033,44 +1033,26 @@ InstallMethod( Intersection2, ############################################################################# ## -#M NormedRowVectors( ) +#M NormedRowVectors_internal( , ) ## -InstallMethod( NormedRowVectors, - "for Gaussian row space", - [ IsGaussianRowSpace ], - function( V ) - local base, # basis vectors - elms, # element list, result - elms2, # intermediate element list - F, # `LeftActingDomain( V )' - q, # `Size( F )' - fieldelms, # elements of `F' (in other succession) - j, # loop over `base' - new, # intermediate element list - pos, # position in `new' to store the next element - len, # actual length of `elms2' - i, # loop over field elements - toadd, # vector to add to known vectors - k, # loop over `elms2' - v; # one normed row vector - - if not IsFinite( V ) then - Error( "sorry, cannot compute normed vectors of infinite domain " ); - fi; +## Assume that is a list of row vectors or vector objects over +## that is in echelon form. +## +BindGlobal( "NormedRowVectors_internal", function( F, base ) + local elms, elms2, fieldelms, j, new, pos, len, i, toadd, k; - base:= Reversed( BasisVectors( CanonicalBasis( V ) ) ); if Length( base ) = 0 then return []; + elif not IsFinite( F ) then + Error( "sorry, cannot compute normed vectors over infinite domain " ); fi; + base := Reversed( base ); elms := [ base[1] ]; elms2 := [ base[1] ]; - F := LeftActingDomain( V ); - q := Size( F ); fieldelms := List( AsSSortedList( F ), x -> x - 1 ); for j in [ 1 .. Length( base ) - 1 ] do - # Here `elms2' has the form # $b_i + M = b_i + \langle b_{i+1}, \ldots, b_n \rangle$. # Compute $b_{i-1} + \bigcup_{\lambda\in F} \lambda b_i + ( b_i + M )$. @@ -1080,9 +1062,7 @@ InstallMethod( NormedRowVectors, for i in fieldelms do toadd:= base[j+1] + i * base[j]; for k in [ 1 .. len ] do - v:= elms2[k] + toadd; - v:= ImmutableVector( q, v ); - new[ pos + k ]:= v; + new[ pos + k ]:= ImmutableVector( F, elms2[k] + toadd ); od; pos:= pos + len; od; @@ -1090,9 +1070,27 @@ InstallMethod( NormedRowVectors, # `elms2' is a set here. Append( elms, elms2 ); - od; + # Return the result. + return elms; + end ); + + +############################################################################# +## +#M NormedRowVectors( ) +## +InstallMethod( NormedRowVectors, + "for Gaussian row space", + [ IsGaussianRowSpace ], + function( V ) + local base, # basis vectors + elms; # element list, result + + base:= BasisVectors( CanonicalBasis( V ) ); + elms:= NormedRowVectors_internal( LeftActingDomain( V ), base ); + # The list is strictly sorted, so we store this. MakeImmutable( elms ); Assert( 1, IsSSortedList( elms ) ); diff --git a/tst/testbugfix/2007-07-02-t00180.tst b/tst/testbugfix/2007-07-02-t00180.tst index be77f789b5..a7f8e14c7c 100644 --- a/tst/testbugfix/2007-07-02-t00180.tst +++ b/tst/testbugfix/2007-07-02-t00180.tst @@ -1,6 +1,6 @@ # 2007/07/02 (SK) gap> GeneratorsOfRing(Rationals); -Error, cannot compute elements list of infinite domain +Error, cannot compute elements list over infinite domain gap> GeneratorsOfRingWithOne(Rationals); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 2nd choice method found for `GeneratorsOfRingWithOne' on 1 arguments diff --git a/tst/testinstall/MatrixObj/DeterminantMatrix.tst b/tst/testinstall/MatrixObj/DeterminantMatrix.tst new file mode 100644 index 0000000000..8d9f63eeca --- /dev/null +++ b/tst/testinstall/MatrixObj/DeterminantMatrix.tst @@ -0,0 +1,29 @@ +#@local M, mat +gap> START_TEST( "DeterminantMatrix.tst" ); + +# nonsquare matrix +gap> mat:= [[1,2,1,2],[1,0,1,0],[2,2,2,2]];; +gap> M:= NewMatrix( IsPlistMatrixRep, GF(5), 4, mat*Z(5)^0 );; +gap> DeterminantMatrix( M ); +Error, DeterminantMat: must be a nonempty square matrix + +# 0x0 matrix +gap> M:= ZeroMatrix( IsPlistRep, GF(9), 0, 0 ); +[ ] +gap> DeterminantMatrix( M ); +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `DeterminantMatrix' on 1 arguments +gap> M:= ZeroMatrix( IsPlistMatrixRep, GF(9), 0, 0 ); +<0x0-matrix over GF(3^2)> +gap> DeterminantMatrix( M ); +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `DeterminantMatrix' on 1 arguments + +# square nonempty matrix +gap> mat:= [[1,2,1],[1,0,1],[2,2,2]];; +gap> M:= NewMatrix( IsPlistMatrixRep, GF(5), 3, mat*Z(5)^0 );; +gap> DeterminantMatrix( M ); +0*Z(5) + +# +gap> STOP_TEST( "DeterminantMatrix.tst" ); diff --git a/tst/testinstall/MatrixObj/RandomInvertibleMatrix.tst b/tst/testinstall/MatrixObj/RandomInvertibleMatrix.tst new file mode 100644 index 0000000000..258d6c2934 --- /dev/null +++ b/tst/testinstall/MatrixObj/RandomInvertibleMatrix.tst @@ -0,0 +1,52 @@ +#@local rs, M +gap> START_TEST( "RandomInvertibleMatrix.tst" ); + +# with base domain +gap> Is8BitMatrixRep( RandomInvertibleMatrix( GF(9), 10 ) ); +true +gap> IsPlistMatrixRep( RandomInvertibleMatrix( Integers, 10 ) ); +true + +# with constructing filter and base domain +gap> Is8BitMatrixRep( RandomInvertibleMatrix( Is8BitMatrixRep, GF(9), 10 ) ); +true +gap> IsPlistRep( RandomInvertibleMatrix( IsPlistRep, Integers, 10 ) ); +true + +# with random source and base domain +gap> rs:= RandomSource(IsMersenneTwister);; +gap> Is8BitMatrixRep( RandomInvertibleMatrix( Is8BitMatrixRep, GF(9), 10 ) ); +true +gap> IsPlistRep( RandomInvertibleMatrix( IsPlistRep, Integers, 10 ) ); +true + +# with constructing filter, random source, and base domain +gap> Is8BitMatrixRep( RandomInvertibleMatrix( Is8BitMatrixRep, rs, GF(9), 10 ) ); +true +gap> IsPlistRep( RandomInvertibleMatrix( IsPlistRep, rs, Integers, 10 ) ); +true + +# with example matrix +gap> M:= Matrix( IsPlistMatrixRep, Integers, [ 1 ], 1 );; +gap> RandomInvertibleMatrix( 2, M ); +<2x2-matrix over Integers> +gap> M:= [ [ 1 ] ];; +gap> IsPlistRep( RandomInvertibleMatrix( 2, M ) ); +true +gap> M:= Matrix( IsPlistMatrixRep, GF(3), [ Z(3) ], 1 );; +gap> RandomInvertibleMatrix( 2, M ); +<2x2-matrix over GF(3)> + +# with random source and example matrix +gap> M:= Matrix( IsPlistMatrixRep, Integers, [ 1 ], 1 );; +gap> RandomInvertibleMatrix( rs, 2, M ); +<2x2-matrix over Integers> +gap> M:= [ [ 1 ] ];; +gap> IsPlistRep( RandomInvertibleMatrix( rs, 2, M ) ); +true +gap> M:= Matrix( IsPlistMatrixRep, GF(3), [ Z(3) ], 1 );; +gap> RandomInvertibleMatrix( rs, 2, M ); +<2x2-matrix over GF(3)> + +# +gap> STOP_TEST( "RandomInvertibleMatrix.tst" ); diff --git a/tst/testinstall/MatrixObj/RandomMatrix.tst b/tst/testinstall/MatrixObj/RandomMatrix.tst new file mode 100644 index 0000000000..d4460cf9c0 --- /dev/null +++ b/tst/testinstall/MatrixObj/RandomMatrix.tst @@ -0,0 +1,72 @@ +#@local rs, M +gap> START_TEST( "RandomMatrix.tst" ); + +# with base domain +gap> Is8BitMatrixRep( RandomMatrix( GF(9), 10, 5 ) ); +true +gap> RandomMatrix( GF(9), 0, 1 ); +Error, Is8BitMatrixRep with zero rows not yet supported +gap> IsPlistMatrixRep( RandomMatrix( Integers, 10, 5 ) ); +true +gap> IsPlistMatrixRep( RandomMatrix( Integers, 0, 0 ) ); +true + +# with constructing filter and base domain +gap> Is8BitMatrixRep( RandomMatrix( Is8BitMatrixRep, GF(9), 10, 5 ) ); +true +gap> IsPlistMatrixRep( RandomMatrix( IsPlistMatrixRep, GF(9), 0, 0 ) ); +true +gap> IsPlistRep( RandomMatrix( IsPlistRep, Integers, 10, 5 ) ); +true + +# with random source and base domain +gap> rs:= RandomSource(IsMersenneTwister);; +gap> Is8BitMatrixRep( RandomMatrix( Is8BitMatrixRep, GF(9), 10, 5 ) ); +true +gap> IsPlistMatrixRep( RandomMatrix( IsPlistMatrixRep, GF(9), 0, 0 ) ); +true +gap> IsPlistRep( RandomMatrix( IsPlistRep, Integers, 10, 5 ) ); +true + +# with constructing filter, random source, and base domain +gap> Is8BitMatrixRep( RandomMatrix( Is8BitMatrixRep, rs, GF(9), 10, 5 ) ); +true +gap> IsPlistMatrixRep( RandomMatrix( IsPlistMatrixRep, rs, GF(9), 0, 0 ) ); +true +gap> IsPlistRep( RandomMatrix( IsPlistRep, rs, Integers, 10, 5 ) ); +true + +# with example matrix +gap> M:= Matrix( IsPlistMatrixRep, Integers, [ 1 ], 1 );; +gap> RandomMatrix( 2, 2, M ); +<2x2-matrix over Integers> +gap> RandomMatrix( 0, 0, M ); +<0x0-matrix over Integers> +gap> M:= [ [ 1 ] ];; +gap> BaseDomain( M ); +Rationals +gap> IsPlistRep( RandomMatrix( 2, 2, M ) ); +true +gap> ForAll( Flat( RandomMatrix( 1, 2, M ) ), IsRat ); +true +gap> M:= Matrix( IsPlistMatrixRep, GF(3), [ Z(3) ], 1 );; +gap> RandomMatrix( 2, 2, M ); +<2x2-matrix over GF(3)> + +# with random source and example matrix +gap> M:= Matrix( IsPlistMatrixRep, Integers, [ 1 ], 1 );; +gap> RandomMatrix( rs, 2, 2, M ); +<2x2-matrix over Integers> +gap> RandomMatrix( rs, 0, 0, M ); +<0x0-matrix over Integers> +gap> M:= [ [ 1 ] ];; +gap> IsPlistRep( RandomMatrix( rs, 2, 2, M ) ); +true +gap> ForAll( Flat( RandomMatrix( rs, 1, 2, M ) ), IsRat ); +true +gap> M:= Matrix( IsPlistMatrixRep, GF(3), [ Z(3) ], 1 );; +gap> RandomMatrix( rs, 2, 2, M ); +<2x2-matrix over GF(3)> + +# +gap> STOP_TEST( "RandomMatrix.tst" ); diff --git a/tst/testinstall/MatrixObj/RankMatrix.tst b/tst/testinstall/MatrixObj/RankMatrix.tst new file mode 100644 index 0000000000..d8561b2806 --- /dev/null +++ b/tst/testinstall/MatrixObj/RankMatrix.tst @@ -0,0 +1,23 @@ +#@local M, mat +gap> START_TEST( "RankMatrix.tst" ); + +# nonsquare matrix +gap> mat:= [[1,2,1,2],[1,0,1,0],[2,2,2,2]];; +gap> M:= NewMatrix( IsPlistMatrixRep, GF(5), 4, mat*Z(5)^0 ); +<3x4-matrix over GF(5)> +gap> RankMatrix( M ); +2 + +# 0x0 matrix +gap> M:= ZeroMatrix( IsPlistRep, GF(9), 0, 0 ); +[ ] +gap> RankMatrix( M ); +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `RankMatrix' on 1 arguments +gap> M:= ZeroMatrix( IsPlistMatrixRep, GF(9), 0, 0 ); +<0x0-matrix over GF(3^2)> +gap> RankMatrix( M ); +0 + +# +gap> STOP_TEST( "RankMatrix.tst" ); diff --git a/tst/testinstall/MatrixObj/acthom.tst b/tst/testinstall/MatrixObj/acthom.tst new file mode 100644 index 0000000000..6f7e73ed3e --- /dev/null +++ b/tst/testinstall/MatrixObj/acthom.tst @@ -0,0 +1,80 @@ +#@local right_representation, q, F, d, filt, groups, G, basis, xset, vectors +#@local orbs, len, D1, v, D2, D3, D4, actions, D, hom, i, g, img, pre +gap> START_TEST( "acthom.tst" ); + +# +gap> right_representation:= function( filt, g ) +> return ( filt = IsPlistRep and IsList( g ) ) or +> ( filt <> IsPlistRep and filt( g ) ); +> end;; +gap> for q in [ 2, 3, 4 ] do +> F:= GF(q); +> for d in [ 2 .. 4 ] do +> for filt in [ IsPlistRep, IsPlistMatrixRep ] do +> PushOptions( rec( ConstructingFilter:= filt ) ); +> # Test groups with special methods and a general group. +> groups:= [ GL( d, F ), SL( d, F ) ]; +> # Add( groups, SylowSubgroup( groups[1], 2 ) ); +> # Add( groups, Subgroup( groups[1], +> # [ GeneratorsOfGroup( groups[1] )[1] ] ) ); +> for G in groups do +> # Consider the G-action +> # - given by the nice monomorphism +> # - on an orbit (linear & projective) +> # - on the whole natural G-set (linear & projective) +> basis:= RowsOfMatrix( One( G ) ); +> xset:= ExternalSet( G ); +> vectors:= HomeEnumerator( xset ); +> orbs:= Orbits( G, vectors ); +> len:= Maximum( List( orbs, Length ) ); +> D1:= [ First( orbs, x -> Length( x ) = len ), OnRight ]; +> v:= OnLines( D1[1][1], One( G ) ); +> D2:= [ Orbit( G, v, OnLines ), OnLines ]; +> D3:= [ vectors, OnRight ]; +> D4:= [ NormedRowVectors_internal( F, basis ), OnLines ]; +> +> actions:= [ NiceMonomorphism( G ) ]; +> for D in [ D1, D2, D3, D4 ] do +> if not CompatibleVectorFilter( One( G ) )( D[1][1] ) then +> Error( "wrong repres. of vector for ", [ q, d, filt ] ); +> fi; +> hom:= ActionHomomorphism( G, D[1], D[2] ); +> if D[2] <> OnLines and +> not IsLinearActionHomomorphism( hom ) then +> Error( "unexpected type of action hom. for ", +> [ q, d, filt ] ); +> fi; +> Add( actions, hom ); +> od; +> +> for hom in actions do +> for i in [ 1 .. 5 ] do +> g:= Random( G ); +> if not right_representation( filt, g ) then +> Error( "wrong repres. of random matrix for ", +> [ q, d, filt ] ); +> fi; +> img:= g^hom; +> pre:= PreImagesRepresentative( hom, img ); +> if not right_representation( filt, pre ) then +> Error( "wrong repres. of preimage matrix for ", +> [ q, d, filt ] ); +> fi; +> if FunctionAction( UnderlyingExternalSet( hom ) ) = OnLines then +> if not ( pre / g in Centre( G ) ) then +> Error( "problem with projective action for ", +> [ q, d, filt ] ); +> fi; +> elif pre <> g then +> Error( "problem with linear action for ", +> [ q, d, filt ] ); +> fi; +> od; +> od; +> od; +> od; +> od; +> od; + +# +gap> STOP_TEST( "acthom.tst" ); diff --git a/tst/testinstall/grpmat.tst b/tst/testinstall/grpmat.tst index 31b192e7ba..4c23741723 100644 --- a/tst/testinstall/grpmat.tst +++ b/tst/testinstall/grpmat.tst @@ -1,4 +1,4 @@ -#@local cl,g,gd,gens,hom,i,img,iso,pcgs,u,G,F,o,a,m,nice,H +#@local cl,g,gd,gens,hom,i,img,iso,pcgs,u,G,F,o,a,m,nice,H,G2,nice2 gap> START_TEST("grpmat.tst"); gap> i := E(4);; G := Group([[i,0],[0,-i]],[[0,1],[-1,0]]);; gap> gens := GeneratorsOfGroup( G );; IsSSortedList( gens ); @@ -89,5 +89,21 @@ gap> TrivialSubgroup( GL(2, 2) ); gap> Length( LowIndexSubgroups( GL(2,5), 50 ) ) = 31; true +# 'NiceMonomorphism' behaves well w.r.t. 'ConstructingFilter' +gap> G:= SP( 4, 2 );; +gap> nice:= NiceMonomorphism( G );; +gap> G2:= SP( 4, 2 : ConstructingFilter:= IsPlistMatrixRep );; +gap> nice2:= NiceMonomorphism( G2 );; +gap> IsPlistMatrixRep( One( G ) ); +false +gap> IsPlistMatrixRep( One( G2 ) ); +true +gap> IsIdenticalObj( nice, nice2 ); +false +gap> IsSubset( Source( nice ), G ); +true +gap> IsSubset( Source( nice2 ), G2 ); +true + # gap> STOP_TEST( "grpmat.tst" ); From ce32e7883132cf1119db4bb7be44b2caacd4baea Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 22 Apr 2026 02:25:33 +0200 Subject: [PATCH 35/52] Faster {Copy,Extract}Sub{Matrix,Vector} for plist matrices/vectors (#6329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... by avoiding some method dispatch, providing optimized methods using `{...}` syntax, and turning ExtractSubVector, CopySubVector, ExtractSubMatrix, and CopySubMatrix into kernel ops. Then run some benchmarks via `benchmark/matobj/bench-submat.g` and the new `benchmark/matobj/bench-subvec.g`. Before: +----------------------------------------------------------------+ | Testing submatrix extraction for integer matrix: list of lists | +----------------------------------------------------------------+ Testing m{}{}: 129 µs per iteration; 7749 iterations per second; (200 iterations) Testing ExtractSubMatrix: 720 µs per iteration; 1388 iterations per second; (200 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 342 µs per iteration; 2921 iterations per second; (200 iterations) Testing CopySubMatrix: 1032 µs per iteration; 969 iterations per second; (200 iterations) +------------------------------------------------+ | Testing submatrix extraction for GF(2) rowlist | +------------------------------------------------+ Testing m{}{}: 167 µs per iteration; 5999 iterations per second; (200 iterations) Testing ExtractSubMatrix: 3288 µs per iteration; 304 iterations per second; (92 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 1992 µs per iteration; 502 iterations per second; (151 iterations) Testing CopySubMatrix: 2606 µs per iteration; 384 iterations per second; (116 iterations) +-------------------------------------------------------------+ | Testing subvector extraction for integer vector: plain list | +-------------------------------------------------------------+ Testing x{}:=v{}: 393 µs per iteration; 2542 iterations per second; (200 iterations) Testing CopySubVector: 2324 µs per iteration; 430 iterations per second; (130 iterations) +---------------------------------------------------+ | Testing subvector extraction for GF(2) row vector | +---------------------------------------------------+ Testing x{}:=v{}: 441 µs per iteration; 2266 iterations per second; (200 iterations) Testing CopySubVector: 2458 µs per iteration; 407 iterations per second; (123 iterations) After: +----------------------------------------------------------------+ | Testing submatrix extraction for integer matrix: list of lists | +----------------------------------------------------------------+ Testing m{}{}: 136 µs per iteration; 7355 iterations per second; (200 iterations) Testing ExtractSubMatrix: 140 µs per iteration; 7135 iterations per second; (200 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 301 µs per iteration; 3319 iterations per second; (200 iterations) Testing CopySubMatrix: 299 µs per iteration; 3347 iterations per second; (200 iterations) +------------------------------------------------+ | Testing submatrix extraction for GF(2) rowlist | +------------------------------------------------+ Testing m{}{}: 154 µs per iteration; 6490 iterations per second; (200 iterations) Testing ExtractSubMatrix: 146 µs per iteration; 6854 iterations per second; (200 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 1895 µs per iteration; 528 iterations per second; (159 iterations) Testing CopySubMatrix: 1935 µs per iteration; 517 iterations per second; (156 iterations) +-------------------------------------------------------------+ | Testing subvector extraction for integer vector: plain list | +-------------------------------------------------------------+ Testing x{}:=v{}: 428 µs per iteration; 2336 iterations per second; (200 iterations) Testing CopySubVector: 453 µs per iteration; 2209 iterations per second; (200 iterations) +---------------------------------------------------+ | Testing subvector extraction for GF(2) row vector | +---------------------------------------------------+ Testing x{}:=v{}: 427 µs per iteration; 2344 iterations per second; (200 iterations) Testing CopySubVector: 460 µs per iteration; 2172 iterations per second; (200 iterations) So overall the Copy/Extract methods are now more or less on par with the code using `{...}` syntax. But actually this `ExtractSubMatrix` for a GF(2) rowlist is now *faster* than the optimized one for a compressed GF(2) matrix: +----------------------------------------------------------+ | Testing submatrix extraction for GF(2) compressed matrix | +----------------------------------------------------------+ Testing m{}{}: 1057 µs per iteration; 946 iterations per second; (200 iterations) Testing ExtractSubMatrix: 1618 µs per iteration; 618 iterations per second; (186 iterations) A substantial part of that is due to the the `ExtractSubMatrix` method for `IsGF2MatrixRep` calling `ConvertToMatrixRepNC(mm,2)`; after removing that, it went down from 1618 to 392 µs (which is still worse). --- AI assistance: Codex implemented the kernel plumbing, method cleanup, and test updates. It also created `benchmark/matobj/bench-subvec.g`. Co-authored-by: Codex --- .../MatrixObj/ExtractSubMatrix.tst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst index 35517c5f25..b73e17a196 100644 --- a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst +++ b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst @@ -1,8 +1,10 @@ gap> START_TEST("ExtractSubMatrix.tst"); + gap> IsBoundGlobal("EXTRACT_SUB_MATRIX"); true gap> EXTRACT_SUB_MATRIX = ExtractSubMatrix; true + gap> m1 := [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] gap> ExtractSubMatrix( m1, [ 2, 1 ], [ 3, 1 ] ); @@ -10,4 +12,21 @@ gap> ExtractSubMatrix( m1, [ 2, 1 ], [ 3, 1 ] ); gap> m2 := IdentityMatrix( Integers, 4 );; gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); [ [ 0, 1 ], [ 1, 0 ] ] + +# IsGF2MatrixRep +gap> m1 := IdentityMatrix( GF(2), 100 ); + +gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); + +gap> IsOne(m2); +true + +# Is8BitMatrixRep +gap> m1 := IdentityMatrix( GF(3), 100 ); +< mutable compressed matrix 100x100 over GF(3) > +gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); +< mutable compressed matrix 20x20 over GF(3) > +gap> IsOne(m2); +true + gap> STOP_TEST("ExtractSubMatrix.tst"); From c23216d2ded18ab04eaaa8b05757ba9bb06d3040 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Tue, 5 May 2026 09:16:38 +0100 Subject: [PATCH 36/52] ChangeBaseDomain --- lib/matobj2.gd | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 1405092d67..9869c1186e 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -388,6 +388,12 @@ DeclareOperation( "ListOp", [ IsVectorObj, IsFunction ] ); ##

## 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> @@ -927,6 +933,17 @@ DeclareTagBasedOperation( "NewIdentityMatrix", ##

## 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> @@ -996,6 +1013,13 @@ DeclareOperation( "Randomize", [ IsRandomSource, IsMatrixOrMatrixObj and IsMutab ##

## 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, [ 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> @@ -1303,7 +1327,6 @@ DeclareOperation( "ZeroMatrix", [ IsOperation, IsSemiring, IsInt, IsInt ] ); ## 1 . . ## . 1 . ## . . 1 -## ]> ## ]]> ## ## From e0a1dbc83ae94968028a6bfa252fb19e16a91c8e Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 7 May 2026 09:29:50 +0100 Subject: [PATCH 37/52] examples up to and including 26.10 --- lib/matobj.gi | 32 + lib/matobj2.gd | 1648 +++++++++++++++++++++++++----------------------- 2 files changed, 903 insertions(+), 777 deletions(-) diff --git a/lib/matobj.gi b/lib/matobj.gi index 35ae1ccbe0..ca1c152681 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,21 @@ 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( [ [1,1], [0,1] ], m1 );; +## gap> Print( m3 * m1 ); +## NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 9, 11, 13 ], [ 6, 7, 8 ] ]) +## ]]> ## ## ## <#/GAPDoc> diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 9869c1186e..cf2798a88c 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( ) @@ -245,126 +227,609 @@ 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"> -## -## -## -## An integer -## -## 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. -## -## -## <#/GAPDoc> -## -DeclareOperation( "PositionNonZero", [ IsVectorObj ] ); - - -############################################################################# +#O ZeroVector( , ) +#O ZeroVector( , ) +#O ZeroVector( , ) +#O ZeroVector( , , ) ## -## <#GAPDoc Label="MatObj_PositionLastNonZero"> +## <#GAPDoc Label="VectorObj_ZeroVector"> ## -## +## ZeroVector +## +## +## +## ## -## An integer +## a vector object ## -## 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. +## 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( "PositionLastNonZero", [ IsVectorObj ] ); +DeclareOperation( "ZeroVector", [ IsSemiring, IsInt ] ); +DeclareOperation( "ZeroVector", [ IsInt, IsVecOrMatObj ] ); +DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); +#DeclareOperation( "ZeroVector", [ IsInt, IsVectorObj ] ); +#DeclareOperation( "ZeroVector", [ IsInt, IsMatrixOrMatrixObj ] ); ############################################################################# ## -#O ListOp( [, ] ) +#O NewVector( , , ) +#O NewZeroVector( , , ) ## -## <#GAPDoc Label="MatObj_ListOp"> +## <#GAPDoc Label="NewVector"> ## -## +## NewVector and NewZeroVector +## +## ## -## A plain list ## -## 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. +## These two operations are constructors, and should only be used +## when or +## +## do not give the desired result. ##

-## If the argument func is not given, -## applies to all entries. -## -## -## <#/GAPDoc> -## -DeclareOperation( "ListOp", [ IsVectorObj ] ); -DeclareOperation( "ListOp", [ IsVectorObj, IsFunction ] ); +## 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> +## +DeclareTagBasedOperation( "NewVector", [ IsOperation, IsSemiring, IsList ] ); + +DeclareTagBasedOperation( "NewZeroVector", + [ IsOperation, IsSemiring, IsInt ] ); + + +############################################################################# +## +#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"> +## +## Matrix +## +## +## +## +## +## +## a matrix object +## +## 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 +## ############################################################################# @@ -408,581 +873,442 @@ DeclareOperation( "Unpack", [ IsVecOrMatObj ] ); ############################################################################# ## -## <#GAPDoc Label="MatObj_ConcatenationOfVectors"> -## -## ConcatenationOfVectors -## -## +#O ChangedBaseDomain( , ) +#O ChangedBaseDomain( , ) ## -## a vector object +## <#GAPDoc Label="ChangedBaseDomain"> +## +## ChangedBaseDomain +## +## ## ## -## 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. +## 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). ##

-## (Note that -## is a function for which no methods can be installed.) +## 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> ## -DeclareGlobalFunction( "ConcatenationOfVectors" ); +DeclareOperation( "ChangedBaseDomain", [ IsVecOrMatObj, IsSemiring ] ); +#DeclareOperation( "ChangedBaseDomain", [ IsVectorObj, IsSemiring ] ); +#DeclareOperation( "ChangedBaseDomain", [ IsMatrixOrMatrixObj, IsSemiring ] ); -############################################################################# -## -## <#GAPDoc Label="MatObj_ExtractSubVector"> -## -## +############################################################################ ## -## a vector object +#O Randomize( [Rs, ]v ) +#O Randomize( [Rs, ]M ) ## +## <#GAPDoc Label="Randomize"> +## +## Randomize +## +## ## -## 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. +## 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. ##

-## 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 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> ## -DeclareOperationKernel( "ExtractSubVector", - [ IsRowVectorOrVectorObj, IsList ], EXTRACT_SUB_VECTOR ); +DeclareOperation( "Randomize", [ IsVectorObj and IsMutable ] ); +DeclareOperation( "Randomize", [ IsRandomSource, IsVectorObj and IsMutable ] ); +DeclareOperation( "Randomize", [ IsMatrixOrMatrixObj and IsMutable ] ); +DeclareOperation( "Randomize", [ IsRandomSource, IsMatrixOrMatrixObj and IsMutable ] ); ############################################################################# ## -## Arithmetical operations for vector objects +## List Like Operations for Vector Objects ## ############################################################################# ## -#O AddVector( , [, [, , ]] ) -#O AddVector( , , [, , ] ) +#O \[\]( , ) +#O \[\]\:\=( , , ) +#O \{\}( , ) ## -## <#GAPDoc Label="MatObj_AddVector"> +## <#GAPDoc Label="ElementAccessVectorObj"> ## -## -## +## Element Access and Assignment for Vector Objects ## -## nothing +## +## +## ## ## -## Called with two vector objects dst and src, -## this function replaces the entries of dst in-place -## by the entries of the sum dst + src. +## 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 scalar mul is given as the third or second argument, -## respectively, then the entries of dst get replaced by those of -## dst + src * mul or -## dst + mul * src, 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 the optional parameters from and to are given then -## only the index range [from..to] is guaranteed to be -## affected. -## Other indices may be affected, if it is more convenient to do so. -## This can be helpful if entries of src are known to be zero. +## 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. ##

-## If from is bigger than to, the operation does nothing. +## 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> ## -DeclareOperation( "AddVector", - [ IsVectorObj and IsMutable, IsVectorObj ] ); -DeclareOperation( "AddVector", - [ IsVectorObj and IsMutable, IsVectorObj, IsObject ] ); -DeclareOperation( "AddVector", - [ IsVectorObj and IsMutable, IsObject, IsVectorObj ] ); -DeclareOperation( "AddVector", - [ IsVectorObj and IsMutable, IsVectorObj, IsObject, IsPosInt, IsPosInt ] ); -DeclareOperation( "AddVector", - [ IsVectorObj and IsMutable, IsObject, IsVectorObj, IsPosInt, IsPosInt ] ); +DeclareOperation( "[]", [ IsVectorObj, IsPosInt ] ); + +DeclareOperation( "[]:=", [ IsVectorObj, IsPosInt, IsObject ] ); + +DeclareOperation( "{}", [ IsVectorObj, IsList ] ); ############################################################################# ## -#O MultVector( , [, , ] ) -#O MultVectorLeft( , [, , ] ) -#O MultVectorRight( , [, , ] ) -## -## <#GAPDoc Label="MatObj_MultVectorLeft"> +## <#GAPDoc Label="MatObj_PositionNonZero"> ## -## -## -## -## -## nothing +## ## +## An integer ## -## These operations multiply v by mul in-place -## where -## multiplies with mul from the left -## and -## does so from the right. -##

-## Note that -## is just a synonym for -## . -## This was chosen because vectors in &GAP; are by default row vectors -## and scalar multiplication is usually written as -## a \cdot v = a \cdot [v_1, ..., v_n] = [a \cdot v_1, ..., a \cdot v_n] -## with scalars being applied from the left. -##

-## If the optional parameters from and to are given then -## only the index range [from..to] is guaranteed to be -## affected. Other indices may be affected, if it is more convenient -## to do so. -## This can be helpful if entries of v are known to be zero. -## If from is bigger than to, the operation does nothing. +## 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. ##

+## 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> ## -DeclareOperation( "MultVectorLeft", - [ IsVectorObj and IsMutable, IsObject ] ); -DeclareOperation( "MultVectorLeft", - [ IsVectorObj and IsMutable, IsObject, IsInt, IsInt ] ); - -DeclareOperation( "MultVectorRight", - [ IsVectorObj and IsMutable, IsObject ] ); -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.) -DeclareOperation( "ScalarProduct", [ IsVectorObj, IsVectorObj ] ); +DeclareOperation( "PositionNonZero", [ IsVectorObj ] ); ############################################################################# ## -#O ZeroVector( , ) -#O ZeroVector( , ) -#O ZeroVector( , ) -#O ZeroVector( , , ) -## -## <#GAPDoc Label="VectorObj_ZeroVector"> +## <#GAPDoc Label="MatObj_PositionLastNonZero"> ## -## ZeroVector -## -## -## -## +## ## -## a vector object +## An integer ## -## 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 . +## 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. ##

## 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 ]) +## gap> 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( "ZeroVector", [ IsSemiring, IsInt ] ); -DeclareOperation( "ZeroVector", [ IsInt, IsVecOrMatObj ] ); -DeclareOperation( "ZeroVector", [ IsOperation, IsSemiring, IsInt ] ); -#DeclareOperation( "ZeroVector", [ IsInt, IsVectorObj ] ); -#DeclareOperation( "ZeroVector", [ IsInt, IsMatrixOrMatrixObj ] ); +DeclareOperation( "PositionLastNonZero", [ IsVectorObj ] ); ############################################################################# ## -#O Vector( , ) -#O Vector( , ) -#O Vector( , ) -#O Vector( , ) -#O Vector( , , ) -#O Vector( , , ) +#O ListOp( [, ] ) ## -## <#GAPDoc Label="Vector"> +## <#GAPDoc Label="MatObj_ListOp"> ## -## Vector -## -## -## -## -## -## -## +## ## -## a vector object +## A plain list ## -## If a semiring R is given as the first argument then -## a vector object is returned whose -## -## value is guessed from R, with base domain R -## and entries given by the last argument. -##

-## 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( 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. -##

-## 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. +## 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. ##

-## Default methods for -## -## delegate to . +## If the argument func is not given, +## applies to all entries. ##

## 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 ); -## +## gap> 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> ## -DeclareOperation( "Vector", [ IsSemiring, IsList ] ); -DeclareOperation( "Vector", [ IsSemiring, IsVectorObj ] ); -DeclareOperation( "Vector", [ IsList, IsVectorObj ] ); -DeclareOperation( "Vector", [ IsVectorObj, IsVectorObj ] ); -DeclareOperation( "Vector", [ IsList ] ); -DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsList ] ); -DeclareOperation( "Vector", [ IsOperation, IsSemiring, IsVectorObj ] ); +DeclareOperation( "ListOp", [ IsVectorObj ] ); +DeclareOperation( "ListOp", [ IsVectorObj, IsFunction ] ); ############################################################################# ## -#O NewVector( , , ) -#O NewZeroVector( , , ) +## Arithmetical operations for vector objects ## -## <#GAPDoc Label="NewVector"> + +############################################################################# +## +#O AddVector( , [, [, , ]] ) +#O AddVector( , , [, , ] ) +## +## <#GAPDoc Label="MatObj_AddVector"> ## -## NewVector and NewZeroVector -## -## +## +## +## +## nothing ## ## -## 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. +## Called with two vector objects dst and src, +## this function replaces the entries of dst in-place +## by the entries of the sum dst + src. ##

-## If the global option check is set to false then -## need not perform consistency checks. +## If a scalar mul is given as the third or second argument, +## respectively, then the entries of dst get replaced by those of +## dst + src * mul or +## dst + mul * src, respectively. ##

-## 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. +## If the optional parameters from and to are given then +## only the index range [from..to] is guaranteed to be +## affected. +## Other indices may be affected, if it is more convenient to do so. +## This can be helpful if entries of src are known to be zero. ##

-## The returned object is mutable if and only if filt implies -## . +## If from is bigger than to, the operation does nothing. ##

## 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 ); -## +## gap> 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> ## -DeclareTagBasedOperation( "NewVector", [ IsOperation, IsSemiring, IsList ] ); - -DeclareTagBasedOperation( "NewZeroVector", - [ IsOperation, IsSemiring, IsInt ] ); +DeclareOperation( "AddVector", + [ IsVectorObj and IsMutable, IsVectorObj ] ); +DeclareOperation( "AddVector", + [ IsVectorObj and IsMutable, IsVectorObj, IsObject ] ); +DeclareOperation( "AddVector", + [ IsVectorObj and IsMutable, IsObject, IsVectorObj ] ); +DeclareOperation( "AddVector", + [ IsVectorObj and IsMutable, IsVectorObj, IsObject, IsPosInt, IsPosInt ] ); +DeclareOperation( "AddVector", + [ IsVectorObj and IsMutable, IsObject, IsVectorObj, IsPosInt, IsPosInt ] ); ############################################################################# ## -#O NewMatrix( , , , ) -#O NewMatrix( , , , ) -#O NewMatrix( , , ) -#O NewZeroMatrix( , , , ) -#O NewIdentityMatrix( , , ) +#O MultVector( , [, , ] ) +#O MultVectorLeft( , [, , ] ) +#O MultVectorRight( , [, , ] ) ## -## <#GAPDoc Label="NewMatrix"> +## <#GAPDoc Label="MatObj_MultVectorLeft"> ## -## NewMatrix, NewZeroMatrix, NewIdentityMatrix -## -## -## -## -## +## +## +## +## +## nothing ## ## -## 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. +## These operations multiply v by mul in-place +## where +## multiplies with mul from the left +## and +## does so from the right. ##

-## 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. +## Note that +## is just a synonym for +## . +## This was chosen because vectors in &GAP; are by default row vectors +## and scalar multiplication is usually written as +## a \cdot v = a \cdot [v_1, ..., v_n] = [a \cdot v_1, ..., a \cdot v_n] +## with scalars being applied from the left. ##

-## The returned object is mutable if and only if filt implies -## . +## If the optional parameters from and to are given then +## only the index range [from..to] is guaranteed to be +## affected. Other indices may be affected, if it is more convenient +## to do so. +## This can be helpful if entries of v are known to be zero. +## If from is bigger than to, the operation does nothing. ##

## 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 ); -## +## gap> v1 := Vector( Integers, [0,1,2,4,8] );; +## gap> MultVector( v1, 2 ); Unpack( v1 ); +## [ 0, 2, 4, 8, 16 ] ## ]]> ## ## ## <#/GAPDoc> ## -DeclareTagBasedOperation( "NewMatrix", - [ IsOperation, IsSemiring, IsInt, IsList] ); - -DeclareOperation( "NewMatrix", - [ IsOperation, IsSemiring, IsList, IsInt] ); - -DeclareOperation( "NewMatrix", - [ IsOperation, IsSemiring, IsList] ); +DeclareOperation( "MultVectorLeft", + [ IsVectorObj and IsMutable, IsObject ] ); +DeclareOperation( "MultVectorLeft", + [ IsVectorObj and IsMutable, IsObject, IsInt, IsInt ] ); -DeclareTagBasedOperation( "NewZeroMatrix", - [ IsOperation, IsSemiring, IsInt, IsInt ] ); +DeclareOperation( "MultVectorRight", + [ IsVectorObj and IsMutable, IsObject ] ); +DeclareOperation( "MultVectorRight", + [ IsVectorObj and IsMutable, IsObject, IsInt, IsInt ] ); -DeclareTagBasedOperation( "NewIdentityMatrix", - [ IsOperation, IsSemiring, 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.) +DeclareOperation( "ScalarProduct", [ IsVectorObj, IsVectorObj ] ); ############################################################################# ## -#O ChangedBaseDomain( , ) -#O ChangedBaseDomain( , ) +## Operations for Vector Objects ## -## <#GAPDoc Label="ChangedBaseDomain"> + +############################################################################# +## +## <#GAPDoc Label="MatObj_ConcatenationOfVectors"> ## -## ChangedBaseDomain -## -## +## ConcatenationOfVectors +## +## +## +## a vector object ## ## -## 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. +## 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. ##

-## For example, one can create a vector defined over GF(4) -## from a vector defined over GF(2) with this operation. +## (Note that +## is a function for which no methods can be installed.) ##

## 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 ); -## +## gap> 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( "ChangedBaseDomain", [ IsVecOrMatObj, IsSemiring ] ); -#DeclareOperation( "ChangedBaseDomain", [ IsVectorObj, IsSemiring ] ); -#DeclareOperation( "ChangedBaseDomain", [ IsMatrixOrMatrixObj, IsSemiring ] ); +DeclareGlobalFunction( "ConcatenationOfVectors" ); -############################################################################ -## -#O Randomize( [Rs, ]v ) -#O Randomize( [Rs, ]M ) +############################################################################# ## -## <#GAPDoc Label="Randomize"> +## <#GAPDoc Label="MatObj_ExtractSubVector"> ## -## Randomize -## -## +## +## +## a vector object +## ## -## 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 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 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. +## 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 ]) +## ]]> ## ## ## <#/GAPDoc> ## -DeclareOperation( "Randomize", [ IsVectorObj and IsMutable ] ); -DeclareOperation( "Randomize", [ IsRandomSource, IsVectorObj and IsMutable ] ); -DeclareOperation( "Randomize", [ IsMatrixOrMatrixObj and IsMutable ] ); -DeclareOperation( "Randomize", [ IsRandomSource, IsMatrixOrMatrixObj and IsMutable ] ); +DeclareOperationKernel( "ExtractSubVector", + [ IsRowVectorOrVectorObj, IsList ], EXTRACT_SUB_VECTOR ); ############################################################################# @@ -1038,6 +1364,14 @@ DeclareOperationKernel( "CopySubVector", ## ## returns the Hamming weight of the vector object v, ## i.e., the number of nonzero entries in v. +##

+## 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> @@ -1056,6 +1390,14 @@ DeclareOperation( "WeightOfVector", [ IsVectorObj ] ); ## 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. +##

+## 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> @@ -1213,130 +1555,6 @@ DeclareOperationKernel( "[,]:=", [ IsMatrixOrMatrixObj, IsInt, IsInt, IsObject ] DeclareSynonym( "SetMatElm", ASS_MAT ); -############################################################################# -## -#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 CompanionMatrix( , ) @@ -1400,130 +1618,6 @@ DeclareOperation( "CompanionMatrix", [ IsUnivariatePolynomial, IsSemiring ] ); -############################################################################# -## -#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"> -## -## Matrix -## -## -## -## -## -## -## a matrix object -## -## 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 -## 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. -##

-## 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 -## and -## of the last argument -## are taken for the result. -##

-## 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. -##

-## 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 ]); - - ############################################################################ ## #A CompatibleVector( ) From 6059c94b03b45f9bde589c53f4e98c2e64932797 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 7 May 2026 09:53:15 +0100 Subject: [PATCH 38/52] resolving conflict --- lib/matobj2.gd | 89 -------------------------------------------------- 1 file changed, 89 deletions(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index c032d0e8da..cf2798a88c 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -1618,95 +1618,6 @@ DeclareOperation( "CompanionMatrix", [ IsUnivariatePolynomial, IsSemiring ] ); -############################################################################# -## -#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"> -## -## Matrix -## -## -## -## -## -## -## a matrix object -## -## 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 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, -## the first argument is a list or a matrix object -## that defines (together with ncols if applicable) the entries of -## the result, and 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 . -## -## -## <#/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 ]); - - ############################################################################ ## #A CompatibleVector( ) From fcf44fd633f47860a2f98f3f46051b5dedbc5376 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 7 May 2026 13:09:51 +0100 Subject: [PATCH 39/52] added examples for 26.13 and 26.14 --- lib/matobj.gi | 16 +- lib/matobj2.gd | 732 +++++++++++------- .../MatrixObj/ExtractSubMatrix.tst | 5 - 3 files changed, 463 insertions(+), 290 deletions(-) diff --git a/lib/matobj.gi b/lib/matobj.gi index ca1c152681..4b5c1f72a8 100644 --- a/lib/matobj.gi +++ b/lib/matobj.gi @@ -1151,9 +1151,17 @@ InstallMethod( MultVectorRight, ## [ [ 3, 0, 3 ], [ 0, 3, 0 ] ] ## [ [ 5, 0, 5 ], [ 0, 5, 0 ] ] ## [ [ 1/2, 0, 1/2 ], [ 0, 1/2, 0 ] ] -## gap> m3 := Matrix( [ [1,1], [0,1] ], m1 );; -## gap> Print( m3 * m1 ); -## NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 9, 11, 13 ], [ 6, 7, 8 ] ]) +## gap> m3 := Matrix( Integers, [ [1,1], [0,1] ] ); +## <2x2-matrix over Integers> +## 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 ] ] ## ]]> ## ## @@ -1436,7 +1444,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 diff --git a/lib/matobj2.gd b/lib/matobj2.gd index cf2798a88c..c4652e9152 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -899,7 +899,7 @@ DeclareOperation( "Unpack", [ IsVecOrMatObj ] ); ##

## v1 := Vector( Integers, [ 3, 5, 7, 9 ] );; -## gap> ChangedBaseDomain( v1, Rationals ); +## 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) ); @@ -1405,6 +1405,91 @@ DeclareOperation( "WeightOfVector", [ IsVectorObj ] ); DeclareOperation( "DistanceOfVectors", [ IsVectorObj, IsVectorObj ] ); +############################################################################# +## +#O MatElm( , , ) . . . . . . select an entry from a matrix +#O [ , ] . . . . . . . . . . select an entry from a matrix +## +## <#GAPDoc Label="MatObj_MatElm"> +## +## +## +## an entry of the matrix object +## +## +## 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> +## +DeclareOperationKernel( "[,]", [ IsMatrixOrMatrixObj, IS_INT, IS_INT ], ELM_MAT ); +DeclareSynonym( "MatElm", ELM_MAT ); + + +############################################################################# +## +#O SetMatElm( , , , ) . . . . set an entry in a matrix +#O [ , ]:= . . . . . . . . . set an entry in a matrix +## +## <#GAPDoc Label="MatObj_SetMatElm"> +## +## +## +## 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. +##

+## 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> +## +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 ExtractSubMatrix( , , ) @@ -1422,6 +1507,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> @@ -1472,6 +1566,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> @@ -1483,76 +1587,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 +## a plain list ## ## -## 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. +## 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. ##

-## If the global option check is set to false then -## need not perform consistency checks. +## 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> ## -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 ); +## This function is used for creating an isomorphic permutation group +## of a matrix group that consists of matrix objects. +## +## +## 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. +## +DeclareAttribute( "RowsOfMatrix", IsMatrixOrMatrixObj ); ############################################################################# @@ -1618,64 +1725,6 @@ DeclareOperation( "CompanionMatrix", [ IsUnivariatePolynomial, IsSemiring ] ); -############################################################################ -## -#A CompatibleVector( ) -## -## <#GAPDoc Label="CompatibleVector"> -## -## -## -## a vector object -## -## -## 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). -##

-## The idea is that there should be an efficient way to -## form the product vM. -## -## -## <#/GAPDoc> -## -DeclareOperation( "CompatibleVector", [ IsMatrixOrMatrixObj ] ); - - -############################################################################ -## -#A RowsOfMatrix( ) -## -## <#GAPDoc Label="RowsOfMatrix"> -## -## -## -## a plain list -## -## -## 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. -## -## -## <#/GAPDoc> -## -## This function is used for creating an isomorphic permutation group -## of a matrix group that consists of matrix objects. -## -## -## 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. -## -DeclareAttribute( "RowsOfMatrix", IsMatrixOrMatrixObj ); - - ############################################################################# ## #F DefaultVectorRepForBaseDomain( ) @@ -1692,7 +1741,6 @@ DeclareGlobalFunction( "DefaultMatrixRepForBaseDomain" ); ## Operations for Row List Matrix Objects ## - ############################################################################ ## #O [ ] @@ -1710,6 +1758,12 @@ DeclareGlobalFunction( "DefaultMatrixRepForBaseDomain" ); ## this operation returns the pos-th row of M. ##

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

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

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

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

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

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

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

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

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

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

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

## If the pos-th row existed in M then it is returned, ## otherwise nothing is returned. +##

+## m1 := Matrix( Integers, [ [1,1], [2,2], [3,3], [4,4], [5,5] ] );; +## gap> v1 := Remove( m1 );; Unpack( v1 ); +## [ 5, 5 ] +## gap> Unpack( m1 ); +## [ [ 1, 1 ], [ 2, 2 ], [ 3, 3 ], [ 4, 4 ] ] +## gap> Remove( m1, 2 );; Unpack( m1 ); +## [ [ 1, 1 ], [ 3, 3 ], [ 4, 4 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1914,6 +2018,13 @@ DeclareOperation( "Remove", [ IsRowListMatrix, IsPosInt ] ); ## values are equal, ## this operation appends the rows of M2 to the ## rows of M1. +##

+## m1 := Matrix( Integers, [ [3,4,5], [7,8,9] ] );; +## gap> m2 := Matrix( Integers, [ [1,0,1], [0,1,0] ] );; +## gap> Append( m1, m2 ); Unpack( m1 ); +## [ [ 3, 4, 5 ], [ 7, 8, 9 ], [ 1, 0, 1 ], [ 0, 1, 0 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -1959,6 +2070,10 @@ DeclareOperation( "Append", [ IsRowListMatrix, IsRowListMatrix ] ); ## (see ) of its rows, ## and the variant with two arguments returns the plain list of values ## of these rows under the function func. +##

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

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

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

+## m1 := Matrix( Integers, [ [2,3], [5,6], [8,9] ] );; +## gap> MultMatrixRow( m1, 2, -10 ); Unpack( m1 ); +## [ [ 2, 3 ], [ -50, -60 ], [ 8, 9 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -2174,12 +2147,20 @@ DeclareOperation( "MultMatrixRowRight", [ IsMatrixOrMatrixObj and IsMutable, IsI ## ## ##

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

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

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

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

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

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

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

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

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

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

-## is a synonym of . This was -## chosen because linear combinations of columns of matrices are usually written as -## A \cdot v^T = A \cdot [v_1, ... ,v_n]^T which multiplies scalars from the right. +## m1 := Matrix( Integers, [ [1,1,1], [2,2,2], [3,3,3] ] );; +## gap> AddMatrixColumns( m1, 1, 3, 10 ); Unpack( m1 ); +## [ [ 11, 1, 1 ], [ 22, 2, 2 ], [ 33, 3, 3 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -2303,6 +2302,12 @@ DeclareOperation( "AddMatrixColumnsLeft", [ IsMatrixOrMatrixObj and IsMutable, I ## the matrix M, or NrCols( M ) + 1 if the row is zero. ## If the optional argument from is given, the search starts after ## position from. +##

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

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

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

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

+## m1 := Matrix( Integers, [ [1,2,3,4,5], [6,7,8,9,10] ] );; +## gap> SwapMatrixColumns( m1, 2, 4 ); Unpack( m1 ); +## [ [ 1, 4, 3, 2, 5 ], [ 6, 9, 8, 7, 10 ] ] +## ]]> ## ## ## <#/GAPDoc> @@ -2407,7 +2424,8 @@ DeclareOperation( "AddMatrix", [ IsMatrixOrMatrixObj and IsMutable, IsMatrixOrMa ## gap> MultMatrixRight(mat1, -2); ## gap> mat1; ## [ [ -2, -4 ], [ -6, -8 ] ] -## gap> MultMatrix(mat1, -2); # Note that this is the same as calling MultMatrixLeft(mat1, -2) +## gap> MultMatrix(mat1, -2); +## gap> # Note that this is the same as calling MultMatrixLeft(mat1, -2) ## gap> mat1; ## [ [ 4, 8 ], [ 12, 16 ] ] ## gap> A := FreeAssociativeAlgebra(Rationals, 2); @@ -2430,3 +2448,155 @@ DeclareOperation( "AddMatrix", [ IsMatrixOrMatrixObj and IsMutable, IsMatrixOrMa DeclareOperation( "MultMatrixRight", [ IsMatrixOrMatrixObj and IsMutable, IsScalar ] ); DeclareOperation( "MultMatrixLeft", [ IsMatrixOrMatrixObj and IsMutable, IsScalar ] ); DeclareSynonym( "MultMatrix", MultMatrixLeft ); + + +############################################################################# +## +## IsEmptyMatrix( ) +## +## <#GAPDoc Label="MatObj_IsEmptyMatrix"> +## +## +## A boolean +## +## Is true if the matrix object M either has zero columns +## or zero rows, and false otherwise. +## In other words, a matrix object is empty if it has no entries. +## +## +## <#/GAPDoc> +## +DeclareProperty( "IsEmptyMatrix", IsMatrixOrMatrixObj ); + + +############################################################################# +## +## TODO: +## +## Do we REALLY want to support and document the following feature? +## If yes then it is intended as permanent, +## although it contradicts the intended use of matrix objects. +## +## Is this a feature with a generic solution, +## such that the implementors of new kinds of matrix objects need not +## care about it? +## If not then it will be very annoying to be forced to support something +## which will not be used at all as long as the code is used as intended. +## (In particular, the documentation claims on the one hand that it is not +## compulsory to provide a compatible vector object representation for one's +## matrix object implementation, but the ``row access'' will force one to +## provide one.) + +############################################################################ +# In the following sense matrices behave like lists: +############################################################################ + +DeclareOperation( "[]", [IsMatrixOrMatrixObj,IsPosInt] ); # , +# This is guaranteed to return a vector object that has the property +# that changing it changes th row (?) of the matrix ! +# A matrix which is not a row-lists internally has to create an intermediate object that refers to some +# row within it to allow the old GAP syntax M[i][j] for read and write +# access to work. Note that this will never be particularly efficient +# for matrices which are not row-lists. Efficient code will have to use MatElm and +# SetMatElm instead. + +# TODO: ... resp. it will use use M[i,j] +# TODO: provide a default method which creates a proxy object for the given row +# and translates accesses to it to corresponding MatElm / SetMatElm calls; +# creating such a proxy object prints an InfoWarning; +# but for the method for plist matrices, no warning is shown, as it is efficient +# anyway + +# TODO: maybe also add GetRow(mat, i) and GetColumn(mat, i) ??? +# these return IsVectorObj objects. +# these again must be objects which are "linked" to the original matrix, as above... +# TODO: perhaps also have ExtractRow(mat, i) and ExtractColumn(mat, i) + + +############################################################################# +## +## Backwards compatibility +## +## We have to declare the operations/synonyms because otherwise +## the method installations in some packages may not work. +## We should remove them as soon as they are not used anymore. +## + +############################################################################# +## +#C IsRowVectorObj( ) +## +## Existing code which uses this name (most notably, the cvec package) +## should be supported for some time. +## +DeclareSynonym( "IsRowVectorObj", IsVectorObj ); + + +############################################################################# +## +#A DimensionsMat( ) +## +## only for backwards compatibility with existing code: +## -> [ NrRows( ), NrCols( ) ] +## +DeclareAttribute( "DimensionsMat", IsMatrixOrMatrixObj ); + + +############################################################################# +## +#A Length( ) +## +## They had been used in older versions. +## +DeclareAttribute( "Length", IsMatrixOrMatrixObj ); + + +############################################################################# +## +#O NewCompanionMatrix( , , ) +## +## This operation is intended for the installation of tag based methods for +## 'CompanionMatrix', such that 'CompanionMatrix' admits method dispatch +## based on . +## +## (Currently 'NewCompanionMatrix' is undocumented. +## Perhaps we can simply declare 'CompanionMatrix' itself as a tag based +## operation for the given requirement. +## This would work also for `DiagonalMatrix`, `RandomMatrix`, +## `ReflectionMatrix`, etc. +## We could even get rid of `NewMatrix`, `NewZeroMatrix`, +## `NewIdentityMatrix`, by declaring `Matrix`, `ZeroMatrix`, +## `IdentityMatrix` as tag based operations for the requirements in +## question, except that the ordering of the arguments for the four +## argument versions of `NewMatrix` and `Matrix` does not fit.) +## +DeclareTagBasedOperation( "NewCompanionMatrix", + [ IsOperation, IsUnivariatePolynomial, IsSemiring ] ); + + +############################################################################# +## +#O NewRowVector( ... ) +## +DeclareSynonym( "NewRowVector", NewVector ); + + +############################################################################# +## +#O Randomize( ... ) +## +## for backwards compatibility with the cvec package +## +DeclareOperation( "Randomize", [ IsVectorObj and IsMutable, IsRandomSource ] ); +DeclareOperation( "Randomize", [ IsMatrixOrMatrixObj and IsMutable, IsRandomSource ] ); + + +############################################################################# +## +#O [ , ] +#O [ , ]:= +## +DeclareOperation( "[]", [ IsMatrixOrMatrixObj, IsPosInt, IsPosInt ] ); +DeclareOperation( "[]:=", [ IsMatrixOrMatrixObj, IsPosInt, IsPosInt, IsObject ] ); + + diff --git a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst index b73e17a196..65ad5df236 100644 --- a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst +++ b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst @@ -1,10 +1,8 @@ gap> START_TEST("ExtractSubMatrix.tst"); - gap> IsBoundGlobal("EXTRACT_SUB_MATRIX"); true gap> EXTRACT_SUB_MATRIX = ExtractSubMatrix; true - gap> m1 := [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] gap> ExtractSubMatrix( m1, [ 2, 1 ], [ 3, 1 ] ); @@ -12,7 +10,6 @@ gap> ExtractSubMatrix( m1, [ 2, 1 ], [ 3, 1 ] ); gap> m2 := IdentityMatrix( Integers, 4 );; gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); [ [ 0, 1 ], [ 1, 0 ] ] - # IsGF2MatrixRep gap> m1 := IdentityMatrix( GF(2), 100 ); @@ -20,7 +17,6 @@ gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); gap> IsOne(m2); true - # Is8BitMatrixRep gap> m1 := IdentityMatrix( GF(3), 100 ); < mutable compressed matrix 100x100 over GF(3) > @@ -28,5 +24,4 @@ gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); < mutable compressed matrix 20x20 over GF(3) > gap> IsOne(m2); true - gap> STOP_TEST("ExtractSubMatrix.tst"); From ca03c6d9f91a451aead2fea6593e0cb63ff5ab96 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 7 May 2026 14:55:59 +0100 Subject: [PATCH 40/52] added examples for 26.13 and 26.14 --- tst/testinstall/MatrixObj/ExtractSubMatrix.tst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst index 65ad5df236..3f17d9a8d2 100644 --- a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst +++ b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst @@ -10,6 +10,7 @@ gap> ExtractSubMatrix( m1, [ 2, 1 ], [ 3, 1 ] ); gap> m2 := IdentityMatrix( Integers, 4 );; gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); [ [ 0, 1 ], [ 1, 0 ] ] + # IsGF2MatrixRep gap> m1 := IdentityMatrix( GF(2), 100 ); @@ -17,6 +18,7 @@ gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); gap> IsOne(m2); true + # Is8BitMatrixRep gap> m1 := IdentityMatrix( GF(3), 100 ); < mutable compressed matrix 100x100 over GF(3) > From 0ee75556329ec5f751295933d50970a182399d3e Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 7 May 2026 15:18:57 +0100 Subject: [PATCH 41/52] added examples for 26.13 and 26.14 --- lib/matobj.gi | 2 +- lib/matobj2.gd | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/matobj.gi b/lib/matobj.gi index 4b5c1f72a8..a87274527e 100644 --- a/lib/matobj.gi +++ b/lib/matobj.gi @@ -1159,7 +1159,7 @@ InstallMethod( MultVectorRight, ## NewMatrix(IsPlistMatrixRep,Integers,2,[ [ 7, 12 ], [ 4, 7 ] ]) ## gap> Unpack( m3 * m4 ); ## [ [ 7, 12 ], [ 4, 7 ] ] -## gap> Unpack( m3^6 ); Unpack( m4^-1 ); +## gap> Unpack( m3^6 ); Unpack( m4^-1 ); ## [ [ 1, 6 ], [ 0, 1 ] ] ## [ [ 7, -5 ], [ -4, 3 ] ] ## ]]> diff --git a/lib/matobj2.gd b/lib/matobj2.gd index c4652e9152..58b77e14d7 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -652,7 +652,6 @@ DeclareOperation( "Matrix", [ IsList ]); ## gap> z5 := ZeroMatrix( IsGF2MatrixRep, GF(2), 2, 5 );; Display( z5 ); ## . . . . . ## . . . . . -## ]> ## ]]> ## ## @@ -1611,7 +1610,7 @@ DeclareOperationKernel( "CopySubMatrix", ## gap> 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 ); +## gap> v1[1] := -1;; v1[3] := -1;; Unpack( v1 ); ## [ -1, 0, -1 ] ## gap> Print( v1 * m1 ); ## NewVector(IsPlistVectorRep,Integers,[ -10, -12 ]) @@ -2101,7 +2100,7 @@ DeclareOperation( "ListOp", [ IsRowListMatrix, IsFunction ] ); ## Multiplies the i-th row of the mutable matrix mat ## with the scalar elm from the left in-place. ##

-## is a synonym of . +## is a synonym of . ## This was chosen because linear combinations of rows of matrices are usually ## written as v \cdot A = [v_1, ... ,v_n] \cdot A ## which multiplies scalars from the left. From c28a132db76f0215a505fc135f5736bba651928f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 8 May 2026 11:34:48 +0100 Subject: [PATCH 42/52] Makefile.rules: add cleanall target, improve cleaning overall (#6378) --- Makefile.rules | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile.rules b/Makefile.rules index 1aec140fdd..74d62a9ca0 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -584,9 +584,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 +980,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 +1012,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 +1054,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} From 4bcb53b0eb7e143ae040dcaa9c9423690b02696c Mon Sep 17 00:00:00 2001 From: lhsoicher Date: Fri, 8 May 2026 13:01:14 +0100 Subject: [PATCH 43/52] Improve documentation of several action functions (#6370) Improve the documentation for the action functions - OnTuplesSets - OnTuplesTuples, - OnSetsTuples, - OnSetsSets, - OnSetsDisjointSets. --- lib/oprt.gd | 61 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/lib/oprt.gd b/lib/oprt.gd index c369951114..20bae46045 100644 --- a/lib/oprt.gd +++ b/lib/oprt.gd @@ -2743,11 +2743,16 @@ DeclareGlobalFunction("OnLines"); ## ## ## implements the action on sets of sets. -## For the special case that the sets are pairwise disjoint, +## set must be a proper set whose entries are again proper sets +## (see ). +##

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

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

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

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

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

+## returns the list of +## the corresponding images obtained by applying the action function +## to x and g, +## for each entry x of the list tup. ## OnTuplesTuples( [ [ 2, 3 ], [ 3, 4 ] ], (1,2,3) ); ## [ [ 3, 1 ], [ 1, 4 ] ] From ce84021e5802b82915e5e047638bf726df56cd56 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 22 Apr 2026 02:25:33 +0200 Subject: [PATCH 44/52] Faster {Copy,Extract}Sub{Matrix,Vector} for plist matrices/vectors (#6329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... by avoiding some method dispatch, providing optimized methods using `{...}` syntax, and turning ExtractSubVector, CopySubVector, ExtractSubMatrix, and CopySubMatrix into kernel ops. Then run some benchmarks via `benchmark/matobj/bench-submat.g` and the new `benchmark/matobj/bench-subvec.g`. Before: +----------------------------------------------------------------+ | Testing submatrix extraction for integer matrix: list of lists | +----------------------------------------------------------------+ Testing m{}{}: 129 µs per iteration; 7749 iterations per second; (200 iterations) Testing ExtractSubMatrix: 720 µs per iteration; 1388 iterations per second; (200 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 342 µs per iteration; 2921 iterations per second; (200 iterations) Testing CopySubMatrix: 1032 µs per iteration; 969 iterations per second; (200 iterations) +------------------------------------------------+ | Testing submatrix extraction for GF(2) rowlist | +------------------------------------------------+ Testing m{}{}: 167 µs per iteration; 5999 iterations per second; (200 iterations) Testing ExtractSubMatrix: 3288 µs per iteration; 304 iterations per second; (92 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 1992 µs per iteration; 502 iterations per second; (151 iterations) Testing CopySubMatrix: 2606 µs per iteration; 384 iterations per second; (116 iterations) +-------------------------------------------------------------+ | Testing subvector extraction for integer vector: plain list | +-------------------------------------------------------------+ Testing x{}:=v{}: 393 µs per iteration; 2542 iterations per second; (200 iterations) Testing CopySubVector: 2324 µs per iteration; 430 iterations per second; (130 iterations) +---------------------------------------------------+ | Testing subvector extraction for GF(2) row vector | +---------------------------------------------------+ Testing x{}:=v{}: 441 µs per iteration; 2266 iterations per second; (200 iterations) Testing CopySubVector: 2458 µs per iteration; 407 iterations per second; (123 iterations) After: +----------------------------------------------------------------+ | Testing submatrix extraction for integer matrix: list of lists | +----------------------------------------------------------------+ Testing m{}{}: 136 µs per iteration; 7355 iterations per second; (200 iterations) Testing ExtractSubMatrix: 140 µs per iteration; 7135 iterations per second; (200 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 301 µs per iteration; 3319 iterations per second; (200 iterations) Testing CopySubMatrix: 299 µs per iteration; 3347 iterations per second; (200 iterations) +------------------------------------------------+ | Testing submatrix extraction for GF(2) rowlist | +------------------------------------------------+ Testing m{}{}: 154 µs per iteration; 6490 iterations per second; (200 iterations) Testing ExtractSubMatrix: 146 µs per iteration; 6854 iterations per second; (200 iterations) ...now testing submatrix copying... Testing m{}{}:=n{}{}: 1895 µs per iteration; 528 iterations per second; (159 iterations) Testing CopySubMatrix: 1935 µs per iteration; 517 iterations per second; (156 iterations) +-------------------------------------------------------------+ | Testing subvector extraction for integer vector: plain list | +-------------------------------------------------------------+ Testing x{}:=v{}: 428 µs per iteration; 2336 iterations per second; (200 iterations) Testing CopySubVector: 453 µs per iteration; 2209 iterations per second; (200 iterations) +---------------------------------------------------+ | Testing subvector extraction for GF(2) row vector | +---------------------------------------------------+ Testing x{}:=v{}: 427 µs per iteration; 2344 iterations per second; (200 iterations) Testing CopySubVector: 460 µs per iteration; 2172 iterations per second; (200 iterations) So overall the Copy/Extract methods are now more or less on par with the code using `{...}` syntax. But actually this `ExtractSubMatrix` for a GF(2) rowlist is now *faster* than the optimized one for a compressed GF(2) matrix: +----------------------------------------------------------+ | Testing submatrix extraction for GF(2) compressed matrix | +----------------------------------------------------------+ Testing m{}{}: 1057 µs per iteration; 946 iterations per second; (200 iterations) Testing ExtractSubMatrix: 1618 µs per iteration; 618 iterations per second; (186 iterations) A substantial part of that is due to the the `ExtractSubMatrix` method for `IsGF2MatrixRep` calling `ConvertToMatrixRepNC(mm,2)`; after removing that, it went down from 1618 to 392 µs (which is still worse). --- AI assistance: Codex implemented the kernel plumbing, method cleanup, and test updates. It also created `benchmark/matobj/bench-subvec.g`. Co-authored-by: Codex --- tst/testinstall/MatrixObj/ExtractSubMatrix.tst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst index 3f17d9a8d2..7f80e2706b 100644 --- a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst +++ b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst @@ -26,4 +26,8 @@ gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); < mutable compressed matrix 20x20 over GF(3) > gap> IsOne(m2); true + +gap> m2 := IdentityMatrix( Integers, 4 );; +gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); +[ [ 0, 1 ], [ 1, 0 ] ] gap> STOP_TEST("ExtractSubMatrix.tst"); From 4ba4b8ec6995f955242bf073899ffc357eac2d6f Mon Sep 17 00:00:00 2001 From: cdwensley Date: Thu, 30 Apr 2026 15:04:45 +0100 Subject: [PATCH 45/52] examples for Matrix --- lib/matobj2.gd | 243 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 58b77e14d7..6ca0cc1530 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -1301,6 +1301,70 @@ DeclareGlobalFunction( "ConcatenationOfVectors" ); ## gap> 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 +## 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( 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. +##

+## 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 ); +## ## ]]> ## ## @@ -1724,6 +1788,185 @@ DeclareOperation( "CompanionMatrix", [ IsUnivariatePolynomial, IsSemiring ] ); +############################################################################# +## +#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"> +## +## Matrix +## +## +## +## +## +## +## a matrix object +## +## 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 +## 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. +##

+## 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 +## and +## of the last argument +## are taken for the result. +##

+## 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. +##

+## 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> Print( Matrix( [-9..-4], 3, m1 ) ); +NewMatrix(IsPlistMatrixRep,Integers,3,[ [ -9, -8, -7 ], [ -6, -5, -4 ] ]) +gap> m5 := Matrix( [ [0,1,2], [7,8,9] ] );; Print( m5 ); +NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 0, 1, 2 ], [ 7, 8, 9 ] ]) +gap> m6 := Matrix( IsGF2MatrixRep, GF(2), [[1,0,1],[0,1,0]]*Z(2)^0 );; +gap> Display( m6 ); + 1 . 1 + . 1 . +gap> m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 ); + +## ]]> +## +## +## <#/GAPDoc> +## +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 ]); + + +############################################################################ +## +#A CompatibleVector( ) +## +## <#GAPDoc Label="CompatibleVector"> +## +## +## +## a vector object +## +## +## 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). +##

+## The idea is that there should be an efficient way to +## form the product vM. +## +## +## <#/GAPDoc> +## +DeclareOperation( "CompatibleVector", [ IsMatrixOrMatrixObj ] ); + + +############################################################################ +## +#A RowsOfMatrix( ) +## +## <#GAPDoc Label="RowsOfMatrix"> +## +## +## +## a plain list +## +## +## 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. +## +## +## <#/GAPDoc> +## +## This function is used for creating an isomorphic permutation group +## of a matrix group that consists of matrix objects. +## +## +## 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. +## +DeclareAttribute( "RowsOfMatrix", IsMatrixOrMatrixObj ); + + ############################################################################# ## #F DefaultVectorRepForBaseDomain( ) From 384ad09741ca4680b920f9c7ec103611d0251e9d Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 8 May 2026 17:32:19 +0100 Subject: [PATCH 46/52] very minor change --- lib/matobj.gi | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/matobj.gi b/lib/matobj.gi index a87274527e..58e4184e6d 100644 --- a/lib/matobj.gi +++ b/lib/matobj.gi @@ -1151,15 +1151,12 @@ InstallMethod( MultVectorRight, ## [ [ 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] ] ); -## <2x2-matrix over Integers> ## 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 ); +## gap> Unpack( m3 * m4 ); Unpack( m3^6 ); Unpack( m4^-1 ); ## [ [ 7, 12 ], [ 4, 7 ] ] -## gap> Unpack( m3^6 ); Unpack( m4^-1 ); ## [ [ 1, 6 ], [ 0, 1 ] ] ## [ [ 7, -5 ], [ -4, 3 ] ] ## ]]> From ed61025eafde453a447b9e957b8195bf944d85db Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 8 May 2026 18:02:53 +0100 Subject: [PATCH 47/52] fixed problem which arose during rebase --- lib/matobj2.gd | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 6ca0cc1530..ddc2983e25 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -1870,27 +1870,27 @@ DeclareOperation( "CompanionMatrix", ## [ 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 ); - +## 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 ); +## ## ]]> ## ## From 6cce307af6fea1f8378f2dfa57bf9aabeff1d162 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 8 May 2026 18:14:35 +0100 Subject: [PATCH 48/52] fixed another rebase problem --- lib/matobj2.gd | 121 ------------------------------------------------- 1 file changed, 121 deletions(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index ddc2983e25..2e5049e7ce 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -1788,127 +1788,6 @@ DeclareOperation( "CompanionMatrix", [ IsUnivariatePolynomial, IsSemiring ] ); -############################################################################# -## -#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"> -## -## Matrix -## -## -## -## -## -## -## a matrix object -## -## 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 -## 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. -##

-## 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 -## and -## of the last argument -## are taken for the result. -##

-## 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. -##

-## 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> Print( Matrix( [-9..-4], 3, m1 ) ); -## NewMatrix(IsPlistMatrixRep,Integers,3,[ [ -9, -8, -7 ], [ -6, -5, -4 ] ]) -## gap> m5 := Matrix( [ [0,1,2], [7,8,9] ] );; Print( m5 ); -## NewMatrix(IsPlistMatrixRep,Rationals,3,[ [ 0, 1, 2 ], [ 7, 8, 9 ] ]) -## gap> m6 := Matrix( IsGF2MatrixRep, GF(2), [[1,0,1],[0,1,0]]*Z(2)^0 );; -## gap> Display( m6 ); -## 1 . 1 -## . 1 . -## gap> m7 := Matrix( IsZmodnZMatrixRep, ZmodnZ(8), [1..6], 3 ); -## -## ]]> -## -## -## <#/GAPDoc> -## -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 ]); - - ############################################################################ ## #A CompatibleVector( ) From 14d9cfe795096c93ea9727f4a5ec7476fb255add Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 8 May 2026 18:23:41 +0100 Subject: [PATCH 49/52] fixed another rebase problem --- lib/matobj2.gd | 58 -------------------------------------------------- 1 file changed, 58 deletions(-) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index 2e5049e7ce..a6b3a0db31 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -1788,64 +1788,6 @@ DeclareOperation( "CompanionMatrix", [ IsUnivariatePolynomial, IsSemiring ] ); -############################################################################ -## -#A CompatibleVector( ) -## -## <#GAPDoc Label="CompatibleVector"> -## -## -## -## a vector object -## -## -## 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). -##

-## The idea is that there should be an efficient way to -## form the product vM. -## -## -## <#/GAPDoc> -## -DeclareOperation( "CompatibleVector", [ IsMatrixOrMatrixObj ] ); - - -############################################################################ -## -#A RowsOfMatrix( ) -## -## <#GAPDoc Label="RowsOfMatrix"> -## -## -## -## a plain list -## -## -## 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. -## -## -## <#/GAPDoc> -## -## This function is used for creating an isomorphic permutation group -## of a matrix group that consists of matrix objects. -## -## -## 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. -## -DeclareAttribute( "RowsOfMatrix", IsMatrixOrMatrixObj ); - - ############################################################################# ## #F DefaultVectorRepForBaseDomain( ) From 7b0f3afbd78991b2068beaf6f789807d549b654d Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 8 May 2026 19:07:28 +0100 Subject: [PATCH 50/52] remove blank lines in test file --- tst/testinstall/MatrixObj/ExtractSubMatrix.tst | 3 --- 1 file changed, 3 deletions(-) diff --git a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst index 7f80e2706b..897430ac91 100644 --- a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst +++ b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst @@ -10,7 +10,6 @@ gap> ExtractSubMatrix( m1, [ 2, 1 ], [ 3, 1 ] ); gap> m2 := IdentityMatrix( Integers, 4 );; gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); [ [ 0, 1 ], [ 1, 0 ] ] - # IsGF2MatrixRep gap> m1 := IdentityMatrix( GF(2), 100 ); @@ -18,7 +17,6 @@ gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); gap> IsOne(m2); true - # Is8BitMatrixRep gap> m1 := IdentityMatrix( GF(3), 100 ); < mutable compressed matrix 100x100 over GF(3) > @@ -26,7 +24,6 @@ gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); < mutable compressed matrix 20x20 over GF(3) > gap> IsOne(m2); true - gap> m2 := IdentityMatrix( Integers, 4 );; gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); [ [ 0, 1 ], [ 1, 0 ] ] From c637dcbaefdae50195b2b34b1ae8ef625f6d327e Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 8 May 2026 20:08:28 +0100 Subject: [PATCH 51/52] finding it hard to fix ExtractSubMatrix.tst --- tst/testinstall/MatrixObj/ExtractSubMatrix.tst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst index 897430ac91..445c4d82e8 100644 --- a/tst/testinstall/MatrixObj/ExtractSubMatrix.tst +++ b/tst/testinstall/MatrixObj/ExtractSubMatrix.tst @@ -10,6 +10,7 @@ gap> ExtractSubMatrix( m1, [ 2, 1 ], [ 3, 1 ] ); gap> m2 := IdentityMatrix( Integers, 4 );; gap> Unpack( ExtractSubMatrix( m2, [ 2, 4 ], [ 4, 2 ] ) ); [ [ 0, 1 ], [ 1, 0 ] ] + # IsGF2MatrixRep gap> m1 := IdentityMatrix( GF(2), 100 ); @@ -17,6 +18,7 @@ gap> m2 := ExtractSubMatrix( m1, [ 11..30 ], [ 11..30 ] ); gap> IsOne(m2); true + # Is8BitMatrixRep gap> m1 := IdentityMatrix( GF(3), 100 ); < mutable compressed matrix 100x100 over GF(3) > From 550f275a23d8e7f9c9fa005443f5db8042757da1 Mon Sep 17 00:00:00 2001 From: cdwensley Date: Fri, 8 May 2026 20:21:39 +0100 Subject: [PATCH 52/52] fix missing end of example --- lib/matobj2.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/matobj2.gd b/lib/matobj2.gd index a6b3a0db31..6a153401e2 100644 --- a/lib/matobj2.gd +++ b/lib/matobj2.gd @@ -1301,6 +1301,8 @@ DeclareGlobalFunction( "ConcatenationOfVectors" ); ## gap> 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 ## that defines the entries of the result,