---
title: "Handbook of Magma Functions, Part IV: Matrices and Linear Algebra"
version: "2.30-1"
canonical: "https://docs.magma-maths.org/MatricesLinearAlgebra/index-matrices-linear-algebra.html"
---

# Matrices and Linear Algebra

- [Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/index-matrices.md): Creating matrices over rings and fields.
- [Sparse Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/index-sparse-matrices.md): Sparse matrix creation, access, and entries.
- [Vector Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/index-vector-spaces.md): Bases, subspaces, quotients, and inner products.
- [Polar Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/index-polar-spaces.md): Reflexive sesquilinear and quadratic forms, and polar space structure.

<a id="mat"></a>
<a id="chapmat"></a>
## Matrices

- [Introduction](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/introduction.md)
- [Creation of Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md)
  - [General Matrix Construction](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#general-matrix-construction)
    - [`Matrix(R, m, n, Q): Rng, RngIntElt, RngIntElt, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-rng-rngintelt-rngintelt-rngelt)
    - [`Matrix(R, m, n, Q): Rng, RngIntElt, RngIntElt, [ <RngIntElt, RngIntElt, RngElt> ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-rng-rngintelt-rngintelt-rngintelt-rngintelt-rngelt)
    - [`Matrix(R, m, n, Q): Rng, RngIntElt, RngIntElt, [ [ RngElt ] ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-rng-rngintelt-rngintelt-rngelt-2)
    - [Example: Creating Matrices with Matrix](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#example-ex-79e602)
  - [Shortcuts](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#shortcuts)
    - [`Matrix(m, n, Q): RngIntElt, RngIntElt, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-rngintelt-rngintelt-rngelt)
    - [`Matrix(m, n, Q): RngIntElt, RngIntElt, [ [ RngElt ] ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-rngintelt-rngintelt-rngelt-2)
    - [`Matrix(Q): [ Mtrx ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-mtrx)
    - [`Matrix(R, n, Q): Rng, RngIntElt, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-rng-rngintelt-rngelt)
    - [`Matrix(n, Q): RngIntElt, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-rngintelt-rngelt)
    - [`Matrix(Q): [ [ RngElt ] ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-rngelt)
    - [`Matrix(R, Q): Rng, [ [ RngElt ] ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-rng-rngelt)
    - [Example: Matrix Construction Shortcuts](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#example-ex-cb789b)
  - [Construction of Structured Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#construction-of-structured-matrices)
    - [`ZeroMatrix(R, m, n): Rng, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-zeromatrix-rng-rngintelt-rngintelt)
    - [`IdentityMatrix(R, n): Rng, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-identitymatrix-rng-rngintelt)
    - [`ScalarMatrix(n, s): RngIntElt, RngElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-scalarmatrix-rngintelt-rngelt)
    - [`ScalarMatrix(R, n, s): Rng, RngIntElt, RngElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-scalarmatrix-rng-rngintelt-rngelt)
    - [`DiagonalMatrix(R, n, Q): Rng, RngIntElt, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-diagonalmatrix-rng-rngintelt-rngelt)
    - [`DiagonalMatrix(R, Q): Rng, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-diagonalmatrix-rng-rngelt)
    - [`DiagonalMatrix(Q): [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-diagonalmatrix-rngelt)
    - [`Matrix(A): Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-matrix-mtrx-2)
    - [`LowerTriangularMatrix(Q): [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-lowertriangularmatrix-rngelt)
    - [`LowerTriangularMatrix(R, Q): Rng, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-lowertriangularmatrix-rng-rngelt)
    - [`UpperTriangularMatrix(Q): [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-uppertriangularmatrix-rngelt)
    - [`UpperTriangularMatrix(R, Q): Rng, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-uppertriangularmatrix-rng-rngelt)
    - [`SymmetricMatrix(Q): [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-symmetricmatrix-rngelt)
    - [`SymmetricMatrix(R, Q): Rng, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-symmetricmatrix-rng-rngelt)
    - [`AntisymmetricMatrix(Q): [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-antisymmetricmatrix-rngelt)
    - [`AntisymmetricMatrix(R, Q): Rng, [ RngElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-antisymmetricmatrix-rng-rngelt)
    - [`PermutationMatrix(R, Q): Rng, [ RngIntElt ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-permutationmatrix-rng-rngintelt)
    - [`PermutationMatrix(R, x): Rng, GrpPermElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-permutationmatrix-rng-grppermelt)
    - [Example: Scalar and Structured Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#example-ex-c66a52)
  - [Construction of Random Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#construction-of-random-matrices)
    - [`RandomMatrix(R, m, n): Rng, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-randommatrix-rng-rngintelt-rngintelt)
    - [`RandomUnimodularMatrix(n, M): RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-randomunimodularmatrix-rngintelt-rngintelt)
    - [`RandomSLnZ(n, k, l): RngIntElt, RngIntElt, RngIntElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-randomslnz-rngintelt-rngintelt-rngintelt)
    - [`RandomGLnZ(n, k, l): RngIntElt, RngIntElt, RngIntElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-randomglnz-rngintelt-rngintelt-rngintelt)
    - [`RandomSymplecticMatrix(g, m): RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-randomsymplecticmatrix-rngintelt-rngintelt)
    - [`RandomSymmetricMatrix(R, n): Rng, RngIntElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-randomsymmetricmatrix-rng-rngintelt)
    - [`RandomSymmetricMatrix(R, n, M): RngOrd, RngIntElt, RngIntElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-randomsymmetricmatrix-rngord-rngintelt-rngintelt)
    - [`RandomPositiveDefiniteSymmetricMatrix(n, M): RngIntElt, RngIntElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-randompositivedefinitesymmetricmatrix-rngintelt-rngintelt)
  - [Creating Vectors](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#creating-vectors)
    - [`Vector(n, Q): RngIntElt, [ RngElt ] → ModTupRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-vector-rngintelt-rngelt)
    - [`Vector(Q): [ RngElt ] → ModTupRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-vector-rngelt)
    - [`Vector(R, n, Q): Rng, RngIntElt, [ RngElt ] → ModTupRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-vector-rng-rngintelt-rngelt)
    - [`Vector(R, Q): Rng, [ RngElt ] → ModTupRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/creation.md#function-vector-rng-rngelt)
- [Elementary Properties](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md)
  - [`NumberOfRows(A): Mtrx → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-numberofrows-mtrx)
  - [`Nrows(A): Mtrx → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-nrows-mtrx)
  - [`NumberOfColumns(A): Mtrx → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-numberofcolumns-mtrx)
  - [`Ncols(A): Mtrx → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-ncols-mtrx)
  - [`NumberOfNonZeroEntries(A): Mtrx → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-numberofnonzeroentries-mtrx)
  - [`NNZEntries(A): Mtrx → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-nnzentries-mtrx)
  - [`Density(A): Mtrx → FldRe`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-density-mtrx)
  - [`BaseRing(A): Mtrx → Rng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-basering-mtrx)
  - [`CoefficientRing(A): Mtrx → Rng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-coefficientring-mtrx)
  - [`ElementToSequence(A): Mtrx → [ RngElt ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-elementtosequence-mtrx)
  - [`Eltseq(A): Mtrx → [ RngElt ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-eltseq-mtrx)
  - [`RowSequence(A): Mtrx → [ [RngElt] ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/access.md#function-rowsequence-mtrx)
- [Accessing or Modifying Entries](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md)
  - [Indexing](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#indexing)
    - [`A[i]: Mtrx, RngIntElt → ModTupRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#indexed-indexed-a-mtrx-rngintelt-modtuprngelt)
    - [`A[i, j]: Mtrx, RngIntElt, RngIntElt → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#indexed-indexed-a-mtrx-rngintelt-rngintelt-rngelt)
    - [`A[Q]: Mtrx, [ RngIntElt ] → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#indexed-indexed-a-mtrx-rngintelt-rngelt)
    - [`A[i .. j]: Mtrx, RngIntElt, RngIntElt → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#indexed-indexed-a-mtrx-rngintelt-rngintelt-rngelt-2)
    - [`A[i] := v: Mtrx, RngIntElt, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#literal-literal-a-i-v-mtrx-rngintelt-mtrx)
    - [`A[i, j] := x: Mtrx, RngIntElt, RngIntElt, RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#literal-literal-a-i-j-x-mtrx-rngintelt-rngintelt-rngelt)
    - [Example: Accessing Matrix Entries](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#example-ex-e9c35f)
  - [Extracting and Inserting Blocks](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#extracting-and-inserting-blocks)
    - [`Submatrix(A, i, j, p, q): Mtrx, RngIntElt, RngIntElt, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-submatrix-mtrx-rngintelt-rngintelt-rngintelt-rngintelt)
    - [`ExtractBlock(A, i, j, p, q): Mtrx, RngIntElt, RngIntElt, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-extractblock-mtrx-rngintelt-rngintelt-rngintelt-rngintelt)
    - [`SubmatrixRange(A, i, j, r, s): Mtrx, RngIntElt, RngIntElt, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-submatrixrange-mtrx-rngintelt-rngintelt-rngintelt-rngintelt)
    - [`ExtractBlockRange(A, i, j, r, s): Mtrx, RngIntElt, RngIntElt, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-extractblockrange-mtrx-rngintelt-rngintelt-rngintelt-rngintelt)
    - [`Submatrix(A, I, J): Mtrx, [RngIntElt], [RngIntElt] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-submatrix-mtrx-rngintelt-rngintelt)
    - [`InsertBlock(A, B, i, j): Mtrx, Mtrx, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-insertblock-mtrx-mtrx-rngintelt-rngintelt)
    - [`InsertBlock(~A, B, i, j): Mtrx, Mtrx, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-insertblock-mtrx-mtrx-rngintelt-rngintelt-ref)
    - [`RowSubmatrix(A, i, k): Mtrx, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-rowsubmatrix-mtrx-rngintelt-rngintelt)
    - [`RowSubmatrix(A, i): Mtrx, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-rowsubmatrix-mtrx-rngintelt)
    - [`RowSubmatrixRange(A, i, j): Mtrx, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-rowsubmatrixrange-mtrx-rngintelt-rngintelt)
    - [`ColumnSubmatrix(A, i, k): Mtrx, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-columnsubmatrix-mtrx-rngintelt-rngintelt)
    - [`ColumnSubmatrix(A, i): Mtrx, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-columnsubmatrix-mtrx-rngintelt)
    - [`ColumnSubmatrixRange(A, i, j): Mtrx, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-columnsubmatrixrange-mtrx-rngintelt-rngintelt)
    - [Example: Extracting Submatrices](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#example-ex-0ed08c)
  - [Row and Column Operations](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#row-and-column-operations)
    - [`SwapRows(A, i, j): Mtrx, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-swaprows-mtrx-rngintelt-rngintelt)
    - [`SwapRows(~A, i, j): Mtrx, RngIntElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-swaprows-mtrx-rngintelt-rngintelt-ref)
    - [`SwapColumns(A, i, j): Mtrx, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-swapcolumns-mtrx-rngintelt-rngintelt)
    - [`SwapColumns(~A, i, j): Mtrx, RngIntElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-swapcolumns-mtrx-rngintelt-rngintelt-ref)
    - [`ReverseRows(A): Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-reverserows-mtrx)
    - [`ReverseRows(~A): Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-reverserows-mtrx-ref)
    - [`ReverseColumns(A): Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-reversecolumns-mtrx)
    - [`ReverseColumns(~A): Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-reversecolumns-mtrx-ref)
    - [`AddRow(A, c, i, j): Mtrx, RngElt, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-addrow-mtrx-rngelt-rngintelt-rngintelt)
    - [`AddRow(~A, c, i, j): Mtrx, RngElt, RngIntElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-addrow-mtrx-rngelt-rngintelt-rngintelt-ref)
    - [`AddColumn(A, c, i, j): Mtrx, RngElt, RngIntElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-addcolumn-mtrx-rngelt-rngintelt-rngintelt)
    - [`AddColumn(~A, c, i, j): Mtrx, RngElt, RngIntElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-addcolumn-mtrx-rngelt-rngintelt-rngintelt-ref)
    - [`MultiplyRow(A, c, i): Mtrx, RngElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-multiplyrow-mtrx-rngelt-rngintelt)
    - [`MultiplyRow(~A, c, i): Mtrx, RngElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-multiplyrow-mtrx-rngelt-rngintelt-ref)
    - [`MultiplyColumn(A, c, i): Mtrx, RngElt, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-multiplycolumn-mtrx-rngelt-rngintelt)
    - [`MultiplyColumn(~A, c, i): Mtrx, RngElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-multiplycolumn-mtrx-rngelt-rngintelt-ref)
    - [`RemoveRow(A, i): Mtrx, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-removerow-mtrx-rngintelt)
    - [`RemoveRow(~A, i): Mtrx, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-removerow-mtrx-rngintelt-ref)
    - [`RemoveColumn(A, j): Mtrx, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-removecolumn-mtrx-rngintelt)
    - [`RemoveColumn(~A, j): Mtrx, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-removecolumn-mtrx-rngintelt-ref)
    - [`RemoveRowColumn(A, i, j): Mtrx, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-removerowcolumn-mtrx-rngintelt)
    - [`RemoveRowColumn(~A, i, j): Mtrx, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-removerowcolumn-mtrx-rngintelt-ref)
    - [`RemoveZeroRows(A): Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#function-removezerorows-mtrx)
    - [`RemoveZeroRows(~A): Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#procedure-removezerorows-mtrx-ref)
    - [Example: Row and Column Operations](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/entries.md#example-ex-80d37c)
- [Building Block Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md)
  - [`BlockMatrix(m, n, blocks): RngIntElt, RngIntElt, [ Mtrx ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-blockmatrix-rngintelt-rngintelt-mtrx)
  - [`BlockMatrix(m, n, rows): RngIntElt, RngIntElt, [ [ Mtrx ] ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-blockmatrix-rngintelt-rngintelt-mtrx-2)
  - [`BlockMatrix(rows): [ [ Mtrx ] ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-blockmatrix-mtrx)
  - [`HorizontalJoin(X, Y): Mtrx, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-horizontaljoin-mtrx-mtrx)
  - [`HorizontalJoin(Q): [ Mtrx ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-horizontaljoin-mtrx)
  - [`HorizontalJoin(T): < Mtrx > → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-horizontaljoin-mtrx-2)
  - [`VerticalJoin(X, Y): Mtrx, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-verticaljoin-mtrx-mtrx)
  - [`VerticalJoin(Q): [ Mtrx ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-verticaljoin-mtrx)
  - [`VerticalJoin(T): < Mtrx > → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-verticaljoin-mtrx-2)
  - [`DiagonalJoin(X, Y): Mtrx, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-diagonaljoin-mtrx-mtrx)
  - [`DiagonalJoin(Q): [ Mtrx ] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-diagonaljoin-mtrx)
  - [`DiagonalJoin(T): < Mtrx > → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-diagonaljoin-mtrx-2)
  - [`KroneckerProduct(A, B): Mtrx, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/join.md#function-kroneckerproduct-mtrx-mtrx)
- [Changing Ring](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/change-ring.md)
  - [`ChangeRing(A, R): Mtrx, Rng → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/change-ring.md#function-changering-mtrx-rng)
  - [`Matrix(R, A): Rng, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/change-ring.md#function-matrix-rng-mtrx)
  - [`ChangeRing(A, R, f): Mtrx, Rng, Map → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/change-ring.md#function-changering-mtrx-rng-map)
  - [`ChangeRing(A, f): Mtrx, Map → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/change-ring.md#function-changering-mtrx-map)
  - [`CanChangeRing(A, R): Mtrx, Rng → BoolElt, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/change-ring.md#function-canchangering-mtrx-rng)
- [Elementary Arithmetic](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md)
  - [`A + B: Mtrx, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#operation-op-plus-mtrx-mtrx)
  - [`A - B: Mtrx, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#operation-op-minus-mtrx-mtrx)
  - [`A * B: Mtrx, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#operation-op-times-mtrx-mtrx)
  - [`x * A: RngElt, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#operation-op-times-rngelt-mtrx)
  - [`A * x: Mtrx, RngElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#operation-op-times-mtrx-rngelt)
  - [`- A: Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#operation-operation-mtrx-mtrx)
  - [`A ^ -1: Mtrx, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#operation-op-pow-mtrx-rngintelt)
  - [`A ^ n: Mtrx, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#operation-op-pow-mtrx-rngintelt-2)
  - [`Transpose(A): Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#function-transpose-mtrx)
  - [`AddScaledMatrix(A, s, B): Mtrx, RngElt, Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#function-addscaledmatrix-mtrx-rngelt-mtrx)
  - [`AddScaledMatrix(~A, s, B): Mtrx, RngElt, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/arithmetic.md#procedure-addscaledmatrix-mtrx-rngelt-mtrx-ref)
- [Nullspaces and Solutions of Systems](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md)
  - [`Nullspace(A): Mtrx → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#function-nullspace-mtrx)
  - [`Kernel(A): Mtrx → ModTupRng, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#function-kernel-mtrx)
  - [`NullspaceMatrix(A): Mtrx → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#function-nullspacematrix-mtrx)
  - [`KernelMatrix(A): Mtrx → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#function-kernelmatrix-mtrx)
  - [`NullspaceOfTranspose(A): Mtrx → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#function-nullspaceoftranspose-mtrx)
  - [`IsConsistent(A, W): Mtrx, Mtrx → BoolElt, Mtrx, ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#function-isconsistent-mtrx-mtrx)
  - [`IsConsistent(A, Q): Mtrx, [ ModTupRng ] → BoolElt, [ ModTupRngElt ], ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#function-isconsistent-mtrx-modtuprng)
  - [`Solution(A, W): ModMatRngElt, ModTupRng → ModTupRngElt, ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#function-solution-modmatrngelt-modtuprng)
  - [`Solution(A, Q): ModMatRngElt, [ ModTupRng ] → [ ModTupRngElt ], ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#function-solution-modmatrngelt-modtuprng-2)
  - [Example: Nullspace of a Random Integer Matrix](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#example-ex-a44c79)
  - [Example: Enumerating All Solutions of a System](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/solution-equation.md#example-ex-83882a)
- [Predicates](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md)
  - [`IsZero(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-iszero-mtrx)
  - [`IsOne(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-isone-mtrx)
  - [`IsMinusOne(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-isminusone-mtrx)
  - [`IsScalar(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-isscalar-mtrx)
  - [`IsDiagonal(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-isdiagonal-mtrx)
  - [`IsSymmetric(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-issymmetric-mtrx)
  - [`IsHermitian(A,f): Mtrx, Map → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-ishermitian-mtrx-map)
  - [`IsUpperTriangular(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-isuppertriangular-mtrx)
  - [`IsLowerTriangular(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-islowertriangular-mtrx)
  - [`IsUnit(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-isunit-mtrx)
  - [`IsSingular(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-issingular-mtrx)
  - [`IsSymplecticMatrix(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/predicates.md#function-issymplecticmatrix-mtrx)
- [Determinant and Other Properties](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md)
  - [`Determinant(A: parameters): Mtrx → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-determinant-mtrx)
  - [`Trace(A): Mtrx → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-trace-mtrx)
  - [`TraceOfProduct(A, B): Mtrx, Mtrx → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-traceofproduct-mtrx-mtrx)
  - [`Rank(A): Mtrx → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-rank-mtrx)
  - [`Minor(M, i, j): Mtrx, RngIntElt, RngIntElt → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-minor-mtrx-rngintelt-rngintelt)
  - [`Minor(M, I, J): Mtrx, [RngIntElt], [RngIntElt] → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-minor-mtrx-rngintelt-rngintelt-2)
  - [`Minors(M, r): Mtrx, RngIntElt → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-minors-mtrx-rngintelt)
  - [`Cofactor(M, i, j): Mtrx, RngIntElt, RngIntElt → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-cofactor-mtrx-rngintelt-rngintelt)
  - [`Cofactors(M): Mtrx → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-cofactors-mtrx)
  - [`Cofactors(M, r): Mtrx, RngIntElt → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-cofactors-mtrx-rngintelt)
  - [`Pfaffian(M): Mtrx → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-pfaffian-mtrx)
  - [`Pfaffian(M, I, J): Mtrx, [RngIntElt], [RngIntElt] → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-pfaffian-mtrx-rngintelt-rngintelt)
  - [`Pfaffians(M, r): Mtrx, RngIntElt → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties.md#function-pfaffians-mtrx-rngintelt)
- [Minimal and Characteristic Polynomials and Eigenvalues](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md)
  - [`MinimalPolynomial(A: parameters): Mtrx → RngUPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-minimalpolynomial-mtrx)
  - [`CharacteristicPolynomial(A: parameters): Mtrx → RngUPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-characteristicpolynomial-mtrx)
  - [`MinimalAndCharacteristicPolynomials(A: parameters): Mtrx → RngUPolElt, RngUPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-minimalandcharacteristicpolynomials-mtrx)
  - [`MCPolynomials(A): Mtrx → RngUPolElt, RngUPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-mcpolynomials-mtrx)
  - [`FactoredMinimalPolynomial(A: parameters): Mtrx → [ <RngUPolElt, RngIntElt>]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-factoredminimalpolynomial-mtrx)
  - [`FactoredCharacteristicPolynomial(A: parameters): Mtrx → [ <RngUPolElt, RngIntElt>]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-factoredcharacteristicpolynomial-mtrx)
  - [`FactoredMinimalAndCharacteristicPolynomials(A: parameters): Mtrx → [<RngUPolElt, RngIntElt>], [<RngUPolElt, RngIntElt>]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-factoredminimalandcharacteristicpolynomials-mtrx)
  - [`FactoredMCPolynomials(A: parameters): Mtrx → [<RngUPolElt, RngIntElt>], [<RngUPolElt, RngIntElt>]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-factoredmcpolynomials-mtrx)
  - [`Eigenvalues(A): Mtrx → { <FldElt, RngIntElt> }`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-eigenvalues-mtrx)
  - [`Eigenspace(A, e): AlgMatElt, FldElt → ModTup`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#function-eigenspace-algmatelt-fldelt)
- [Canonical Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md)
  - [Canonical Forms over General Rings](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#canonical-forms-over-general-rings)
    - [`EchelonForm(A): Mtrx → Mtrx, AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-echelonform-mtrx)
    - [`Adjoint(A): Mtrx → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-adjoint-mtrx)
  - [Canonical Forms over Fields](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#canonical-forms-over-fields)
    - [`PrimaryRationalForm(A): Mtrx → AlgMatElt, AlgMatElt, [ <RngUPolElt, RngIntElt ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-primaryrationalform-mtrx)
    - [`JordanForm(A): Mtrx → Mtrx, AlgMatElt, [ <RngUPolElt, RngIntElt> ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-jordanform-mtrx)
    - [`RationalForm(A): Mtrx → Mtrx, AlgMatElt, [ RngUPolElt ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-rationalform-mtrx)
    - [`PrimaryInvariantFactors(A): Mtrx → [ <RngUPolElt, RngIntElt> ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-primaryinvariantfactors-mtrx)
    - [`InvariantFactors(A): Mtrx → [ RngUPolElt ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-invariantfactors-mtrx)
    - [`IsSimilar(A, B): AlgMatElt, AlgMatElt → BoolElt, AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-issimilar-algmatelt-algmatelt)
    - [`HessenbergForm(A): Mtrx → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-hessenbergform-mtrx)
    - [`FrobeniusFormAlternating(A): AlgMatElt → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-frobeniusformalternating-algmatelt)
    - [Example: Canonical Forms over a Finite Field](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#example-ex-1f87a1)
  - [Canonical Forms over Euclidean Domains](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#canonical-forms-over-euclidean-domains)
    - [`HermiteForm(A): Mtrx → Mtrx, ModMatRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-mat-hermiteform)
    - [`SmithForm(A): ModMatRngElt → ModMatRngElt, ModMatRngElt, ModMatRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-mat-smithform)
    - [`ElementaryDivisors(A): Mtrx → [RngElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-elementarydivisors-mtrx)
    - [`Saturation(A): Mtrx → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-mat-saturation)
    - [Example: Echelon Forms over a Field and the Integers](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#example-ex-bd35e5)
- [Orders of Invertible Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/order.md)
  - [`HasFiniteOrder(A): Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/order.md#function-hasfiniteorder-mtrx)
  - [`Order(A): AlgMatElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/order.md#function-order-algmatelt)
  - [`FactoredOrder(A): AlgMatElt → [ <RngIntElt, RngIntElt> ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/order.md#function-factoredorder-algmatelt)
  - [`ProjectiveOrder(A): AlgMatElt → RngIntElt, RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/order.md#function-projectiveorder-algmatelt)
  - [`FactoredProjectiveOrder(A): AlgMatElt → [ <RngIntElt, RngIntElt> ], RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/order.md#function-factoredprojectiveorder-algmatelt)
- [Numerical Linear Algebra](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md)
  - [`RQDecomposition(M): Mtrx[RngReCom] → Mtrx, AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-rqdecomposition-mtrx-rngrecom)
  - [`QLDecomposition(M): Mtrx[RngReCom] → AlgMatElt, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-qldecomposition-mtrx-rngrecom)
  - [`NumericalInverse(M): Mtrx[RngReCom] → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalinverse-mtrx-rngrecom)
  - [Example: Numerical Matrix Decompositions](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#example-ex-5a8543)
  - [Rank, Kernel, Solution, and Pseudoinverse](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#rank-kernel-solution-and-pseudoinverse)
    - [`NumericalRank(M): Mtrx[RngReCom] → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalrank-mtrx-rngrecom)
    - [`NumericalKernel(M): Mtrx[RngReCom] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalkernel-mtrx-rngrecom)
    - [`NumericalImage(M): Mtrx[RngReCom] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalimage-mtrx-rngrecom)
    - [`NumericalSolution(M,w): Mtrx[RngReCom], Mtrx[RngReCom] → Mtrx, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalsolution-mtrx-rngrecom-mtrx-rngrecom)
    - [`NumericalIsConsistent(M,w): Mtrx[RngReCom], Mtrx[RngReCom] → BoolElt, Mtrx, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalisconsistent-mtrx-rngrecom-mtrx-rngrecom)
    - [`NumericalPseudoinverse(M): Mtrx[RngReCom] → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalpseudoinverse-mtrx-rngrecom)
    - [Example: Numerical Rank, Kernel, and Pseudoinverse](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#example-ex-b3a16a)
  - [Eigenvalues and the Singular Value Decomposition](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#eigenvalues-and-the-singular-value-decomposition)
    - [`NumericalHessenbergForm(M): Mtrx[RngReCom] → Mtrx, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalhessenbergform-mtrx-rngrecom)
    - [`NumericalSchurForm(M): Mtrx[RngReCom] → Mtrx, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalschurform-mtrx-rngrecom)
    - [`NumericalEigenvalues(M): Mtrx[RngReCom] → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericaleigenvalues-mtrx-rngrecom)
    - [`NumericalEigenvectors(M, e): Mtrx, FldComElt → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericaleigenvectors-mtrx-fldcomelt)
    - [`NumericalBidiagonalForm(M): Mtrx[RngReCom] → Mtrx, Mtrx, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalbidiagonalform-mtrx-rngrecom)
    - [`NumericalSingularValueDecomposition(M): Mtrx[RngReCom] → Mtrx, Mtrx, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#function-numericalsingularvaluedecomposition-mtrx-rngrecom)
    - [Example: Numerical Hessenberg Form and Eigenvalues](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#example-ex-604853)
    - [Example: Numerical Singular Value Decomposition](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/numerical-linalg.md#example-ex-4e7c97)
- [Miscellaneous Operations on Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/misc.md)
  - [`FrobeniusImage(A, e): Mtrx, RngIntElt → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/misc.md#function-frobeniusimage-mtrx-rngintelt)
- [Bibliography](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/bibliography.md)

### Introduction

This chapter describes all the basic operations available for creating and working with matrices. Matrices arise in many different contexts and there are several types of matrix within Magma, but most of the operations listed here apply to all types of matrix.

The parent of any matrix will be one of several types of matrix-structure (module, matrix algebra, matrix group, etc.), and each of these matrix-structure types are described in other chapters, together with operations peculiar to their elements.

### Creation of Matrices

This section describes the elementary constructs provided for creating a matrix or vector. For each of the following functions, the parent of the result will be as follows:

**(a)**
If the result is a vector then its parent will be the appropriate $R$-space (of type `ModTupRng` or `ModTupFld`).

**(b)**
If the result is a square matrix then its parent will be the appropriate matrix algebra (of type `AlgMatElt`).

**(c)**
If the result is a non-square matrix then its parent will be the appropriate $R$-matrix space (of type `ModMatRng` or `ModMatFld`).

A matrix or a vector may also be created by coercing a sequence of ring elements into the appropriate parent matrix structure. There is also a virtual type `Mtrx` and all matrix types inherit from `Mtrx`. While writing package intrinsics, an argument should be declared to be of type `Mtrx` if it is a general matrix.

#### General Matrix Construction

<a id="function-matrix-rng-rngintelt-rngintelt-rngelt"></a>
##### `Matrix(R, m, n, Q): Rng, RngIntElt, RngIntElt, [ RngElt ] -> Mtrx`

<a id="function-matrix-rng-rngintelt-rngintelt-rngintelt-rngintelt-rngelt"></a>
##### `Matrix(R, m, n, Q): Rng, RngIntElt, RngIntElt, [ <RngIntElt, RngIntElt, RngElt> ] -> Mtrx`

<a id="function-matrix-rng-rngintelt-rngintelt-rngelt-2"></a>
##### `Matrix(R, m, n, Q): Rng, RngIntElt, RngIntElt, [ [ RngElt ] ] -> Mtrx`

Given a ring $R$, integers $m,n\ge 0$, and a sequence $Q$, return the $m\times n$ matrix over $R$ whose entries are those specified by $Q$, coerced into $R$. Either of $m$ and $n$ may be 0, in which case $Q$ must have length 0 (and may even be null), and the $m\times n$ zero matrix over $R$ is returned. There are several possibilities for $Q$:

**(a)**
The sequence $Q$ may be a sequence of length $mn$ containing elements of a ring $S$, in which case the entries are given in row-major order. In this case, the function is equivalent to `MatrixRing(R, n)!Q` if $m=n$ and `RMatrixSpace(R, m, n)!Q` otherwise.

**(b)**
The sequence $Q$ may be a sequence of tuples, each of the form `<i, j, x>`, where $1\leq i\leq m$, $1\leq j\leq n$, and $x\in S$ for some ring $S$. Such a tuple specifies that the $(i, j)$-th entry of the matrix is $x$. If an entry position is not given then its value is zero, while if an entry position is repeated then the last value overrides any previous value(s). This case is useful for creating sparse matrices.

**(c)**
The sequence $Q$ may be a sequence of $m$ sequences, each of length $n$ and having entries in a ring $S$, in which case the rows of the matrix are specified by the inner sequences.

**(d)**
The sequence $Q$ may be a sequence of $m$ vectors, each of length $n$ and having entries in a ring $S$, in which case the rows of the matrix are specified by the vectors.

<a id="example-ex-79e602"></a>
##### `Example: Creating Matrices with Matrix (ex-79e602)`

This example demonstrates simple ways of creating matrices using the general `Matrix(R, m, n, Q)` function.

(a) Defining a $2 \times 2$ matrix over ${\mathbb{Z}}$:

```magma
> X := Matrix(IntegerRing(), 2, 2, [1,2, 3,4]);
> X;
[1 2]
[3 4]
> Parent(X);
Full Matrix Algebra of degree 2 over Integer Ring
```

(b) Defining a $2 \times 3$ matrix over ${\bf F}_{23}$:

```magma
> X := Matrix(GF(23), 2, 3, [1,-2,3, 4,100,-6]);
> X;
[ 1 21  3]
[ 4  8 17]
> Parent(X);
Full KMatrixSpace of 2 by 3 matrices over GF(23)
```

(c) Defining a sparse $5 \times 10$ matrix over ${\mathbb{Q}}$:

```magma
> X := Matrix(RationalField(), 5, 10, [<1,2,23>, <3,7,11>, <5,10,-1>]);
> X;
[ 0 23  0  0  0  0  0  0  0  0]
[ 0  0  0  0  0  0  0  0  0  0]
[ 0  0  0  0  0  0 11  0  0  0]
[ 0  0  0  0  0  0  0  0  0  0]
[ 0  0  0  0  0  0  0  0  0 -1]
> Parent(X);
Full KMatrixSpace of 5 by 10 matrices over Rational Field
```

(c) Defining a sparse $10 \times 10$ matrix over ${\bf F}_{101}$:

```magma
> X := Matrix(GF(101), 10, 10, [<2*i-1, 2*j-1, i*j>: i, j in [1..5]]);
> X;
[  1   0   2   0   3   0   4   0   5   0]
[  0   0   0   0   0   0   0   0   0   0]
[  2   0   4   0   6   0   8   0  10   0]
[  0   0   0   0   0   0   0   0   0   0]
[  3   0   6   0   9   0  12   0  15   0]
[  0   0   0   0   0   0   0   0   0   0]
[  4   0   8   0  12   0  16   0  20   0]
[  0   0   0   0   0   0   0   0   0   0]
[  5   0  10   0  15   0  20   0  25   0]
[  0   0   0   0   0   0   0   0   0   0]
> Parent(X);
Full Matrix Algebra of degree 10 over GF(101)
```

#### Shortcuts

The following functions are “shortcut” versions of the previous general creation function, where some of the arguments are omitted since they can be inferred by Magma.

<a id="function-matrix-rngintelt-rngintelt-rngelt"></a>
##### `Matrix(m, n, Q): RngIntElt, RngIntElt, [ RngElt ] -> Mtrx`

Given integers $m,n\ge 0$ and a sequence $Q$ of length $mn$ containing elements of a ring $R$, return the $m\times n$ matrix over $R$ whose entries are the entries of $Q$, in row-major order. Either of $m$ and $n$ may be 0, in which case $Q$ must have length 0 and some universe $R$. This function is equivalent to `MatrixRing(Universe(Q), n)!Q` if $m=n$ and `RMatrixSpace(Universe(Q), m, n)!Q` otherwise.

<a id="function-matrix-rngintelt-rngintelt-rngelt-2"></a>
##### `Matrix(m, n, Q): RngIntElt, RngIntElt, [ [ RngElt ] ] -> Mtrx`

Given integers $m$ and $n$, and a sequence $Q$ consisting of $m$ sequences, each of length $n$ and having entries in a ring $R$, return the $m\times n$ matrix over $R$ whose rows are given by the inner sequences of $Q$.

<a id="function-matrix-mtrx"></a>
##### `Matrix(Q): [ Mtrx ] -> Mtrx`

Given a sequence $Q$ of $m$ vectors, each of length $n$ over a ring $R$, return the $m\times n$ matrix over $R$ whose rows are the entries of $Q$.

<a id="function-matrix-rng-rngintelt-rngelt"></a>
##### `Matrix(R, n, Q): Rng, RngIntElt, [ RngElt ] -> Mtrx`

Given a ring $R$, an integer $n\ge 0$, and a sequence $Q$ of length $l$ containing elements of a ring $S$, such that $n$ divides $l$, return the $(l/n)\times n$ matrix over $R$ whose entries are the entries of $Q$, coerced into $R$, in row-major order. The argument $n$ may be 0, in which case $Q$ must have length 0 (and may even be null), in which case the $0 \times 0$ matrix over $R$ is returned. This function is equivalent to `MatrixRing(R, n)!Q` if $l=n^2$ and `RMatrixSpace(R, #Q div n, n)!Q` otherwise.

<a id="function-matrix-rngintelt-rngelt"></a>
##### `Matrix(n, Q): RngIntElt, [ RngElt ] -> Mtrx`

Given an integer $n\ge 0$ and a sequence $Q$ of length $l$ containing elements of a ring $R$, such that $n$ divides $l$, return the $(l/n)\times n$ matrix over $R$ whose entries are the entries of $Q$, in row-major order. The argument $n$ may be 0, in which case $Q$ must have length 0 and some universe $R$, in which case the $0 \times 0$ matrix over $R$ is returned. This function is equivalent to `MatrixRing(Universe(Q), n)!Q` if $l=n^2$ and `RMatrixSpace(Universe(Q), #Q div n, n)!Q` otherwise.

<a id="function-matrix-rngelt"></a>
##### `Matrix(Q): [ [ RngElt ] ] -> Mtrx`

Given a sequence $Q$ consisting of $m$ sequences, each of length $n$ and having entries in a ring $R$, return the $m\times n$ matrix over $R$ whose rows are given by the inner sequences of $Q$.

<a id="function-matrix-rng-rngelt"></a>
##### `Matrix(R, Q): Rng, [ [ RngElt ] ] -> Mtrx`

Given a sequence $Q$ consisting of $m$ sequences, each of length $n$ and having entries in a ring $S$, return the $m\times n$ matrix over $R$ whose rows are given by the inner sequences of $Q$, with the entries coerced into $R$.

<a id="example-ex-cb789b"></a>
##### `Example: Matrix Construction Shortcuts (ex-cb789b)`

The first matrix in the previous example may be created thus:

```magma
> X := Matrix(2, [1,2, 3,4]);
> X;
[1 2]
[3 4]
> X := Matrix([[1,2], [3,4]]);
> X;
[1 2]
[3 4]
```

The second matrix in the previous example may be created thus:

```magma
> X := Matrix(GF(23), 3, [1,-2,3, 4,100,-6]);
> X;
[ 1 21  3]
[ 4  8 17]
> Parent(X);
Full KMatrixSpace of 2 by 3 matrices over GF(23)
> X := Matrix(GF(23), [[1,-2,3], [4,100,-6]]);
> X;
[ 1 21  3]
[ 4  8 17]
> X := Matrix([[GF(23)|1,-2,3], [4,100,-6]]);
> X;
[ 1 21  3]
[ 4  8 17]
```

#### Construction of Structured Matrices

<a id="function-zeromatrix-rng-rngintelt-rngintelt"></a>
##### `ZeroMatrix(R, m, n): Rng, RngIntElt, RngIntElt -> Mtrx`

Given a ring $R$ and integers $m,n\ge 0$, return the $m\times n$ zero matrix over $R$.

<a id="function-identitymatrix-rng-rngintelt"></a>
##### `IdentityMatrix(R, n): Rng, RngIntElt -> Mtrx`

Given a ring $R$ and integer $n\ge 0$, return the $n\times n$ identity matrix over $R$.

<a id="function-scalarmatrix-rngintelt-rngelt"></a>
##### `ScalarMatrix(n, s): RngIntElt, RngElt -> Mtrx`

Given an integer $n\ge 0$ and an element $s$ of a ring $R$, return the $n \times n$ scalar matrix over $R$ which has $s$ on the diagonal and zeros elsewhere. The argument $n$ may be 0, in which case the $0 \times 0$ matrix over $R$ is returned. This function is equivalent to `MatrixRing(Parent(s), n)!s`.

<a id="function-scalarmatrix-rng-rngintelt-rngelt"></a>
##### `ScalarMatrix(R, n, s): Rng, RngIntElt, RngElt -> Mtrx`

Given a ring $R$, an integer $n\ge 0$, and an element $s$ of a ring $S$, return the $n \times n$ scalar matrix over $R$ which has $s$, coerced into $R$, on the diagonal and zeros elsewhere. The argument $n$ may be 0, in which case the $0 \times 0$ matrix over $R$ is returned. This function is equivalent to `MatrixRing(R, n)!s`.

<a id="function-diagonalmatrix-rng-rngintelt-rngelt"></a>
##### `DiagonalMatrix(R, n, Q): Rng, RngIntElt, [ RngElt ] -> Mtrx`

Given a ring $R$, an integer $n\ge 0$, and a sequence $Q$ of $n$ ring elements, return the $n \times n$ diagonal matrix over $R$ whose diagonal entries correspond to the entries of $Q$, coerced into $R$.

<a id="function-diagonalmatrix-rng-rngelt"></a>
##### `DiagonalMatrix(R, Q): Rng, [ RngElt ] -> Mtrx`

Given a ring $R$ and a sequence $Q$ of $n$ ring elements, return the $n \times n$ diagonal matrix over $R$ whose diagonal entries correspond to the entries of $Q$, coerced into $R$.

<a id="function-diagonalmatrix-rngelt"></a>
##### `DiagonalMatrix(Q): [ RngElt ] -> Mtrx`

Given a sequence $Q$ of $n$ elements from a ring $R$, return the $n \times n$ diagonal matrix over $R$ whose diagonal entries correspond to the entries of $Q$.

<a id="function-matrix-mtrx-2"></a>
##### `Matrix(A): Mtrx -> Mtrx`

Given a matrix $A$ of any type, return the same matrix but having as parent the appropriate matrix algebra if $A$ is square, or the appropriate $R$-matrix space otherwise. This is useful, for example, if it is desired to convert a matrix group element or a square $R$-matrix space element to be an element of a general matrix algebra.

<a id="function-lowertriangularmatrix-rngelt"></a>
##### `LowerTriangularMatrix(Q): [ RngElt ] -> Mtrx`

Given a sequence $Q$ of length $l$ containing elements of a ring $R$, such that $l={{n + 1} \choose 2} = n(n+1)/2$ for some integer $n$ (so $l$ is a triangular number), return the $n \times n$ lower-triangular matrix $F$ over $R$ such that the entries of $Q$ describe the lower triangular part of $F$, in row major order.

<a id="function-lowertriangularmatrix-rng-rngelt"></a>
##### `LowerTriangularMatrix(R, Q): Rng, [ RngElt ] -> Mtrx`

Given a ring $R$ and a sequence $Q$ of length $l$ containing elements of a ring $S$, such that $l={{n + 1} \choose 2} = n(n+1)/2$ for some integer $n$ (so $l$ is a triangular number), return the $n \times n$ lower-triangular matrix $F$ over $R$ such that the entries of $Q$, coerced into $R$, describe the lower triangular part of $F$, in row major order.

<a id="function-uppertriangularmatrix-rngelt"></a>
##### `UpperTriangularMatrix(Q): [ RngElt ] -> Mtrx`

Given a sequence $Q$ of length $l$ containing elements of a ring $R$, such that $l={{n + 1} \choose 2} = n(n+1)/2$ for some integer $n$ (so $l$ is a triangular number), return the $n \times n$ upper-triangular matrix $F$ over $R$ such that the entries of $Q$ describe the upper triangular part of $F$, in *row major* order.

<a id="function-uppertriangularmatrix-rng-rngelt"></a>
##### `UpperTriangularMatrix(R, Q): Rng, [ RngElt ] -> Mtrx`

Given a ring $R$ and a sequence $Q$ of length $l$ containing elements of a ring $S$, such that $l={{n + 1} \choose 2} = n(n+1)/2$ for some integer $n$ (so $l$ is a triangular number), return the $n \times n$ upper-triangular matrix $F$ over $R$ such that the entries of $Q$, coerced into $R$, describe the upper triangular part of $F$, in *row major* order.

<a id="function-symmetricmatrix-rngelt"></a>
##### `SymmetricMatrix(Q): [ RngElt ] -> Mtrx`

Given a sequence $Q$ of length $l$ containing elements of a ring $R$, such that $l={{n + 1} \choose 2} = n(n+1)/2$ for some integer $n$ (so $l$ is a triangular number), return the $n  \times n$ symmetric matrix $F$ over $R$ such that the entries of $Q$ describe the lower triangular part of $F$, in row major order. This function allows the creation of symmetric matrices without the need to specify the redundant upper triangular part.

<a id="function-symmetricmatrix-rng-rngelt"></a>
##### `SymmetricMatrix(R, Q): Rng, [ RngElt ] -> Mtrx`

Given a ring $R$ and a sequence $Q$ of length $l$ containing elements of a ring $S$, such that $l={{n + 1} \choose 2} = n(n+1)/2$ for some integer $n$ (so $l$ is a triangular number), return the $n \times n$ symmetric matrix $F$ over $R$ such that the entries of $Q$, coerced into $R$, describe the lower triangular part of $F$, in row major order. This function allows the creation of symmetric matrices without the need to specify the redundant upper triangular part.

<a id="function-antisymmetricmatrix-rngelt"></a>
##### `AntisymmetricMatrix(Q): [ RngElt ] -> Mtrx`

Given a sequence $Q$ of length $l$ containing elements of a ring $R$, such that $l={{n} \choose 2} = n(n-1)/2$ for some integer $n$ (so $l$ is a triangular number), return the $n  \times n$ antisymmetric matrix $F$ over $R$ such that the entries of $Q$ describe the proper lower triangular part of $F$, in row major order. The diagonal of $F$ is zero and the proper upper triangular part of $F$ is the negation of the proper lower triangular part of $F$.

<a id="function-antisymmetricmatrix-rng-rngelt"></a>
##### `AntisymmetricMatrix(R, Q): Rng, [ RngElt ] -> Mtrx`

Given a ring $R$ and a sequence $Q$ of length $l$ containing elements of a ring $S$, such that $l={{n} \choose 2} = n(n-1)/2$ for some integer $n$ (so $l$ is a triangular number), return the $n \times n$ antisymmetric matrix $F$ over $R$ such that the entries of $Q$, coerced into $R$, describe the proper lower triangular part of $F$, in row major order.

<a id="function-permutationmatrix-rng-rngintelt"></a>
##### `PermutationMatrix(R, Q): Rng, [ RngIntElt ] -> Mtrx`

Given a ring $R$ and a sequence $Q$ of length $n$, such that $Q$ is a permutation of $[1,2,\dots,n]$, return the $n$ by $n$ permutation matrix over $R$ corresponding $Q$.

<a id="function-permutationmatrix-rng-grppermelt"></a>
##### `PermutationMatrix(R, x): Rng, GrpPermElt -> Mtrx`

Given a ring $R$ and a permutation $x$ of degree $n$, return the $n$ by $n$ permutation matrix over $R$ corresponding $x$.

<a id="example-ex-c66a52"></a>
##### `Example: Scalar and Structured Matrices (ex-c66a52)`

This example demonstrates ways of creating special matrices.

(a) Defining a $3 \times 3$ scalar matrix over ${\mathbb{Z}}$:

```magma
> S := ScalarMatrix(3, -4);
> S;
[-4  0  0]
[ 0 -4  0]
[ 0  0 -4]
> Parent(S);
Full Matrix Algebra of degree 3 over Integer Ring
```

(b) Defining a $3 \times 3$ diagonal matrix over ${\bf F}_{23}$:

```magma
> D := DiagonalMatrix(GF(23), [1, 2, -3]);
> D;
[ 1  0  0]
[ 0  2  0]
[ 0  0 20]
> Parent(D);
Full Matrix Algebra of degree 3 over GF(23)
```

(c) Defining a $3 \times 3$ symmetric matrix over ${\mathbb{Q}}$:

```magma
> S := SymmetricMatrix([1, 1/2,3, 1,3,4]);
> S;
[  1 1/2   1]
[1/2   3   3]
[  1   3   4]
> Parent(S);
Full Matrix Algebra of degree 3 over Rational Field
```

(d) Defining $n \times n$ lower- and upper-triangular matrices for various $n$:

```magma
> low := func<n | LowerTriangularMatrix([i: i in [1 .. Binomial(n + 1, 2)]])>;
> up := func<n | UpperTriangularMatrix([i: i in [1 .. Binomial(n + 1, 2)]])>;
> sym := func<n | SymmetricMatrix([i: i in [1 .. Binomial(n + 1, 2)]])>;
> low(3);
[1 0 0]
[2 3 0]
[4 5 6]
> up(3);
[1 2 3]
[0 4 5]
[0 0 6]
> sym(3);
[1 2 4]
[2 3 5]
[4 5 6]

> up(6);
[ 1  2  3  4  5  6]
[ 0  7  8  9 10 11]
[ 0  0 12 13 14 15]
[ 0  0  0 16 17 18]
[ 0  0  0  0 19 20]
[ 0  0  0  0  0 21]
```

#### Construction of Random Matrices

<a id="function-randommatrix-rng-rngintelt-rngintelt"></a>
##### `RandomMatrix(R, m, n): Rng, RngIntElt, RngIntElt -> Mtrx`

Given a *finite* ring $R$ and positive integers $m$ and $n$, construct a random $m\times n$ matrix over $R$.

<a id="function-randomunimodularmatrix-rngintelt-rngintelt"></a>
##### `RandomUnimodularMatrix(n, M): RngIntElt, RngIntElt -> Mtrx`

Given positive integers $M$ and $n$, construct a random integral $n \times n$ matrix having determinant $1$ or $-1$. Most entries will lie in the range $[-M, M]$.

<a id="function-randomslnz-rngintelt-rngintelt-rngintelt"></a>
##### `RandomSLnZ(n, k, l): RngIntElt, RngIntElt, RngIntElt -> AlgMatElt`

A random element of $SL_n({\mathbb{Z}})$, obtained by multiplying $l$ random matrices of the form $I+E$, where $E$ has exactly one nonzero entry, which is off the diagonal and has absolute value at most $k$.

<a id="function-randomglnz-rngintelt-rngintelt-rngintelt"></a>
##### `RandomGLnZ(n, k, l): RngIntElt, RngIntElt, RngIntElt -> AlgMatElt`

A random element of $GL_n({\mathbb{Z}})$, obtained in a similar way to `RandomSLnZ`.

<a id="function-randomsymplecticmatrix-rngintelt-rngintelt"></a>
##### `RandomSymplecticMatrix(g, m): RngIntElt, RngIntElt -> Mtrx`

Given positive integers $n$ and $m$, construct a (somewhat) random $2n \times 2n$ symplectic matrix over the integers. The entries will have the same order of magnitude as $m$.

<a id="function-randomsymmetricmatrix-rng-rngintelt"></a>
##### `RandomSymmetricMatrix(R, n): Rng, RngIntElt -> AlgMatElt`

<a id="function-randomsymmetricmatrix-rngord-rngintelt-rngintelt"></a>
##### `RandomSymmetricMatrix(R, n, M): RngOrd, RngIntElt, RngIntElt -> AlgMatElt`

Generate a random symmetric matrix of dimension $n$ over the ring $R$, where each coordinate is in $[-M,M]$.

<a id="function-randompositivedefinitesymmetricmatrix-rngintelt-rngintelt"></a>
##### `RandomPositiveDefiniteSymmetricMatrix(n, M): RngIntElt, RngIntElt -> AlgMatElt`

Generates a random positive definite symmetric matrix over the integers of dimension $n$, with entries in $[-M,M]$.

#### Creating Vectors

<a id="function-vector-rngintelt-rngelt"></a>
##### `Vector(n, Q): RngIntElt, [ RngElt ] -> ModTupRngElt`

Given an integer $n$ and a sequence $Q$ of length $n$ containing elements of a ring $R$, return the vector of length $n$ whose entries are the entries of $Q$. The integer $n$ may be 0, in which case $Q$ must have length 0 and some universe $R$. This function is equivalent to `RSpace(Universe(Q), n)!Q`.

<a id="function-vector-rngelt"></a>
##### `Vector(Q): [ RngElt ] -> ModTupRngElt`

Given a sequence $Q$ of length $l$ containing elements of a ring $R$, return the vector of length $l$ whose entries are the entries of $Q$. The argument $Q$ may have length 0 if it has a universe $R$ (i.e., it may not be null). This function is equivalent to `RSpace(Universe(Q), #Q)!Q`.

<a id="function-vector-rng-rngintelt-rngelt"></a>
##### `Vector(R, n, Q): Rng, RngIntElt, [ RngElt ] -> ModTupRngElt`

Given a ring $R$, an integer $n$, and a sequence $Q$ of length $n$ containing elements of a ring $S$, return the vector of length $n$ whose entries are the entries of $Q$, coerced into $R$. The integer $n$ may be 0, in which case $Q$ must have length 0 (and may even be null). This function is equivalent to `RSpace(R, n)!Q`.

<a id="function-vector-rng-rngelt"></a>
##### `Vector(R, Q): Rng, [ RngElt ] -> ModTupRngElt`

Given a ring $R$ and a sequence $Q$ of length $l$ containing elements of a ring $S$, return the vector of length $l$ whose entries are the entries of $Q$, coerced into $R$. The argument $Q$ may have length 0 and may be null. This function is equivalent to `RSpace(R, #Q)!Q`.

### Elementary Properties

The following functions yield elementary properties of matrices and may be applied to matrices of any type, including vectors.

<a id="function-numberofrows-mtrx"></a>
#### `NumberOfRows(A): Mtrx -> RngIntElt`

<a id="function-nrows-mtrx"></a>
#### `Nrows(A): Mtrx -> RngIntElt`

Given an $m \times n$ matrix $A$, return $m$, the number of rows of $A$.

<a id="function-numberofcolumns-mtrx"></a>
#### `NumberOfColumns(A): Mtrx -> RngIntElt`

<a id="function-ncols-mtrx"></a>
#### `Ncols(A): Mtrx -> RngIntElt`

Given an $m \times n$ matrix $A$, return $n$, the number of columns of $A$.

<a id="function-numberofnonzeroentries-mtrx"></a>
#### `NumberOfNonZeroEntries(A): Mtrx -> RngIntElt`

<a id="function-nnzentries-mtrx"></a>
#### `NNZEntries(A): Mtrx -> RngIntElt`

Given a matrix $A$, return the number of non-zero entries in $A$.

<a id="function-density-mtrx"></a>
#### `Density(A): Mtrx -> FldRe`

Given a matrix $A$, return the density of $A$ as a real number, which is the number of non-zero entries in $A$ divided by the product of the number of rows of $A$ and the number of columns of $A$ (or zero if $A$ has zero rows or columns).

<a id="function-basering-mtrx"></a>
#### `BaseRing(A): Mtrx -> Rng`

<a id="function-coefficientring-mtrx"></a>
#### `CoefficientRing(A): Mtrx -> Rng`

Given a matrix $A$ with entries lying in a ring $R$, return $R$.

<a id="function-elementtosequence-mtrx"></a>
#### `ElementToSequence(A): Mtrx -> [ RngElt ]`

<a id="function-eltseq-mtrx"></a>
#### `Eltseq(A): Mtrx -> [ RngElt ]`

Given a matrix $A$ over the ring $R$ having $m$ rows and $n$ columns, return the entries of $A$, in row-major order, as a sequence of $mn$ elements of $R$.

<a id="function-rowsequence-mtrx"></a>
#### `RowSequence(A): Mtrx -> [ [RngElt] ]`

Returns the entries of $A$ as a sequence of rows where a row is represented as a sequence of entries of $A$.

### Accessing or Modifying Entries

#### Indexing

The following functions and operators enable one to access individual entries or rows of matrices or vectors.

<a id="indexed-indexed-a-mtrx-rngintelt-modtuprngelt"></a>
##### `A[i]: Mtrx, RngIntElt -> ModTupRngElt`

Given a matrix $A$ over the ring $R$ having $m$ rows and $n$ columns, and an integer $i$ such that $1 \leq i \leq m$, return the $i$-th row of $A$, as a vector of length $n$.

<a id="indexed-indexed-a-mtrx-rngintelt-rngintelt-rngelt"></a>
##### `A[i, j]: Mtrx, RngIntElt, RngIntElt -> RngElt`

Given a matrix $A$ over the ring $R$ having $m$ rows and $n$ columns, integers $i$ and $j$ such that $1 \leq i \leq m$ and $1 \leq j \leq n$, return the $(i,j)$-th entry of $A$, as an element of the ring $R$.

<a id="indexed-indexed-a-mtrx-rngintelt-rngelt"></a>
##### `A[Q]: Mtrx, [ RngIntElt ] -> RngElt`

<a id="indexed-indexed-a-mtrx-rngintelt-rngintelt-rngelt-2"></a>
##### `A[i .. j]: Mtrx, RngIntElt, RngIntElt -> RngElt`

Given a matrix $A$ over the ring $R$ having $m$ rows and $n$ columns, and a sequence $Q$ of integers in the range $[1..m]$, return the sequence consisting of the rows of $A$ specified by $Q$. This is equivalent to `[A[i]: i in Q]]`. If $Q$ is a range, then the second form `A[i .. j]` may be used to specify the range directly.

<a id="literal-literal-a-i-v-mtrx-rngintelt-mtrx"></a>
##### `A[i] := v: Mtrx, RngIntElt, Mtrx`

Given a matrix $A$ over the ring $R$ having $m$ rows and $n$ columns, an integer $i$ such that $1 \leq i \leq m$, and a vector $v$ over $R$ of length $n$, modify the $i$-th row of $A$ to be $v$. The integer $0$ may also be given for $v$, indicating the zero vector.

<a id="literal-literal-a-i-j-x-mtrx-rngintelt-rngintelt-rngelt"></a>
##### `A[i, j] := x: Mtrx, RngIntElt, RngIntElt, RngElt`

Given a matrix $A$ over the ring $R$ having $m$ rows and $n$ columns, integers $i$ and $j$ such that $1 \leq i \leq m$ and $1 \leq j \leq n$, and a ring element $x$ coercible into $R$, modify the $(i,j)$-th entry of $A$ to be $x$.

<a id="example-ex-e9c35f"></a>
##### `Example: Accessing Matrix Entries (ex-e9c35f)`

This example demonstrates simple ways of accessing the entries of matrices.

```magma
> X := Matrix(4, [1,2,3,4, 5,4,3,2, 1,2,3,4]);
> X;
[1 2 3 4]
[5 4 3 2]
[1 2 3 4]
> X[1];
(1 2 3 4)
> X[1, 2];
2
> X[1, 2] := 23;
> X;
[ 1 23  3  4]
[ 5  4  3  2]
[ 1  2  3  4]
> X[3] := Vector([9,8,7,6]);
> X[2] := 0;
> X;
[ 1 23  3  4]
[ 0  0  0  0]
[ 9  8  7  6]
```

#### Extracting and Inserting Blocks

The following functions enable the extraction of certain rows, columns, or general submatrices, or the replacement of a block by another matrix.

<a id="function-submatrix-mtrx-rngintelt-rngintelt-rngintelt-rngintelt"></a>
##### `Submatrix(A, i, j, p, q): Mtrx, RngIntElt, RngIntElt, RngIntElt, RngIntElt -> Mtrx`

<a id="function-extractblock-mtrx-rngintelt-rngintelt-rngintelt-rngintelt"></a>
##### `ExtractBlock(A, i, j, p, q): Mtrx, RngIntElt, RngIntElt, RngIntElt, RngIntElt -> Mtrx`

Given an $m \times n$ matrix $A$ and integers $i$, $j$, $p$ and $q$ such that $1\leq i \leq i + p \leq m+1$ and $1 \leq j \leq j + q \leq n+1$, return the $p \times q$ submatrix of $A$ rooted at $(i, j)$. Either or both of $p$ and $q$ may be zero, while $i$ may be $m+1$ if $p$ is zero and $j$ may be $n+1$ if $q$ is zero.

<a id="function-submatrixrange-mtrx-rngintelt-rngintelt-rngintelt-rngintelt"></a>
##### `SubmatrixRange(A, i, j, r, s): Mtrx, RngIntElt, RngIntElt, RngIntElt, RngIntElt -> Mtrx`

<a id="function-extractblockrange-mtrx-rngintelt-rngintelt-rngintelt-rngintelt"></a>
##### `ExtractBlockRange(A, i, j, r, s): Mtrx, RngIntElt, RngIntElt, RngIntElt, RngIntElt -> Mtrx`

Given an $m \times n$ matrix $A$ and integers $i$, $j$, $r$, and $s$ such that $1\leq i$, $i-1 \leq r \leq m$, $1 \leq j$, and $j-1 \leq s \leq n$, return the $r-i+1\times s-j+1$ submatrix of $A$ rooted at the $(i, j)$-th entry and extending to the $(r, s)$-th entry, inclusive. $r$ may equal $i-1$ or $s$ may equal $j-1$, in which case a matrix with zero rows or zero columns, respectively, will be returned.

<a id="function-submatrix-mtrx-rngintelt-rngintelt"></a>
##### `Submatrix(A, I, J): Mtrx, [RngIntElt], [RngIntElt] -> Mtrx`

Given an $m \times n$ matrix $A$ and integer sequences $I$ and $J$, return the submatrix of $A$ given by the row indices in $I$ and the column indices in $J$.

<a id="function-insertblock-mtrx-mtrx-rngintelt-rngintelt"></a>
##### `InsertBlock(A, B, i, j): Mtrx, Mtrx, RngIntElt, RngIntElt -> Mtrx`

<a id="function-insertblock-mtrx-mtrx-rngintelt-rngintelt-ref"></a>
##### `InsertBlock(~A, B, i, j): Mtrx, Mtrx, RngIntElt, RngIntElt -> Mtrx`

Given an $m \times n$ matrix $A$ over a ring $R$, a $p \times q$ matrix $B$ over $R$, and integers $i$ and $j$ such that $1\leq i \leq i + p \leq m+1$ and $1 \leq j \leq j + q \leq n+1$, insert $B$ at position $(i,j)$ in $A$. In the functional version ($A$ is a value argument), this function returns the new matrix and leaves $A$ untouched, while in the procedural version ($\sim A$ is a reference argument), $A$ is modified in place so that the $p \times q$ submatrix of $A$ rooted at $(i, j)$ is now equal to $B$.

<a id="function-rowsubmatrix-mtrx-rngintelt-rngintelt"></a>
##### `RowSubmatrix(A, i, k): Mtrx, RngIntElt, RngIntElt -> Mtrx`

Given an $m \times n$ matrix $A$ and integers $i$ and $k$ such that $1 \le i \leq i + k \leq m+1$, return the $k \times n$ submatrix of $X$ consisting of rows $[i \ldots i + k - 1]$ inclusive. The integer $k$ may be zero and $i$ may also be $m+1$ if $k$ is zero, but the result will always have $n$ columns.

<a id="function-rowsubmatrix-mtrx-rngintelt"></a>
##### `RowSubmatrix(A, i): Mtrx, RngIntElt -> Mtrx`

Given an $m \times n$ matrix $A$ and an integer $i$ such that $0 \le i \leq m$, return the $i\times n$ submatrix of $X$ consisting of the first $i$ rows. The integer $i$ may be $0$, but the result will always have $n$ columns.

<a id="function-rowsubmatrixrange-mtrx-rngintelt-rngintelt"></a>
##### `RowSubmatrixRange(A, i, j): Mtrx, RngIntElt, RngIntElt -> Mtrx`

Given an $m \times n$ matrix $A$ and integers $i$ and $j$ such that $1 \le i$ and $i-1 \leq j \leq m$, return the $j-i+1 \times n$ submatrix of $X$ consisting of rows $[i \ldots j]$ inclusive. The integer $j$ may equal $i-1$, in which case a matrix with zero rows and $n$ columns will be returned.

<a id="function-columnsubmatrix-mtrx-rngintelt-rngintelt"></a>
##### `ColumnSubmatrix(A, i, k): Mtrx, RngIntElt, RngIntElt -> Mtrx`

Given an $m \times n$ matrix $A$ and integers $i$ and $k$ such that $1 \le i \leq i + k \leq n+1$, return the $m \times k$ submatrix of $X$ consisting of columns $[i \ldots i + k - 1]$ inclusive. The integer $k$ may be zero and $i$ may also be $n+1$ if $k$ is zero, but the result will always have $m$ rows.

<a id="function-columnsubmatrix-mtrx-rngintelt"></a>
##### `ColumnSubmatrix(A, i): Mtrx, RngIntElt -> Mtrx`

Given an $m \times n$ matrix $A$ and an integer $i$ such that $0 \le i \leq n$, return the $m\times i$ submatrix of $X$ consisting of the first $i$ columns. The integer $i$ may be $0$, but the result will always have $m$ rows.

<a id="function-columnsubmatrixrange-mtrx-rngintelt-rngintelt"></a>
##### `ColumnSubmatrixRange(A, i, j): Mtrx, RngIntElt, RngIntElt -> Mtrx`

Given an $m \times n$ matrix $A$ and integers $i$ and $j$ such that $1 \le i$ and $i-1 \leq j \leq n$, return the $m\times j-i+1$ submatrix of $X$ consisting of columns $[i \ldots j]$ inclusive. The integer $j$ may equal $i-1$, in which case a matrix with zero columns and $n$ rows will be returned.

<a id="example-ex-0ed08c"></a>
##### `Example: Extracting Submatrices (ex-0ed08c)`

The use of the submatrix operations is illustrated by applying them to a $6 \times 6$ matrix over the ring of integers ${\mathbb{Z}}$.

```magma
> A := Matrix(6,
>     [ 9, 1, 7, -3, 2, -1,
>       3, -4, -5, 9, 2, 7,
>       7, 1, 0, 1, 8, 22,
>       -3, 3, 3, 8, 8, 37,
>       -9, 0, 7, -1, 2, 3,
>       7, 2, -2, 4, 3, 47 ]);
> A;
[ 9  1  7 -3  2 -1]
[ 3 -4 -5  9  2  7]
[ 7  1  0  1  8 22]
[-3  3  3  8  8 37]
[-9  0  7 -1  2  3]
[ 7  2 -2  4  3 47]
> Submatrix(A, 2,2, 3,3);
[-4 -5  9]
[ 1  0  1]
[ 3  3  8]
> SubmatrixRange(A, 2,2, 3,3);
[-4 -5]
[ 1  0]
> S := $1;
> InsertBlock(~A, S, 5,5);
> A;
[ 9  1  7 -3  2 -1]
[ 3 -4 -5  9  2  7]
[ 7  1  0  1  8 22]
[-3  3  3  8  8 37]
[-9  0  7 -1 -4 -5]
[ 7  2 -2  4  1  0]
> RowSubmatrix(A, 5, 2);
[-9  0  7 -1 -4 -5]
[ 7  2 -2  4  1  0]
> RowSubmatrixRange(A, 2, 3);
[ 3 -4 -5  9  2  7]
[ 7  1  0  1  8 22]
> RowSubmatrix(A, 2, 0);
Matrix with 0 rows and 6 columns
```

#### Row and Column Operations

The following functions and procedures provide elementary row or column operations on matrices. For each operation, there is a corresponding function which creates a new matrix for the result (leaving the input matrix unchanged), and a corresponding procedure which modifies the input matrix in place.

<a id="function-swaprows-mtrx-rngintelt-rngintelt"></a>
##### `SwapRows(A, i, j): Mtrx, RngIntElt, RngIntElt -> Mtrx`

<a id="procedure-swaprows-mtrx-rngintelt-rngintelt-ref"></a>
##### `SwapRows(~A, i, j): Mtrx, RngIntElt, RngIntElt`

Given an $m \times n$ matrix $A$ and integers $i$ and $j$ such that $1 \le i\le m$ and $1 \leq j \leq m$, swap the $i$-th and $j$-th rows of $A$.

<a id="function-swapcolumns-mtrx-rngintelt-rngintelt"></a>
##### `SwapColumns(A, i, j): Mtrx, RngIntElt, RngIntElt -> Mtrx`

<a id="procedure-swapcolumns-mtrx-rngintelt-rngintelt-ref"></a>
##### `SwapColumns(~A, i, j): Mtrx, RngIntElt, RngIntElt`

Given an $m \times n$ matrix $A$ and integers $i$ and $j$ such that $1 \le i\le n$ and $1 \leq j \leq n$, swap the $i$-th and $j$-th columns of $A$.

<a id="function-reverserows-mtrx"></a>
##### `ReverseRows(A): Mtrx -> Mtrx`

<a id="procedure-reverserows-mtrx-ref"></a>
##### `ReverseRows(~A): Mtrx`

Given a matrix $A$, reverse all the rows of $A$.

<a id="function-reversecolumns-mtrx"></a>
##### `ReverseColumns(A): Mtrx -> Mtrx`

<a id="procedure-reversecolumns-mtrx-ref"></a>
##### `ReverseColumns(~A): Mtrx`

Given a matrix $A$, reverse all the columns of $A$.

<a id="function-addrow-mtrx-rngelt-rngintelt-rngintelt"></a>
##### `AddRow(A, c, i, j): Mtrx, RngElt, RngIntElt, RngIntElt -> Mtrx`

<a id="procedure-addrow-mtrx-rngelt-rngintelt-rngintelt-ref"></a>
##### `AddRow(~A, c, i, j): Mtrx, RngElt, RngIntElt, RngIntElt`

Given an $m \times n$ matrix $A$ over a ring $R$, a ring element $c$ coercible into $R$, and integers $i$ and $j$ such that $1 \le i\le m$ and $1 \leq j \leq m$, add $c$ times row $i$ of $A$ to row $j$ of $A$.

<a id="function-addcolumn-mtrx-rngelt-rngintelt-rngintelt"></a>
##### `AddColumn(A, c, i, j): Mtrx, RngElt, RngIntElt, RngIntElt -> Mtrx`

<a id="procedure-addcolumn-mtrx-rngelt-rngintelt-rngintelt-ref"></a>
##### `AddColumn(~A, c, i, j): Mtrx, RngElt, RngIntElt, RngIntElt`

Given an $m \times n$ matrix $A$ over a ring $R$, a ring element $c$ coercible into $R$, and integers $i$ and $j$ such that $1 \le i\le n$ and $1 \leq j \leq n$, add $c$ times column $i$ of $A$ to column $j$.

<a id="function-multiplyrow-mtrx-rngelt-rngintelt"></a>
##### `MultiplyRow(A, c, i): Mtrx, RngElt, RngIntElt -> Mtrx`

<a id="procedure-multiplyrow-mtrx-rngelt-rngintelt-ref"></a>
##### `MultiplyRow(~A, c, i): Mtrx, RngElt, RngIntElt`

Given an $m \times n$ matrix $A$ over a ring $R$, a ring element $c$ coercible into $R$, and an integer $i$ such that $1 \le i\le m$, multiply row $i$ of $A$ by $c$ (on the left).

<a id="function-multiplycolumn-mtrx-rngelt-rngintelt"></a>
##### `MultiplyColumn(A, c, i): Mtrx, RngElt, RngIntElt -> Mtrx`

<a id="procedure-multiplycolumn-mtrx-rngelt-rngintelt-ref"></a>
##### `MultiplyColumn(~A, c, i): Mtrx, RngElt, RngIntElt`

Given an $m \times n$ matrix $A$ over a ring $R$, a ring element $c$ coercible into $R$, and an integer $i$ such that $1 \le i\le n$, multiply column $i$ of $A$ by $c$ (on the left).

<a id="function-removerow-mtrx-rngintelt"></a>
##### `RemoveRow(A, i): Mtrx, RngIntElt -> Mtrx`

<a id="procedure-removerow-mtrx-rngintelt-ref"></a>
##### `RemoveRow(~A, i): Mtrx, RngIntElt`

Given an $m \times n$ matrix $A$ and an integer $i$ such that $1 \le i\le m$, remove row $i$ from $A$ (leaving an $(m-1) \times n$ matrix).

<a id="function-removecolumn-mtrx-rngintelt"></a>
##### `RemoveColumn(A, j): Mtrx, RngIntElt -> Mtrx`

<a id="procedure-removecolumn-mtrx-rngintelt-ref"></a>
##### `RemoveColumn(~A, j): Mtrx, RngIntElt`

Given an $m \times n$ matrix $A$ and an integer $j$ such that $1 \le j\le n$, remove column $j$ from $A$ (leaving an $m \times (n-1)$ matrix).

<a id="function-removerowcolumn-mtrx-rngintelt"></a>
##### `RemoveRowColumn(A, i, j): Mtrx, RngIntElt -> Mtrx`

<a id="procedure-removerowcolumn-mtrx-rngintelt-ref"></a>
##### `RemoveRowColumn(~A, i, j): Mtrx, RngIntElt`

Given an $m \times n$ matrix $A$ and integers $i$ and $j$ such that $1 \le i\le m$ and $1 \le j\le n$, remove row $i$ and column $j$ from $A$ (leaving an $(m-1) \times (n-1)$ matrix).

<a id="function-removezerorows-mtrx"></a>
##### `RemoveZeroRows(A): Mtrx -> Mtrx`

<a id="procedure-removezerorows-mtrx-ref"></a>
##### `RemoveZeroRows(~A): Mtrx`

Given a matrix $A$, remove all the zero rows of $A$.

<a id="example-ex-80d37c"></a>
##### `Example: Row and Column Operations (ex-80d37c)`

The use of row and column operations is illustrated by applying them to a $5 \times 6$ matrix over the ring of integers ${\mathbb{Z}}$.

```magma
> A := Matrix(5, 6,
>     [ 3, 1, 0, -4, 2, -12,
>       2, -4, -5, 5, 23, 6,
>       8, 0, 0, 1, 5, 12,
>       -2, -6, 3, 8, 9, 17,
>       11, 12, -6, 4, 2, 27 ]);
> A;
[  3   1   0  -4   2 -12]
[  2  -4  -5   5  23   6]
[  8   0   0   1   5  12]
[ -2  -6   3   8   9  17]
[ 11  12  -6   4   2  27]
> SwapColumns(~A, 1, 2);
> A;
[  1   3   0  -4   2 -12]
[ -4   2  -5   5  23   6]
[  0   8   0   1   5  12]
[ -6  -2   3   8   9  17]
[ 12  11  -6   4   2  27]
> AddRow(~A, 4, 1, 2);
> AddRow(~A, 6, 1, 4);
> AddRow(~A, -12, 1, 5);
> A;
[  1   3   0  -4   2 -12]
[  0  14  -5 -11  31 -42]
[  0   8   0   1   5  12]
[  0  16   3 -16  21 -55]
[  0 -25  -6  52 -22 171]
> RemoveRow(~A, 1);
> A;
[ 2 -4 -5  5 23  6]
[ 8  0  0  1  5 12]
[-2 -6  3  8  9 17]
[11 12 -6  4  2 27]
> RemoveRowColumn(~A, 4, 6);
> A;
[ 2 -4 -5  5 23]
[ 8  0  0  1  5]
[-2 -6  3  8  9]
```

### Building Block Matrices

Block matrices can be constructed either by listing the blocks, or by joining together smaller matrices horizontally, vertically, or diagonally.

<a id="function-blockmatrix-rngintelt-rngintelt-mtrx"></a>
#### `BlockMatrix(m, n, blocks): RngIntElt, RngIntElt, [ Mtrx ] -> Mtrx`

The matrix constructed from the given block matrices, which should all have the same dimensions, and should be given as a sequence of $m\cdot n$ block matrices (given in row major order, in other words listed across rows).

<a id="function-blockmatrix-rngintelt-rngintelt-mtrx-2"></a>
#### `BlockMatrix(m, n, rows): RngIntElt, RngIntElt, [ [ Mtrx ] ] -> Mtrx`

<a id="function-blockmatrix-mtrx"></a>
#### `BlockMatrix(rows): [ [ Mtrx ] ] -> Mtrx`

The matrix constructed from the given block matrices, which should all have the same dimensions, and should be given as a sequence of $m$ rows, each containing $n$ block matrices.

<a id="function-horizontaljoin-mtrx-mtrx"></a>
#### `HorizontalJoin(X, Y): Mtrx, Mtrx -> Mtrx`

Given a matrix $X$ with $r$ rows and $c$ columns, and a matrix $Y$ with $r$ rows and $d$ columns, both over the same coefficient ring $R$, return the matrix over $R$ with $r$ rows and $(c+d)$ columns obtained by joining $X$ and $Y$ horizontally (placing $Y$ to the right of $X$).

<a id="function-horizontaljoin-mtrx"></a>
#### `HorizontalJoin(Q): [ Mtrx ] -> Mtrx`

<a id="function-horizontaljoin-mtrx-2"></a>
#### `HorizontalJoin(T): < Mtrx > -> Mtrx`

Given a sequence $Q$ or tuple $T$ of matrices, each having the same number of rows and being over the same coefficient ring $R$, return the matrix over $R$ obtained by joining the elements of $Q$ or $T$ horizontally in order.

<a id="function-verticaljoin-mtrx-mtrx"></a>
#### `VerticalJoin(X, Y): Mtrx, Mtrx -> Mtrx`

Given a matrix $X$ with $r$ rows and $c$ columns, and a matrix $Y$ with $s$ rows and $c$ columns, both over the same coefficient ring $R$, return the matrix with $(r+s)$ rows and $c$ columns over $R$ obtained by joining $X$ and $Y$ vertically (placing $Y$ underneath $X$).

<a id="function-verticaljoin-mtrx"></a>
#### `VerticalJoin(Q): [ Mtrx ] -> Mtrx`

<a id="function-verticaljoin-mtrx-2"></a>
#### `VerticalJoin(T): < Mtrx > -> Mtrx`

Given a sequence $Q$ or tuple $T$ of matrices, each having the same number of columns and being over the same coefficient ring $R$, return the matrix over $R$ obtained by joining the elements of $Q$ or $T$ vertically in order.

<a id="function-diagonaljoin-mtrx-mtrx"></a>
#### `DiagonalJoin(X, Y): Mtrx, Mtrx -> Mtrx`

Given matrices $X$ with $a$ rows and $b$ columns and $Y$ with $c$ rows and $d$ columns, both over the same coefficient ring $R$, return the matrix with $(a+c)$ rows and $(b+d)$ columns over $R$ obtained by joining $X$ and $Y$ diagonally (placing $Y$ diagonally to the right of and underneath $X$, with zero blocks above and below the diagonal).

<a id="function-diagonaljoin-mtrx"></a>
#### `DiagonalJoin(Q): [ Mtrx ] -> Mtrx`

<a id="function-diagonaljoin-mtrx-2"></a>
#### `DiagonalJoin(T): < Mtrx > -> Mtrx`

Given a sequence $Q$ or tuple $T$ of matrices, each being over the same coefficient ring $R$, return the matrix over $R$ obtained by joining the elements of $Q$ or $T$ diagonally in order.

<a id="function-kroneckerproduct-mtrx-mtrx"></a>
#### `KroneckerProduct(A, B): Mtrx, Mtrx -> Mtrx`

Given an $m \times n$ matrix $A$ and a $p \times q$ matrix $B$, both over a ring $R$, return the Kronecker product of $A$ and $B$, which is the $mp\times nq$ matrix $C$ over $R$ such that the $((i-1)p+r, (j-1)q+s)$-th entry of $C$ is the $(i,j)$-th entry of $A$ times the $(r,s)$-th entry of $B$, for $1\leq i\le m$, $1\leq j\leq n$, $1\leq r\leq p$, and $1\leq s\leq q$.

### Changing Ring

<a id="function-changering-mtrx-rng"></a>
#### `ChangeRing(A, R): Mtrx, Rng -> Mtrx`

<a id="function-matrix-rng-mtrx"></a>
#### `Matrix(R, A): Rng, Mtrx -> Mtrx`

Given a matrix $A$ over a ring $S$ having $m$ rows and $n$ columns, and another ring $R$, return the $m\times n$ matrix over $R$ obtained by coercing the entries of $A$ from $S$ into $R$. The argument order to `ChangeRing(A, R)` here is consistent with other forms of `ChangeRing`, while the `Matrix(R, A)` form of this function is provided to be consistent with the matrix creation functions above, for which the destination ring is the first argument, if supplied.

<a id="function-changering-mtrx-rng-map"></a>
#### `ChangeRing(A, R, f): Mtrx, Rng, Map -> Mtrx`

<a id="function-changering-mtrx-map"></a>
#### `ChangeRing(A, f): Mtrx, Map -> Mtrx`

Given a matrix $A$ over a ring $S$ having $m$ rows and $n$ columns, another ring $R$, and a map $f:S \rightarrow R$, return the $m\times n$ matrix over $R$ obtained by applying $f$ to each of the entries of $A$. The $R$ may be omitted, in which case it is taken to be the codomain of $f$.

<a id="function-canchangering-mtrx-rng"></a>
#### `CanChangeRing(A, R): Mtrx, Rng -> BoolElt, Mtrx`

Return whether the entries in the matrix $A$ can be coerced into $R$ and the matrix resulting from `ChangeRing(A, R)` if so.

### Elementary Arithmetic

<a id="operation-op-plus-mtrx-mtrx"></a>
#### `A + B: Mtrx, Mtrx -> Mtrx`

Given $m \times n$ matrices $A$ and $B$ over a ring $R$, return $A+B$.

<a id="operation-op-minus-mtrx-mtrx"></a>
#### `A - B: Mtrx, Mtrx -> Mtrx`

Given $m \times n$ matrices $A$ and $B$ over a ring $R$, return $A-B$.

<a id="operation-op-times-mtrx-mtrx"></a>
#### `A * B: Mtrx, Mtrx -> Mtrx`

Given an $m \times n$ matrix $A$ over a ring $R$ and an $n \times p$ matrix $B$ over $R$, return the $m \times p$ matrix $A\cdot B$ over $R$. This function attempts to preserve the maximal amount of information in the choice of parent for the product. For example, if $A$ and $B$ are both square and have the same matrix algebra $M$ as parent, then the product will also have $M$ as parent. Similarly, if the parents of $A$ and $B$ are $R$-matrix spaces such that the codomain of $B$ equals the domain $A$, then the product will have domain equal to that of $A$ and codomain equal to that of $B$.

<a id="operation-op-times-rngelt-mtrx"></a>
#### `x * A: RngElt, Mtrx -> Mtrx`

<a id="operation-op-times-mtrx-rngelt"></a>
#### `A * x: Mtrx, RngElt -> Mtrx`

Given an $m \times n$ matrix $A$ over a ring $R$ and a ring element $x$ coercible into $R$, return the scalar product $x\cdot A$.

Note that if $x$ is not coercible into the ring $R$ then $A$ may be automatically coerced into the ring of $x$. On the other hand, one particular common case is that multiplying an integral matrix by the real number 1.0 will **not** coerce the matrix into the reals, as the scalar is coercible into the ring $R$ (the integers) in that case.

<a id="operation-operation-mtrx-mtrx"></a>
#### `- A: Mtrx -> Mtrx`

Given a matrix $A$, return $-A$.

<a id="operation-op-pow-mtrx-rngintelt"></a>
#### `A ^ -1: Mtrx, RngIntElt -> Mtrx`

Given a invertible square matrix $A$ over a ring $R$, return the inverse $B$ of $A$ so that $A\cdot B = B\cdot A = 1$. The coefficient ring $R$ must be either a field, a Euclidean domain, or a ring with an exact division algorithm and having characteristic equal to zero or greater than $m$ (this includes most commutative rings).

<a id="operation-op-pow-mtrx-rngintelt-2"></a>
#### `A ^ n: Mtrx, RngIntElt -> Mtrx`

Given a square matrix $A$ over a ring $R$ and an integer $n$, return the matrix power $A^n$. $A^0$ is defined to be the identity matrix for any square matrix $A$ (even if $A$ is zero). If $n$ is negative, $A$ must be invertible (see the previous function), and the result is $(A^{-1})^{-n}$.

<a id="function-transpose-mtrx"></a>
#### `Transpose(A): Mtrx -> Mtrx`

Given an $m \times n$ matrix $A$ over a ring $R$, return the transpose of $A$, which is simply the $n \times m$ matrix over $R$ whose $(i,j)$-th entry is the $(j,i)$-th entry of $A$.

<a id="function-addscaledmatrix-mtrx-rngelt-mtrx"></a>
#### `AddScaledMatrix(A, s, B): Mtrx, RngElt, Mtrx -> Mtrx`

Given a matrix $A$ over a ring $R$, a scalar $s$ coercible into $R$, and a matrix $B$ over $R$ with the same shape as $A$, return $A + s\cdot B$. This is generally quicker than the call `A + s*B`.

<a id="procedure-addscaledmatrix-mtrx-rngelt-mtrx-ref"></a>
#### `AddScaledMatrix(~A, s, B): Mtrx, RngElt, Mtrx`

Given a matrix $A$ over a ring $R$, a scalar $s$ coercible into $R$, and a matrix $B$ over $R$ with the same shape as $A$, set $A$ to $A+ s\cdot B$. This is generally quicker than the statement `A := A + s*B;`.

### Nullspaces and Solutions of Systems

The following functions compute nullspaces of matrices (solving equations of the form $V\cdot A=0$), or solve systems of the form $V\cdot A=W$, for given $A$ and $W$.

Magma possesses a very rich suite of internal algorithms for computing nullspaces of matrices efficiently, including a fast $p$-adic algorithm for matrices over ${\mathbb{Z}}$ and ${\mathbb{Q}}$, and also algorithms which take advantage of sparsity if it is present.

<a id="function-nullspace-mtrx"></a>
#### `Nullspace(A): Mtrx -> ModTupRng`

<a id="function-kernel-mtrx"></a>
#### `Kernel(A): Mtrx -> ModTupRng, Map`

Given an $m \times n$ matrix $A$ over a ring $R$, return the nullspace of $A$ (or the kernel of $A$, considered as a linear transformation or map), which is the $R$-space consisting of all vectors $v$ of length $m$ such that $v\cdot A = 0$. If the parent of $A$ is an $R$-matrix space, then the result will be the appropriate submodule of the domain of $A$. The function `Kernel(A)` also returns the inclusion map from the kernel into the domain of $A$, to be consistent with other forms of the `Kernel` function.

<a id="function-nullspacematrix-mtrx"></a>
#### `NullspaceMatrix(A): Mtrx -> ModTupRng`

<a id="function-kernelmatrix-mtrx"></a>
#### `KernelMatrix(A): Mtrx -> ModTupRng`

Given an $m \times n$ matrix $A$ over a ring $R$, return a basis matrix of the nullspace of $A$. This is a matrix $N$ having $m$ columns and the maximal number of independent rows subject to the condition that $N\cdot A = 0$. This function has the advantage that the nullspace is not returned as a $R$-space, so echelonization of the resulting nullspace may be avoided.

<a id="function-nullspaceoftranspose-mtrx"></a>
#### `NullspaceOfTranspose(A): Mtrx -> ModTupRng`

This function is equivalent to `Nullspace(Transpose(A))`, but may be more efficient in space for large matrices, since the transpose may not have to be explicitly constructed to compute the nullspace.

<a id="function-isconsistent-mtrx-mtrx"></a>
#### `IsConsistent(A, W): Mtrx, Mtrx -> BoolElt, Mtrx, ModTupRng`

Given an $m \times n$ matrix $A$ over a ring $R$, and a vector $W$ of length $n$ over $R$ or a $r \times n$ matrix $W$ over $R$, return `true` iff and only if the system of linear equations $V\cdot A = W$ is consistent. If the system is consistent, then the function will also return:

**(a)**
A particular solution $V$ so that $V\cdot A = W$;

**(b)**
The nullspace $N$ of $A$ so that adding any elements of $N$ to any rows of $V$ will yield other solutions to the system.

<a id="function-isconsistent-mtrx-modtuprng"></a>
#### `IsConsistent(A, Q): Mtrx, [ ModTupRng ] -> BoolElt, [ ModTupRngElt ], ModTupRng`

Given an $m \times n$ matrix $A$ over a ring $R$, and a sequence $Q$ of vectors of length $n$ over $R$, return `true` if and only if the system of linear equations $V[i]*A = Q[i]$ for all $i$ is consistent. If the system is consistent, then the function will also return:

**(a)**
A particular solution sequence $V$;

**(b)**
The nullspace $N$ of $A$ so that $(V[i] + u) * A = Q[i]$ for $u\in N$ for all $i$.

<a id="function-solution-modmatrngelt-modtuprng"></a>
#### `Solution(A, W): ModMatRngElt, ModTupRng -> ModTupRngElt, ModTupRng`

Given an $m \times n$ matrix $A$ over a ring $R$, and a vector $W$ of length $n$ over $R$ or a $r \times n$ matrix $W$ over $R$, solve the system of linear equations $V\cdot A = W$ and return:

**(a)**
A particular solution $V$ so that $V\cdot A = W$;

**(b)**
The nullspace $N$ of $A$ so that adding any elements of $N$ to any rows of $V$ will yield other solutions to the system. If there is no solution, an error results.

<a id="function-solution-modmatrngelt-modtuprng-2"></a>
#### `Solution(A, Q): ModMatRngElt, [ ModTupRng ] -> [ ModTupRngElt ], ModTupRng`

Given an $m \times n$ matrix $A$ over a ring $R$, and a sequence $Q$ of vectors of length $n$ over $R$, solve the system of linear equations $V[i]*A = Q[i]$ for each $i$ and return:

**(a)**
A particular solution sequence $V$;

**(b)**
The nullspace $N$ of $A$ so that $(V[i] + u) * A = Q[i]$ for $u\in N$ for all $i$. If there is no solution, an error results.

<a id="example-ex-a44c79"></a>
#### `Example: Nullspace of a Random Integer Matrix (ex-a44c79)`

We compute the nullspace of a $301\times 300$ matrix over ${\mathbb{Z}}$ with random entries in the range $[0 .. 10]$. The nullity is 1 and the entries of the non-zero null vector are integers, each having about 455 decimal digits.

```magma
> m := 301; n := 300;
> X := Matrix(n, [Random(0, 10): i in [1 .. m*n]]);
> time N := NullspaceMatrix(X);
Time: 9.519
> Nrows(N), Ncols(N);
1 301
> time IsZero(N*X);
true
Time: 0.429
> {#Sprint(N[1,i]): i in [1..301]};
{ 452, 455, 456, 457, 458 }
```

<a id="example-ex-83882a"></a>
#### `Example: Enumerating All Solutions of a System (ex-83882a)`

We show how one can enumerate all solutions to the system $V\cdot X=W$ for a given matrix $X$ and vector $W$ over a finite field. The `Solution` function gives a particular solution for $V$, and then adding this to every element in the nullspace $N$ of $X$, we obtain all solutions.

```magma
> K := GF(3);
> X := Matrix(K, 4, 3, [1,2,1, 2,2,2, 1,1,1, 1,0,1]);
> X;
[1 2 1]
[2 2 2]
[1 1 1]
[1 0 1]
> W := Vector(K, [0,1,0]);
> V, N := Solution(X, W);
> V;
(1 1 0 0)
> N;
Vector space of degree 4, dimension 2 over GF(3)
Echelonized basis:
(1 0 1 1)
(0 1 1 0)
> [V + U: U in N];
[
    (1 1 0 0),
    (2 1 1 1),
    (0 1 2 2),
    (0 2 0 2),
    (1 2 1 0),
    (2 2 2 1),
    (2 0 0 1),
    (0 0 1 2),
    (1 0 2 0)
]
> [(V + U)*X eq W: U in N];
[ true, true, true, true, true, true, true, true, true ]
```

### Predicates

The functions in this section test various properties of matrices. See also the Lattices chapter for a description of the function [`IsPositiveDefinite`](https://docs.magma-maths.org/LatticesQuadraticForms/Lattices/definite.md#function-lat-ispositivedefinite) and related functions.

<a id="function-iszero-mtrx"></a>
#### `IsZero(A): Mtrx -> BoolElt`

Given an $m \times n$ matrix $A$ over the ring $R$, return `true` iff $A$ is the $m \times n$ zero matrix.

<a id="function-isone-mtrx"></a>
#### `IsOne(A): Mtrx -> BoolElt`

Given a square $m \times m$ matrix $A$ over the ring $R$, return `true` iff $A$ is the $m \times m$ identity matrix.

<a id="function-isminusone-mtrx"></a>
#### `IsMinusOne(A): Mtrx -> BoolElt`

Given a square $m \times m$ matrix $A$ over the ring $R$, return `true` iff $A$ is the negation of the $m \times m$ identity matrix.

<a id="function-isscalar-mtrx"></a>
#### `IsScalar(A): Mtrx -> BoolElt`

Given a square $m \times m$ matrix $A$ over the ring $R$, return `true` iff $A$ is scalar, i.e., iff $A$ is the product of some element of $R$ and the $m \times m$ identity matrix.

<a id="function-isdiagonal-mtrx"></a>
#### `IsDiagonal(A): Mtrx -> BoolElt`

Given a square matrix $A$ over the ring $R$, return `true` iff $A$ is diagonal, i.e., iff the only non-zero entries of $A$ are on the diagonal.

<a id="function-issymmetric-mtrx"></a>
#### `IsSymmetric(A): Mtrx -> BoolElt`

Given a square matrix $A$ over the ring $R$, return `true` iff $A$ is symmetric, i.e., iff $A$ equals its transpose.

<a id="function-ishermitian-mtrx-map"></a>
#### `IsHermitian(A, f): Mtrx, Map -> BoolElt`

Given a square matrix $A$ over the ring $R$, and an involution $f : R \to R$, return `true` iff $A$ is Hermitian with respect to $f$, i.e., iff $A$ equals applying $f$ to its transpose.

<a id="function-isuppertriangular-mtrx"></a>
#### `IsUpperTriangular(A): Mtrx -> BoolElt`

Given a matrix $A$ over the ring $R$, return `true` iff $A$ is upper triangular, i.e., iff the only non-zero entries of $A$ are on or above the diagonal.

<a id="function-islowertriangular-mtrx"></a>
#### `IsLowerTriangular(A): Mtrx -> BoolElt`

Given a matrix $A$ over the ring $R$, return `true` iff $A$ is lower triangular, i.e., iff the only non-zero entries of $A$ are on or below the diagonal.

<a id="function-isunit-mtrx"></a>
#### `IsUnit(A): Mtrx -> BoolElt`

Given a square matrix $A$ over the ring $R$, return `true` iff $A$ is a unit, i.e., iff $A$ has an inverse. The coefficient ring $R$ may be any commutative ring (since the computation depends on testing if the determinant is a unit – a calculation which is supported in all commutative rings).

<a id="function-issingular-mtrx"></a>
#### `IsSingular(A): Mtrx -> BoolElt`

Given a square $m \times m$ matrix $A$ over the ring $R$, return `true` iff $A$ is singular, i.e., iff the determinant of $A$ is zero (or, equivalently, iff the rank of $A$ is less than $m$). Note that `(not IsSingular(A))` is *not* equivalent to `IsUnit(A)` whenever $R$ is not a field: if the determinant of $A$ is non-zero but not a unit, then $A$ is non-singular but not invertible. The coefficient ring $R$ may be any commutative ring (since the computation involves only computing the determinant and testing whether it is zero).

<a id="function-issymplecticmatrix-mtrx"></a>
#### `IsSymplecticMatrix(A): Mtrx -> BoolElt`

Given an $m \times m$ matrix $A$ over the integers, return `true` if and only if $A$ is an integer symplectic matrix, that is, $AJ{}^tA = J$, where $J = \left(\begin{matrix}0 & {\bf 1}_g \\ -{\bf 1}_g & 0\end{matrix}\right).$

### Determinant and Other Properties

<a id="function-determinant-mtrx"></a>
#### `Determinant(A: parameters): Mtrx -> RngElt`

```magma
MonteCarloLevel: RngIntElt                    Default: 0
Proof          : BoolElt                      Default: true
pAdic          : BoolElt                      Default: true
Divisor        : RngIntElt                    Default: 0
```

Given a square matrix $A$ over the ring $R$, return the determinant of $A$ as an element of $R$. $R$ may be any commutative ring. The determinant of the $0 \times 0$ matrix over $R$ is defined to be `R!1`. If the coefficient ring is the integer ring ${\mathbb{Z}}$ or the rational field ${\mathbb{Q}}$ then a modular algorithm based on that of Abbott et al. [[ABM99](https://docs.magma-maths.org/references.md#cite-abm-det)] is used, which first computes a divisor $d$ of the determinant $D$ using a fast $p$-adic nullspace computation, and then computes the quotient $D/d$ by computing the determinant $D$ modulo enough small primes to cover the Hadamard bound divided by $d$. This always yields a correct answer. If the parameter `MonteCarloLevel` is set to a small positive integer $s$, then a probabilistic Monte-Carlo modular technique is used. Rather than using sufficient primes to cover the Hadamard bound divided by the divisor $d$, this version of the algorithm terminates when the constructed residue remains constant for $s$ steps. The probability of this being wrong is non-zero but extremely small, even if $s$ is only 1 or 2. If the level is set to 0, then the normal deterministic algorithm is used. Setting the parameter `Proof` to `false` is equivalent to setting `MonteCarloLevel` to 2. If the coefficient ring is ${\mathbb{Z}}$ and the parameter `Divisor` is set to an integer $d$, then $d$ must be a known exact divisor of the determinant (the sign does not matter), and the algorithm may be sped up because of this knowledge.

<a id="function-trace-mtrx"></a>
#### `Trace(A): Mtrx -> RngElt`

Given a square matrix $A$ over the ring $R$, return the trace of $A$ as an element of $R$, which is simply the sum of the diagonal elements of $A$.

<a id="function-traceofproduct-mtrx-mtrx"></a>
#### `TraceOfProduct(A, B): Mtrx, Mtrx -> RngElt`

Given square matrices $A$ and $B$ over the ring $R$, with the same size, return the trace of $A\cdot B$ as an element of $R$. This is in general much faster than the call `Trace(A*B)`.

<a id="function-rank-mtrx"></a>
#### `Rank(A): Mtrx -> RngIntElt`

Given an $m \times n$ matrix $A$ over a ring $R$, return the rank of $A$. This is defined to be the largest $r$ such that there exists a non-zero $r \times r$ subdeterminant of $A$, so $r\leq m$ and $r \leq n$. The rank may have to be obtained by computing the Smith form or echelon form of $A$, and this computation may be quite expensive over some rings.

<a id="function-minor-mtrx-rngintelt-rngintelt"></a>
#### `Minor(M, i, j): Mtrx, RngIntElt, RngIntElt -> RngElt`

The determinant of the submatrix of $M$ (which must be square) formed by removing the $i$-th row and $j$-th column.

<a id="function-minor-mtrx-rngintelt-rngintelt-2"></a>
#### `Minor(M, I, J): Mtrx, [RngIntElt], [RngIntElt] -> RngElt`

The determinant of the submatrix of $M$ given by the row indices in $I$ and the column indices in $J$.

<a id="function-minors-mtrx-rngintelt"></a>
#### `Minors(M, r): Mtrx, RngIntElt -> SeqEnum`

Returns a sequence of all the $r$ by $r$ minors of the matrix $M$.

<a id="function-cofactor-mtrx-rngintelt-rngintelt"></a>
#### `Cofactor(M, i, j): Mtrx, RngIntElt, RngIntElt -> RngElt`

The appropriate cofactor of $M$, equal to $(-1)^{i+j}$ times the corresponding minor.

<a id="function-cofactors-mtrx"></a>
#### `Cofactors(M): Mtrx -> SeqEnum`

Returns a sequence of all the cofactors of the matrix $M$.

<a id="function-cofactors-mtrx-rngintelt"></a>
#### `Cofactors(M, r): Mtrx, RngIntElt -> SeqEnum`

Returns a sequence of all the $r$ by $r$ cofactors of the matrix $M$.

<a id="function-pfaffian-mtrx"></a>
#### `Pfaffian(M): Mtrx -> RngElt`

<a id="function-pfaffian-mtrx-rngintelt-rngintelt"></a>
#### `Pfaffian(M, I, J): Mtrx, [RngIntElt], [RngIntElt] -> RngElt`

<a id="function-pfaffians-mtrx-rngintelt"></a>
#### `Pfaffians(M, r): Mtrx, RngIntElt -> SeqEnum`

Let $M$ be an anti-symmetric square matrix. Then its determinant is always a square and a particular square-root of this, which can be described by a universal polynomial in its entries, is called the Pfaffian of $M$. The first function returns this. The second function returns the Pfaffian of the submatrix of $M$ described by the indices in $I$ and $J$. The third function returns the sequence of Pfaffians of the ${n \choose r}$ principal $r$ by $r$ submatrices of $M$ ($n=$ the number of rows of $M$).

These are primarily convenience functions and are computed naively by Pfaffian row-expansion.

<a id="properties-2"></a>
<a id="sec-matmincharpoly"></a>
### Minimal and Characteristic Polynomials and Eigenvalues

The functions in this section deal with minimal and characteristic polynomials.

<a id="function-minimalpolynomial-mtrx"></a>
#### `MinimalPolynomial(A: parameters): Mtrx -> RngUPolElt`

```magma
Proof: BoolElt                    Default: true
```

Given a square matrix $A$ over a ring $R$, return the minimal polynomial of $A$. This is defined to be the unique monic univariate polynomial $f(x)$ of minimal degree such that $f(A) = 0$, and $f(x)$ always divides the characteristic polynomial of $A$. The coefficient ring $R$ is currently restricted to being a field or the integer ring ${\mathbb{Z}}$. Setting the parameter `Proof` to false suppresses proof of correctness.

<a id="function-characteristicpolynomial-mtrx"></a>
#### `CharacteristicPolynomial(A: parameters): Mtrx -> RngUPolElt`

```magma
Al   : MonStg                     Default: "Modular"
Proof: BoolElt                    Default: true
```

Given a square matrix $A$ over a ring $R$, return the characteristic polynomial of $A$. This is defined to be the monic univariate polynomial $\operatorname{Det}(x-A)\in R[x]$ where $R[x]$ is the univariate polynomial ring over $R$. $R$ may be any commutative ring. The parameter `Al` allows the user to specify which algorithm that is to be employed. The algorithm `"Modular"` (the default) may be used for matrices over $\Z$ and $\Q$—in such a case the parameter `Proof` can also be used to suppress proof of correctness. The algorithm `"Hessenberg"`, available for matrices over fields, works by first reducing the matrix to Hessenberg form. The algorithm `"Interpolation"`, available for matrices over $Z$ and $Q$, works by evaluating the characteristic matrix of $a$ at various points and then interpolating. The algorithm `"Trace"`, available for matrices over fields, works by calculating the traces of powers of $a$. Since V2.8, none of these algorithms are now recommended for matrices over $\Z$ or $\Q$, as the new $p$-adic modular algorithm over the integers is extremely fast.

<a id="function-minimalandcharacteristicpolynomials-mtrx"></a>
#### `MinimalAndCharacteristicPolynomials(A: parameters): Mtrx -> RngUPolElt, RngUPolElt`

<a id="function-mcpolynomials-mtrx"></a>
#### `MCPolynomials(A): Mtrx -> RngUPolElt, RngUPolElt`

```magma
Proof: BoolElt                    Default: true
```

Given a square matrix $A$ over a ring $R$, return the minimal and characteristic polynomials of $A$. For some rings, both polynomials can be computed at the same time, so in such cases it will be more efficient to use this function than to call `MinimalPolynomial` and `CharacteristicPolynomials` separately. Setting the parameter `Proof` to false suppresses proof of correctness.

<a id="function-factoredminimalpolynomial-mtrx"></a>
#### `FactoredMinimalPolynomial(A: parameters): Mtrx -> [ <RngUPolElt, RngIntElt>]`

```magma
Proof: BoolElt                    Default: true
```

Given a square matrix $A$ over a ring $R$, return the factorization of the minimal polynomial of $A$. This is equivalent to `Factorization(MinimalPolynomial(A))`, but may be faster than that for some coefficient rings (in particular, ${\mathbb{Z}}$ and ${\mathbb{Q}}$). Setting the parameter `Proof` to false suppresses proof of correctness.

<a id="function-factoredcharacteristicpolynomial-mtrx"></a>
#### `FactoredCharacteristicPolynomial(A: parameters): Mtrx -> [ <RngUPolElt, RngIntElt>]`

```magma
Al   : MonStg                     Default: "Modular"
Proof: BoolElt                    Default: true
```

Given a square matrix $A$ over a ring $R$, return the factorisation of the characteristic polynomial of $A$. This function returns the same result as the command `Factorisation(CharacteristicPolynomial(A))`, but may be faster than that for some coefficient rings (in particular, ${\mathbb{Z}}$ and ${\mathbb{Q}}$). The parameters are as for the function `CharacteristicPolynomial` above (setting the parameter `Proof` to false suppresses proof of correctness).

<a id="function-factoredminimalandcharacteristicpolynomials-mtrx"></a>
#### `FactoredMinimalAndCharacteristicPolynomials(A: parameters): Mtrx -> [<RngUPolElt, RngIntElt>], [<RngUPolElt, RngIntElt>]`

<a id="function-factoredmcpolynomials-mtrx"></a>
#### `FactoredMCPolynomials(A: parameters): Mtrx -> [<RngUPolElt, RngIntElt>], [<RngUPolElt, RngIntElt>]`

```magma
Al   : MonStg                     Default: "Modular"
Proof: BoolElt                    Default: true
```

Given a square matrix $A$ over a ring $R$, return the factorizations of the minimal and characteristic polynomials of $A$, respectively. For some rings, both polynomials can be computed and factored at the same time, so in such cases it will be more efficient to use this function than to call the above functions separately. Setting the parameter `Proof` to false suppresses proof of correctness.

<a id="function-eigenvalues-mtrx"></a>
#### `Eigenvalues(A): Mtrx -> { <FldElt, RngIntElt> }`

Given a square matrix $A$ over a ring $R$, return the eigenvalues of $A$ as a set of pairs, each of which gives the value of a distinct eigenvalue and its multiplicity. Factorization of polynomials over the base ring $R$ must be possible.

<a id="function-eigenspace-algmatelt-fldelt"></a>
#### `Eigenspace(A, e): AlgMatElt, FldElt -> ModTup`

Given a square matrix $A$ over a ring $R$, and an element $e$ of $R$, return the eigenspace of $A$ corresponding to $e$, which is `Nullspace(A - e)`. If the ring element $e$ is not a eigenvalue for the matrix $A$ then the trivial nullspace is returned.

### Canonical Forms

#### Canonical Forms over General Rings

The functions defined here apply to matrices defined over fields or Euclidean domains. See also the section on Reduction in the Lattices chapter for a description of the function [`LLL`](https://docs.magma-maths.org/LatticesQuadraticForms/Lattices/reduction.md#function-lat-lll) and related basis-reduction functions for matrices.

<a id="function-echelonform-mtrx"></a>
##### `EchelonForm(A): Mtrx -> Mtrx, AlgMatElt`

Given an $m \times n$ matrix $A$ over the ring $R$, return the (reduced) row echelon form $E$ of $A$, and also an invertible $m \times m$ transformation matrix $T$ over $R$ such that $T\cdot A = E$. Recall that $T$ is a product of elementary matrices that transforms $A$ into the echelon form $E$. If $R$ is a Euclidean domain, the function [`HermiteForm`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-mat-hermiteform) (described below) is invoked. Note however, that the user cannot set the parameters for [`HermiteForm`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-mat-hermiteform) when invoking it via `EchelonForm`.

<a id="function-adjoint-mtrx"></a>
##### `Adjoint(A): Mtrx -> AlgMatElt`

Given a square $m \times m$ matrix $A$ over the ring $R$, return the adjoint of $A$ as an $m \times m$ matrix. The base ring $R$ must be a ring with exact division whose characteristic is zero or greater than $m$ (this includes most commutative rings).

#### Canonical Forms over Fields

The functions described in this section apply to square matrices defined over fields which support factorization of univariate polynomials. See [[Ste97](https://docs.magma-maths.org/references.md#cite-steel-canonical)] for a description of the single algorithm which is the basis of most of these functions.

<a id="function-primaryrationalform-mtrx"></a>
##### `PrimaryRationalForm(A): Mtrx -> AlgMatElt, AlgMatElt, [ <RngUPolElt, RngIntElt ]`

Given a square matrix $A$ over a field $K$ such that factorization of polynomials is possible over $K$, return the primary rational form of $A$. Each block in the form is the companion matrix of a power of an irreducible polynomial. This function returns three values:

**(a)**
The primary rational canonical form $F$ of $A$;

**(b)**
An invertible matrix $T$ such that $T\cdot A\cdot T^{-1} = F$;

**(c)**
A sequence of pairs corresponding to the blocks of $F$ where each pair consists of the irreducible polynomial and the multiplicity making up the block. This is the value returned by `PrimaryInvariantFactors(A)`.

<a id="function-jordanform-mtrx"></a>
##### `JordanForm(A): Mtrx -> Mtrx, AlgMatElt, [ <RngUPolElt, RngIntElt> ]`

Given a square matrix $A$ over a field $K$ such that factorization of polynomials is possible over $K$, return the generalized Jordan form of $A$. Each block in the form is a Jordan block (which itself is derived from a power of an irreducible polynomial), and the generalized Jordan form corresponds to the usual Jordan form if the minimal polynomial splits over $K$. This function returns three values:

**(a)**
The Jordan canonical form $F$ of $A$;

**(b)**
An invertible matrix $T$ such that $T\cdot A\cdot T^{-1} = F$;

**(c)**
A sequence of pairs corresponding to the blocks of $F$ where each pair consists of the irreducible polynomial and the multiplicity making up the block. This is the value returned by `PrimaryInvariantFactors(A)`.

<a id="function-rationalform-mtrx"></a>
##### `RationalForm(A): Mtrx -> Mtrx, AlgMatElt, [ RngUPolElt ]`

Given a square matrix $A$ over a field $K$ such that factorization of polynomials is possible over $K$, return the rational form of $A$. For each block other than the final block, the polynomial corresponding to that block divides the polynomial corresponding to the next block. This function returns three values:

**(a)**
The rational form $F$ of $A$;

**(b)**
An invertible matrix $T$ such that $T\cdot A\cdot T^{-1} = F$;

**(c)**
A sequence containing the polynomials corresponding to the successive blocks (where each polynomial, other than the last, divides the next polynomial). This is the value returned by `InvariantFactors(A)`.

<a id="function-primaryinvariantfactors-mtrx"></a>
##### `PrimaryInvariantFactors(A): Mtrx -> [ <RngUPolElt, RngIntElt> ]`

Given a square matrix $A$ over a field $K$ such that factorization of polynomials is possible over $K$, return the primary invariant factors of $A$. This is the same as the third return value of `PrimaryRationalForm(A)` or `JordanForm(A)`.

<a id="function-invariantfactors-mtrx"></a>
##### `InvariantFactors(A): Mtrx -> [ RngUPolElt ]`

Given a square matrix $A$ over a field $K$ such that factorization of polynomials is possible over $K$, return the invariant factors of $A$. This is the same as the third return value of `RationalForm(A)`.

<a id="function-issimilar-algmatelt-algmatelt"></a>
##### `IsSimilar(A, B): AlgMatElt, AlgMatElt -> BoolElt, AlgMatElt`

Given square $m \times m$ matrices $A$ and $B$, both over a field $K$ such that factorization of polynomials is possible over $K$, return `true` iff and only if $A$ is similar to $B$, and if so, return also an invertible $m \times m$ transformation matrix $T$ such that $T\cdot A\cdot T^{-1} = B$.

<a id="function-hessenbergform-mtrx"></a>
##### `HessenbergForm(A): Mtrx -> AlgMatElt`

Given a square $m \times m$ matrix $A$ over the ring $R$, return the Hessenberg form of $A$ as an $m \times m$ matrix. The form has zero entries above the super-diagonal. (This form is used in one of the characteristic polynomial algorithms.) The base ring $R$ must be a field.

<a id="function-frobeniusformalternating-algmatelt"></a>
##### `FrobeniusFormAlternating(A): AlgMatElt -> SeqEnum`

Given a non-singular $2n \times 2n$ alternating matrix $A$ over the integers, this function returns the (alternating) Frobenius form $F$ of $A$. That is, a block matrix $F = \left(\begin{matrix}0 & D \\ -D & 0\end{matrix}\right),$ where $D$ is a diagonal matrix with positive diagonal entries, $d_i$, satisfying $d_1 | d_2 | \cdots | d_n$. The second return value is the change of basis matrix $B$, such that $BA {}^tB = F.$

<a id="example-ex-1f87a1"></a>
##### `Example: Canonical Forms over a Finite Field (ex-1f87a1)`

We construct a $5 \times 5$ matrix over the finite field with 5 elements and then calculate various canonical forms. We verify the correctness of the polynomial invariant factors corresponding to the rational form by calculating the Smith form of the characteristic matrix of the original matrix (see below).

```magma
> K := GF(5);
> A := Matrix(K, 5,
>     [ 0, 2, 4, 2, 0,
>       2, 2, 2, 3, 3,
>       3, 4, 4, 1, 3,
>       0, 0, 0, 0, 1,
>       0, 0, 0, 1, 0 ]);
> A;
[0 2 4 2 0]
[2 2 2 3 3]
[3 4 4 1 3]
[0 0 0 0 1]
[0 0 0 1 0]
> PrimaryInvariantFactors(A);
[
    <x + 1, 1>,
    <x + 1, 1>,
    <x + 4, 1>,
    <x + 4, 1>,
    <x + 4, 1>
]
> JordanForm(A);
[4 0 0 0 0]
[0 4 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
> R, T, F := RationalForm(A);
> R;
[1 0 0 0 0]
[0 0 1 0 0]
[0 1 0 0 0]
[0 0 0 0 1]
[0 0 0 1 0]
> T;
[1 3 0 2 1]
[2 1 2 2 0]
[3 4 3 4 1]
[1 0 0 0 0]
[0 2 4 2 0]
> T*A*T^-1 eq R;
true;
> F;
[
    x + 4,
    x^2 + 4,
    x^2 + 4
]
> P<x> := PolynomialRing(K);
> PM := MatrixAlgebra(P, 5);
> Ax := PM ! x - PM ! A;
> Ax;
[    x     3     1     3     0]
[    3 x + 3     3     2     2]
[    2     1 x + 1     4     2]
[    0     0     0     x     4]
[    0     0     0     4     x]
> SmithForm(Ax);
[      1       0       0       0       0]
[      0       1       0       0       0]
[      0       0   x + 4       0       0]
[      0       0       0 x^2 + 4       0]
[      0       0       0       0 x^2 + 4]
> ElementaryDivisors(Ax);
[
    1,
    1,
    x + 4,
    x^2 + 4,
    x^2 + 4
]
```

#### Canonical Forms over Euclidean Domains

The functions defined here apply to matrices defined over Euclidean domains. See also the section on Reduction in the Lattices chapter for a description of the function [`LLL`](https://docs.magma-maths.org/LatticesQuadraticForms/Lattices/reduction.md#function-lat-lll) and related functions, which are very useful for integer matrices.

<a id="function-mat-hermiteform"></a>
##### `HermiteForm(A): Mtrx -> Mtrx, ModMatRngElt`

```magma
Al      : MonStg                     Default: "Default"
Optimize: BoolElt                    Default: true
Integral: BoolElt                    Default: true
```

Given an $m \times n$ matrix $A$ over the Euclidean ring $R$, return the Hermite form $H$ of $A$, and also an invertible $m \times m$ transformation matrix $T$ over $R$ such that $T\cdot A = H$. The basic algorithm used is the classical Kannan-Bachem algorithm [[CC82](https://docs.magma-maths.org/references.md#cite-choucollins), [KB79](https://docs.magma-maths.org/references.md#cite-kannanbachem)], which has classical complexity (but does not suffer from bad coefficient growth). Since V2.13, for matrices over the integers there is also a fast modular algorithm by Allan Steel. By default, Magma chooses between these two algorithms, usually favouring the new modular algorithm. But one may set the parameter `Al` to `"Modular"` to force the modular algorithm to be used, and to `"Classical"` to force the classical algorithm to be used. If $R$ is the ring of integers ${\mathbb{Z}}$ and the matrix $T$ is requested (i.e., if an assignment statement is used with two variables on the left side), then the LLL algorithm will also be used by default to improve $T$ (using the kernel of $A$) so that the size of its entries are very small. If the parameter `Optimize` is set to $\texttt{false}$, then this will not happen (which will be faster but the entries of $T$ will not be as small). If the parameter `Integral` is set to $\texttt{true}$, then the integral (de Weger) LLL method will be used in the LLL step, instead of the default floating point method.

<a id="function-mat-smithform"></a>
##### `SmithForm(A): ModMatRngElt -> ModMatRngElt, ModMatRngElt, ModMatRngElt`

Given an $m \times n$ matrix $A$ over the Euclidean ring $R$, return the Smith normal form of $A$. This function returns three values:

**(a)**
The Smith normal form $S$ of $A$; and

**(b)**
Unimodular matrices $P$ and $Q$ such that $P\cdot A\cdot Q = S$, i.e., $P$ and $Q$ are matrices which transform $A$ into Smith normal form. The algorithm implemented first uses the sparse techniques described in [[HHR93](https://docs.magma-maths.org/references.md#cite-hhr-smith)] to reduce the matrix to a dense submatrix, then, if this is non-trivial, it either repeatedly calls the Hermite normal form algorithm (see above) and transposes until a diagonal form is obtained, or uses the modular algorithm of F. Lübeck [[Lub02](https://docs.magma-maths.org/references.md#cite-luebeck-smithform)]. Unless one wishes one or both of the transformation matrices, it is preferable to use the following function `ElementaryDivisors` since it gives the same information, but saves memory since the matrix $S$ does not need to be constructed.

<a id="function-elementarydivisors-mtrx"></a>
##### `ElementaryDivisors(A): Mtrx -> [RngElt]`

Given an $m \times n$ matrix $A$ over the Euclidean ring or field $R$, return the elementary divisors of $A$. These are simply the non-zero diagonal entries of the Smith form of $A$, in order. The divisors are returned as a sequence $[e_1, \ldots, e_r]$ of $r$ elements of $R$ (which may include ones), where $r$ is the rank of $A$ and $e_i | e_{i+1}$ for $i=1, \ldots, r-1$. The divisors are normalized, so the result is unique. If $R$ is a field, the result is always the sequence of $r$ ones, where $r$ is the rank of $A$. Note that if $m=n=r$, then the determinant of $A$ is the product of the $e_i$ and if $R$ is also a domain, then $e_r$ is the lowest common denominator of the inverse of $A$ over the field of fractions of $R$.

<a id="function-mat-saturation"></a>
##### `Saturation(A): Mtrx -> Mtrx`

Given an $m \times n$ matrix $A$ over the integer ring ${\mathbb{Z}}$, having rank $r$, return an $m \times n$ matrix $S$ over ${\mathbb{Z}}$ whose first $r$ rows form a basis of the saturation w.r.t. ${\mathbb{Q}}$ of the ${\mathbb{Q}}$-vector space spanned by the rows of $A$. The rows of $S$ thus span the same space over ${\mathbb{Q}}$ as those of $A$, while the ${\mathbb{Z}}$-module spanned by the rows of $S$ is the set of all $v$ such that for some non-zero scalar $s$, $s\cdot v$ is in the ${\mathbb{Z}}$-module spanned by the rows of $A$.

<a id="example-ex-bd35e5"></a>
##### `Example: Echelon Forms over a Field and the Integers (ex-bd35e5)`

We illustrate some of these operations for a $4\times 3$ matrix over ${\bf F}_{8}$.

```magma
> K<w> := GF(8);
> A := Matrix(K, 4, 3, [1,w,w^5, 0,w^3,w^4, w,1,w^6, w^3,1,w^4]);
> A;
[  1   w w^5]
[  0 w^3 w^4]
[  w   1 w^6]
[w^3   1 w^4]
> EchelonForm(A);
[  1   0   0]
[  0   1   0]
[  0   0   1]
[  0   0   0]
```

We now illustrate some of these operations for a $4\times 5$ matrix over ${\mathbb{Z}}$.

```magma
> A := Matrix(4, 5,
>     [ 2,-4,12,7,0,
>       3,-3,5,-1,4,
>       2,-1,-4,-5,-12,
>       0,3,6,-2,0]);
> A;
[  2  -4  12   7   0]
[  3  -3   5  -1   4]
[  2  -1  -4  -5 -12]
[  0   3   6  -2   0]
> Rank(A);
4
> HermiteForm(A);
[   1    1    1    6 -164]
[   0    3    0   16 -348]
[   0    0    2   13 -200]
[   0    0    0   19 -316]
> SmithForm(A);
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 2 0]
> ElementaryDivisors(A);
[ 1, 1, 1, 2 ]
```

### Orders of Invertible Matrices

The functions defined here apply to invertible square matrices. Magma can efficiently compute the order of an invertible matrix over a finite field, using the Cunningham database to factorize the numbers of the form $p^n-1$ which arise. The algorithm employed is that described in [[CLG97b](https://docs.magma-maths.org/references.md#cite-clg-order)].

Magma also contains efficient algorithms for rigorously proving whether a matrix over the ring of integers $\Z$, the rational field $\Q$, an algebraic number field, a cyclotomic field, or a quadratic field has finite order or not, and for determining the order if it is finite.

<a id="function-hasfiniteorder-mtrx"></a>
#### `HasFiniteOrder(A): Mtrx -> BoolElt`

Given a square invertible matrix $A$ over a ring $R$, return `true` iff $A$ has finite order, i.e., iff there exists a positive integer $n$ such that $A^n=1$. The coefficient ring $R$ is currently restricted to being either a finite field, the ring of integers $\Z$, the rational field $\Q$, an algebraic number field, a cyclotomic field, or a quadratic field. For matrices over any of these rings, the function rigorously proves its result (over other rings, an error results).

<a id="function-order-algmatelt"></a>
#### `Order(A): AlgMatElt -> RngIntElt`

```magma
Proof: BoolElt                    Default: true
```

Given a square invertible matrix $A$ over any commutative ring, return the order of $A$. If $R$ is a ring for which a finite order proof exists (see `HasFiniteOrder` above), then an error results if $A$ has infinite order. Over other rings, if $A$ has infinite order then the function may loop indefinitely since it may not be able to prove the infinitude of the order.

<a id="function-factoredorder-algmatelt"></a>
#### `FactoredOrder(A): AlgMatElt -> [ <RngIntElt, RngIntElt> ]`

```magma
Proof: BoolElt                    Default: true
```

Given a square invertible matrix $A$ over a finite field, return the order of $A$ in factored form. This returns the same value as `Factorization(Order(A))`, but since the order computation must compute the factorization of the order anyway, it involves no more effort to have it return the factorization. The conditions on the ring are as for `Order`.

<a id="function-projectiveorder-algmatelt"></a>
#### `ProjectiveOrder(A): AlgMatElt -> RngIntElt, RngElt`

```magma
Proof: BoolElt                    Default: true
```

Given a square invertible matrix $A$ over a finite field $K$, return the projective order $n$ of $A$ and a scalar $s\in K$ such that $A^n = sI$. The projective order of $A$ is the smallest $n$ such that $A^n$ is a scalar matrix (not just the identity matrix), and it always divides the true order of $A$. The parameter `Proof` is as for `Order`.

<a id="function-factoredprojectiveorder-algmatelt"></a>
#### `FactoredProjectiveOrder(A): AlgMatElt -> [ <RngIntElt, RngIntElt> ], RngElt`

```magma
Proof: BoolElt                    Default: true
```

Given a square invertible matrix $A$ over a finite field $K$, return the projective order $n$ of $A$ in factored form and a scalar $s\in K$ such that $A^n = sI$. The parameter `Proof` is as for `FactoredOrder`.

### Numerical Linear Algebra

Magma has some limited capabilities with numerical linear algebra, that is, linear algebra over a real or complex field. The basis of these is the `RQDecomposition` (appropriate as Magma is row-based), and its companion `QLDecomposition`. Internally, Magma uses these functions to compute (e.g.) matrix inverses and determinants over **R** and **C**.

All of the intrinsics starting with `Numeric` can also be accessed with this word omitted (by extended types on a real/complex matrix), though for some purposes it is useful to remind oneself that numerical linear algebra is not always the same.

<a id="function-rqdecomposition-mtrx-rngrecom"></a>
#### `RQDecomposition(M): Mtrx[RngReCom] -> Mtrx, AlgMatElt`

Given a matrix $M$ over a real or complex field, write $M=RQ$ where $R$ is of triangular form and $Q$ orthogonal (or unitary in the complex case). In particular, $R$ has the same dimensions as $M$; when $M$ has more columns $c$ than rows $r$, then $R$ is of the form $[Z|U]$ where $Z$ is a zero matrix that has $(c-r)$ columns and $U$ is upper triangular. When $r>c$ then the bottom $c$ rows of $R$ form an upper triangular matrix. No normalisations are made except that $Q$ has determinant 1.

<a id="function-qldecomposition-mtrx-rngrecom"></a>
#### `QLDecomposition(M): Mtrx[RngReCom] -> AlgMatElt, Mtrx`

Given a matrix $M$ over a real or complex field, write $M=QL$ where $L$ is of triangular form and $Q$ orthogonal (or unitary in the complex case). This function works simply by applying `RQDecomposition` to the transpose.

<a id="function-numericalinverse-mtrx-rngrecom"></a>
#### `NumericalInverse(M): Mtrx[RngReCom] -> AlgMatElt`

```magma
Epsilon: FldReElt                    Default: 
```

Given a square positive-dimension matrix over a real or complex field, compute its inverse. The `Epsilon` parameter allows one to specify what size of values should be considered to be zero (resulting in an inversion failure). By default, the value of `Epsilon` is computed in a way that is relative to the size of the entries and their precision.

<a id="example-ex-5a8543"></a>
#### `Example: Numerical Matrix Decompositions (ex-5a8543)`

We give some examples of these decompositions.

```magma
> RR := RealField(10);
> r := 4;
> c := 5;
> A := [RR!Random([-2^10..2^10])/2^9 : i in [1..r*c]];
> M := Matrix(r,c,A);
> M;
[-0.1796875000 -1.394531250 -1.345703125 -0.4414062500 0.0000000000]
[1.396484375 -1.496093750 -0.2617187500 -1.882812500 -1.679687500]
[-1.169921875 -0.9062500000 1.707031250 -0.6582031250 1.480468750]
[0.8867187500 -0.3359375000 0.5839843750 0.9707031250 1.896484375]
> R,Q := RQDecomposition(M); R, Q;
[0.0000000000 1.767478576 0.8447303787 -0.05853296288 0.3765439489]
[0.0000000000 0.0000000000 2.924272555 -0.2048205303 1.424771353]
[0.0000000000 0.0000000000 0.0000000000 2.589389831 -1.011949267]
[0.0000000000 0.0000000000 0.0000000000 0.0000000000 -2.403971597]

[-0.1278237197 -0.4893124575 0.3070157953 0.6619247514 -0.4602513884]
[-0.3369945746 -0.5416048144 -0.7236111740 0.05012569151 0.2587917417]
[0.6155218516 -0.6003864917 0.06838441636 -0.4759773097 -0.1715752984]
[-0.5959647961 -0.2953736282 0.5643042371 -0.4119965068 0.2634387749]
[-0.3688557516 0.1397427076 -0.2429248231 -0.4037914284 -0.7888963320]
> Max([Abs(x) : x in Eltseq(R*Q-M)]);
3.492459655E-10 10
> Max([Abs(x) : x in Eltseq(Transpose(Q)*Q-1)]);
1.527951099E-10 14
> //
> CC<i> := ComplexField(5);
> r := 5;
> c := 3;
> A := [CC!Random([-2^10..2^10])/2^9 : j in [1..r*c]];
> B := [CC!Random([-2^10..2^10])/2^9 : j in [1..r*c]];
> M := Matrix(r,c,A) + i*Matrix(r,c,B);
> R,Q := RQDecomposition(M); R, Q;
[-1.1471 + 1.0971*i      -2.6950 - 0.38148*i   0.47294 - 0.95428*i]
[-0.25971 - 0.0084722*i  0.61157 + 0.49147*i   1.5717 - 0.61096*i]
[0.30902 + 0.59626*i     0.79478 + 1.0406*i    -1.1157 - 1.6800*i]
[0.00000                 1.2132 + 1.4143*i    -0.95447 + 0.14362*i]
[0.00000                 0.00000               3.0078 - 0.24966*i]

[0.42713 - 0.0038340*i   0.51414 - 0.56570*i     -0.39550 + 0.27712*i]
[0.54343 + 0.60175*i    -0.087580 + 0.0038354*i   0.56113 + 0.14178*i]
[0.33511 + 0.21874*i    -0.62188 + 0.14580*i     -0.65721]
> Max([Abs(x) : x in Eltseq(R*Q-M)]);
0.00020472 3
> Max([Abs(x) : x in Eltseq(ConjugateTranspose(Q)*Q-1)]);
0.00012207 9
> //
> r := 5;
> c := 5;
> A := [RR!Random([-2^10..2^10])/2^9 : j in [1..r*c]];
> M := Matrix(r,c,A);
> MI := NumericalInverse(M); MI;
[0.5488038571 -0.3734925483 0.005386589048 0.4034292318 -0.6410457874]
[0.3082898339 -0.5126616665 0.1612965318 -0.2971166681 0.07521900340]
[-0.4446389269 0.4962564367 0.1565165202 -0.4722494193 0.2177560581]
[-0.05815013416 -0.3372341073 0.03559373548 0.5402886617 -0.7996494168]
[-0.9780538200 1.225635935 -0.4735623930 -1.060353816 1.356842221]
> Max([Abs(x) : x in Eltseq(M*MI-1)]);
4.656612873E-10 4
```

#### Rank, Kernel, Solution, and Pseudoinverse

To compute the kernel (thus also rank) of a matrix $M$ or a solution to a system $vM=w$, the implementation first performs a QL decomposition internally. When $L$ is of a strict triangular form, namely $L=\bigl({Z\over A|T}\bigr)$ where $Z$ is zero and $T$ is not only lower triangular but also invertible, then the information can be read off immediately. In particular, the rank $r$ is the dimension of $T$, the kernel is the first $k$ rows of $Q$ where $k$ is number of rows in $Z$, while $vM=w$ requires $vQL=w$ so $v=w_rT^{-1}Q_r^T$ where $w_r$ and $Q_r$ are the rightmost $r$ columns of $w$ and $Q$; one checks $vQ_rA$ is (numerically) equal to the other columns of $w$.

When $L$ is not of this form, then an arbitrary orthogonal/unitary transformation is performed on the input (on the right), and the algorithm is re-tried. This case occurs when the $r$ rightmost columns of $M$ are not linearly independent (Magma is internally working on the transpose of $M$ in the $RQ$ decomposition, so that the rightmost columns become the lowermost rows). Similarly, if a condition number for $T$ is too large, such a randomising transform can be profitably applied.

Note that the kernel is returned as a matrix, and indeed has orthonormal rows. The same is true for the image.

The computation of the `NumericalPseudoinverse` is similar, being based on the `QLDecomposition` and possibly also transforming the columns on the right, to ensure that $L$ is of the nice triangular form (this is internally called `QLCDecomposition`). The pseudoinverse of the row-independent (bottom) part $B$ of $L$ is then computed as the solution $\tilde P$ of $\tilde P BB^\star=B^\star$, and one row-extends $\tilde P$ to the left (by zero columns) to get the full (numerical) pseudoinverse $P$.

<a id="function-numericalrank-mtrx-rngrecom"></a>
##### `NumericalRank(M): Mtrx[RngReCom] -> RngIntElt`

```magma
Epsilon: FldReElt                    Default: 
```

Given a matrix over a real or complex field, compute its (numerical) rank. The `Epsilon` parameter allows one to specify what size of values should be considered to be zero. By default, the value of `Epsilon` is computed in a way that is relative to the size of the entries and their precision.

<a id="function-numericalkernel-mtrx-rngrecom"></a>
##### `NumericalKernel(M): Mtrx[RngReCom] -> Mtrx`

```magma
Epsilon: FldReElt                    Default: 
```

Given a matrix over a real or complex field, compute its (numerical) kernel. The `Epsilon` parameter allows one to specify what size of values should be considered to be zero. By default, the value of `Epsilon` is computed in a way that is relative to the size of the entries and their precision.

Exceptionally, `Kernel` returns a space, while `NumericalKernel` returns a basis matrix of it.

<a id="function-numericalimage-mtrx-rngrecom"></a>
##### `NumericalImage(M): Mtrx[RngReCom] -> Mtrx`

```magma
Epsilon: FldReElt                    Default: 
```

Given a matrix over a real or complex field, compute its (numerical) image, that is, its row space. The `Epsilon` parameter allows one to specify what size of values should be considered to be zero. By default, the value of `Epsilon` is computed in a way that is relative to the size of the entries and their precision.

Exceptionally, `Image` returns a space, while `NumericalImage` returns a basis matrix of it.

<a id="function-numericalsolution-mtrx-rngrecom-mtrx-rngrecom"></a>
##### `NumericalSolution(M, w): Mtrx[RngReCom], Mtrx[RngReCom] -> Mtrx, Mtrx`

```magma
Epsilon: FldReElt                    Default: 
```

Given a matrix $M$ and a compatible matrix (or vector) $w$ over a real or complex field, solve numerically for $vM=w$. This gives an error if there is no solution. The second return value is the kernel of $M$. The `Epsilon` parameter allows one to specify what size of values should be considered to be zero. By default, the value of `Epsilon` is computed in a way that is relative to the size of the entries and their precision.

Exceptionally, the second return value is a matrix for `NumericalSolution` and a space for `Solution`.

<a id="function-numericalisconsistent-mtrx-rngrecom-mtrx-rngrecom"></a>
##### `NumericalIsConsistent(M, w): Mtrx[RngReCom], Mtrx[RngReCom] -> BoolElt, Mtrx, Mtrx`

```magma
Epsilon: FldReElt                    Default: 
```

Given a matrix $M$ and a compatible matrix (or vector) $w$ over a real or complex field, determine whether $vM=w$ is numerically solvable. The second return value is a solution (when one exists)(, and the third return value is the (numerical) kernel of $M$. The `Epsilon` parameter allows one to specify what size of values should be considered to be zero. By default, the value of `Epsilon` is computed in a way that is relative to the size of the entries and their precision.

Exceptionally, the third return value is a matrix for `NumericalIsConsistent` and a space for `IsConsistent`.

<a id="function-numericalpseudoinverse-mtrx-rngrecom"></a>
##### `NumericalPseudoinverse(M): Mtrx[RngReCom] -> Mtrx`

```magma
Epsilon: FldReElt                    Default: 
```

Given a matrix $M$ over a real or complex field, compute its pseudoinverse $P$ such that $PMP=P$, $MPM=M$, $(MP)^\star=MP$, and $(PM)^\star=PM$. The `Epsilon` parameter allows one to specify what size of values should be considered to be zero. By default, the value of `Epsilon` is computed in a way that is relative to the size of the entries and their precision. Note that the Magma intrinsic `PseudoInverse` is quite different (largely applicable for matrices over Euclidean domains).

<a id="example-ex-b3a16a"></a>
##### `Example: Numerical Rank, Kernel, and Pseudoinverse (ex-b3a16a)`

We give some examples for ranks, kernels, solutions, and pseudoinverses.

```magma
> RR := RealField(10);
> r := 3;
> c := 5;
> S := [-2^10..2^10];
> A := [Vector([RR!Random(S)/2^9 : i in [1..c]]) : j in [1..r]];
> M := Matrix(A cat [A[1]+A[2]-A[3]]);
> M;
[-1.347656250 -1.980468750 0.2070312500 0.2734375000 -1.273437500]
[0.6464843750 1.726562500 -0.3769531250 0.2011718750 -1.646484375]
[-0.1660156250 1.236328125 -1.500000000 1.119140625 -1.195312500]
[-0.5351562500 -1.490234375 1.330078125 -0.6445312500 -1.724609375]
> NumericalRank(M);
3
> NumericalKernel(M); // scaled to norm 1
[-0.5000000001 -0.4999999998 0.4999999999 0.5000000002]
> v := Vector([RR!Random(S)/2^9 : i in [1..c]]);
> NumericalIsConsistent(M,v);
false
> w := &+[M[i] * Random(S)/2^9 : i in [1..r]];
> NumericalIsConsistent(M,w);
true (1.174316406 0.4165039062 0.7807617187 0.8100585938)
> PI := NumericalPseudoinverse(M); PI;
[-0.1991067080 0.1335911770 -0.1240987264 0.05858319545]
[-0.1885126384 0.1881125824 0.02268111094 -0.02308116681]
[-0.1331315985 0.1012317424 -0.2422989451 0.2103990890]
[0.1423299946 -0.08451596130 0.1982404871 -0.1404264538]
[-0.07615077666 -0.2393032832 -0.09708672579 -0.2183673341]
> Max([Abs(x) :  x in Eltseq(PI*M*PI-PI)]);
7.275957614E-11 9
> //
> CC<i> := ComplexField(30);
> r := 5;
> c := 4;
> A := [CC!Random([-2^30..2^30])/2^28 : j in [1..r*c]];
> B := [CC!Random([-2^30..2^30])/2^28 : j in [1..r*c]];
> M := Matrix(r,c,A) + i*Matrix(r,c,B);
> NumericalRank(M);
4
> NumericalKernel(M);
[0.208965559769595845191678654168 + 0.0334373308308175861091994295635*i
 -0.0227045638063900267279802631268 - 0.354081499548224953341852663885*i
 -0.220008165304096296179634856382 - 0.815082824683314746916890536889*i
 0.0146505331723745379341299824850 - 0.155641405430086914216739561265*i
 0.209604845631814749141329584762 - 0.219520964338492435702429703559*i]
> PI := NumericalPseudoinverse(M);
> Max([Abs(x) :  x in Eltseq(PI*M*PI-PI)]);
1.60521564392120817260990102530E-30 1
> Max([Abs(x) :  x in Eltseq(M*PI*M-M)]);
2.54399997817916409183980874314E-29 18
> Max([Abs(x) :  x in Eltseq(M*PI-ConjugateTranspose(M*PI))]);
7.88860905221011805411728565283E-30 25
> Max([Abs(x) :  x in Eltseq(PI*M-ConjugateTranspose(PI*M))]);
5.03961120551682881427899748034E-30 8
```

#### Eigenvalues and the Singular Value Decomposition

Computing the eigenvalues of a real or complex square matrix is done by first computing the Hessenberg form (almost upper-triangular, but with possible nonzero entries on the immediate subdiagonal), and then applying iterative methods to achieve the Schur form (upper-triangular except for 2-by-2 blocks with complex eigenvalues in the real case). Special methods are used in the case where the matrix is symmetric. The computation of the singular value decomposition works by first computing the bidiagonal form, and then similarly iterating.

<a id="function-numericalhessenbergform-mtrx-rngrecom"></a>
##### `NumericalHessenbergForm(M): Mtrx[RngReCom] -> Mtrx, Mtrx`

Given a square matrix $M$ over a real/complex field, compute a Hessenberg matrix $H$ that is upper-triangular except for possible nonzero entries on the immediate subdiagonal, and an orthogonal/unitary transformation matrix $Q$ such that $H=QMQ^{\star}$ and $QQ^{\star}=I$ (both equalities being numerically approximate). A procedure similar to the RQ decomposition is used, working on both rows and columns.

<a id="function-numericalschurform-mtrx-rngrecom"></a>
##### `NumericalSchurForm(M): Mtrx[RngReCom] -> Mtrx, Mtrx`

```magma
Transform: BoolElt                    Default: true
```

Given a square matrix $M$ over a real/complex field, compute the Schur form $S$ that is upper-triangular except for possible nonzero entries on the immediate subdiagonal corresponding to 2-by-2 real blocks with complex eigenvalues, and an orthogonal/unitary transformation matrix $Q$ such that $S=QMQ^{\star}$ and $QQ^{\star}=I$ (both equalities being numerically approximate). First the Hessenberg form is calculated, and then the unwanted subdiagonal terms are removed by a iterative process.

<a id="function-numericaleigenvalues-mtrx-rngrecom"></a>
##### `NumericalEigenvalues(M): Mtrx[RngReCom] -> SeqEnum`

```magma
Balance: BoolElt                    Default: true
```

Given a square matrix $M$ over a real/complex field, compute numerical approximations to its eigenvalues. This operates by calculating the Schur form, and then returning the relevant eigenvalues. A form of Parlett-Reinsch balancing is used by default, to increase the precision of the answer.

Exceptionally, `NumericalEigenvalues` returns a sequence of reals or complexes, while `Eigenvalues` on real/complex matrix returns a tuple of eigenvalues and multiplicities, for reasons of backwards compatibility (the multiplicities really cannot be guaranteed in the numerical case). Note that `NumericalEigenvalues` always returns a full sequence of eigenvalues for a real input, while `Eigenvalues` will return only those which are (approximately) real.

<a id="function-numericaleigenvectors-mtrx-fldcomelt"></a>
##### `NumericalEigenvectors(M, e): Mtrx, FldComElt -> SeqEnum`

Given a square matrix $M$ that is coercible into the complexes and an approximation $e$ to an eigenvalue of it, attempt to find eigenvectors. This function uses `NumericalKernel`, though returns the result as a sequence of (row) vectors.

<a id="function-numericalbidiagonalform-mtrx-rngrecom"></a>
##### `NumericalBidiagonalForm(M): Mtrx[RngReCom] -> Mtrx, Mtrx, Mtrx`

Given a matrix $M$ over a real/complex field, compute a bidiagonal form $B$ and orthogonal/unitary transformations $U,V$ such that $B=UMV^\star$. Here $B$ is upper bidiagonal if the number of columns is at least as large as the number of rows, and else is lower bidiagonal.

<a id="function-numericalsingularvaluedecomposition-mtrx-rngrecom"></a>
##### `NumericalSingularValueDecomposition(M): Mtrx[RngReCom] -> Mtrx, Mtrx, Mtrx`

Given a matrix $M$ over a real/complex field, compute the singular value decomposition $S$ and orthogonal/unitary transformations $U,V$ such that $S=UMV^\star$. Here $S$ is diagonal in its upper-left corner, with the diagonal entries being nonnegative and sorted in increasing size.

<a id="example-ex-604853"></a>
##### `Example: Numerical Hessenberg Form and Eigenvalues (ex-604853)`

We give some examples for eigenvalues.

```magma
> RR := RealField(10);
> r := 5;
> c := 5;
> A := [RR!Random([-2^10..2^10])/2^9 : i in [1..r*c]];
> M := Matrix(r,c,A);
> H := NumericalHessenbergForm(M); H;
[-1.387758248 0.2244522681 0.1050196798 -0.6292371533 1.500649611]
[-1.737800256 -0.6560018402 -0.1292093616 -0.4045870847 -0.1501588456]
[-0.0000000000 3.503611888 -0.4200132582 -1.521474700 -0.4771033714]
[-0.0000000000 0.0000000000 1.241929396 -1.887789155 -1.398580785]
[-0.0000000000 0.0000000000 0.0000000000 2.063240612 -1.882812500]
> S := NumericalSchurForm(M); S; // need not be diag in real case
[-0.5276818045 2.970316193 -0.8183434354 -1.227178569 1.207265137]
[-0.6560286404 0.1374330601 0.7474073924 -0.7405697671 0.4496312767]
[0.0000000000 0.0000000000 -2.733003988 0.5326130259 -0.2389927500]
[0.0000000000 0.0000000000 0.0000000000 -1.878704188 2.041990652]
[0.0000000000 0.0000000000 0.0000000000 -2.574033133 -1.232418078]
> NumericalEigenvalues(M);
[ -2.733003988,
  -1.555561133 - 2.269742311*$.1, -1.555561133 + 2.269742311*$.1,
  -0.1951243722 - 1.355735243*$.1, -0.1951243722 + 1.355735243*$.1 ]
> M := M + Transpose(M); // make symmetric
> NumericalEigenvalues(M); // all real
[ -5.927297871, -4.230690093, -3.248785626, -1.661515789, 2.599539376 ]
> //
> // example with companion matrix of a polynomial
> //
> f:=Polynomial([Random(10^(12-j)) : j in [0..8]] cat [1]); f;
x^9 + 8569*x^8 + 98753*x^7 + 533140*x^6 + 3583980*x^5 + 52066941*x^4 +
    183889636*x^3 + 5743452355*x^2 + 22923098485*x + 725907276071
> NumericalEigenvalues(ChangeRing(CompanionMatrix(f),RR));
[ -8557.467295,
  -10.76902934 - 4.819656295*$.1, -10.76902934 + 4.819656295*$.1,
  -4.602845057 - 8.104590519*$.1, -4.602845057 + 8.104590519*$.1,
   2.007741523 - 8.923992632*$.1, 2.007741523 + 8.923992632*$.1,
   7.597780247 - 5.110282521*$.1, 7.597780247 + 5.110282521*$.1 ]
> Sort([r[1] : r in Roots(f,ComplexField(10))],func<x,y|Real(x)-Real(y)>);
[ -8557.467295,
  -10.76902933 - 4.819656325*$.1, -10.76902933 + 4.819656325*$.1,
  -4.602845059 - 8.104590521*$.1, -4.602845059 + 8.104590521*$.1,
   2.007741527 - 8.923992640*$.1, 2.007741527 + 8.923992640*$.1,
   7.597780251 - 5.110282532*$.1, 7.597780251 + 5.110282532*$.1 ]
```

<a id="example-ex-4e7c97"></a>
##### `Example: Numerical Singular Value Decomposition (ex-4e7c97)`

We give some examples for bidiagonal form and singular value decomposition.

```magma
> CC<i> := ComplexField(5);
> r := 4;
> c := 5;
> A := [CC!Random([-2^10..2^10])/2^9 : i in [1..r*c]];
> B := [CC!Random([-2^10..2^10])/2^9 : i in [1..r*c]];
> M := Matrix(r,c,A) + i*Matrix(r,c,B);
> X := NumericalBidiagonalForm(M); X;
> NumericalBidiagonalForm(M); // matrix over CC
[2.1983 3.7789 0.00000 0.00000 0.00000]
[0.00000 2.0496 1.8677 0.00000 0.00000]
[0.00000 0.00000 2.6879 2.4315 0.00000]
[0.00000 0.00000 0.00000 3.5035 0.00000]
> NumericalSingularValueDecomposition(M);
[4.9265 0.00000 0.00000 0.00000 0.00000]
[0.00000 4.5508 0.00000 0.00000 0.00000]
[0.00000 0.00000 2.5876 0.00000 0.00000]
[0.00000 0.00000 0.00000 0.73134 0.00000]
> [Sqrt(Real(x)) : x in NumericalEigenvalues(M*ConjugateTranspose(M))];
[ 0.73122, 2.5876, 4.5506, 4.9265 ]
```

### Miscellaneous Operations on Matrices

<a id="function-frobeniusimage-mtrx-rngintelt"></a>
#### `FrobeniusImage(A, e): Mtrx, RngIntElt -> Mtrx`

Given a matrix $A$ over a finite field $K$ of characteristic $p$, return the matrix obtained from $A$ by mapping each entry $A_{i,j}$ to $(A_{i,j})^{p^e}$.

## Sparse Matrices

- [Introduction](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/introduction.md)
- [Creation of Sparse Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md)
  - [Construction of Initialized Sparse Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#construction-of-initialized-sparse-matrices)
    - [`SparseMatrix(R, m, n, Q): Rng, RngIntElt, RngIntElt, [ <RngIntElt, RngIntElt, RngElt> ] → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-sparsematrix-rng-rngintelt-rngintelt-rngintelt-rngintelt-rngelt)
    - [`SparseMatrix(m, n, Q): RngIntElt, RngIntElt, [ <RngIntElt, RngIntElt, RngElt> ] → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-sparsematrix-rngintelt-rngintelt-rngintelt-rngintelt-rngelt)
    - [`SparseMatrix(R, m, n): Rng, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-sparsematrix-rng-rngintelt-rngintelt)
    - [`SparseMatrix(m, n): RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-sparsematrix-rngintelt-rngintelt)
  - [Construction of Trivial Sparse Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#construction-of-trivial-sparse-matrices)
    - [`SparseMatrix(R): Rng → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-sparsematrix-rng)
    - [`SparseMatrix() → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-sparsematrix)
    - [Example: Creating Sparse Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#example-ex-a5eec8)
  - [Construction of Structured Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#construction-of-structured-matrices)
    - [`IdentitySparseMatrix(R, n): Rng, RngElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-identitysparsematrix-rng-rngelt)
    - [`ScalarSparseMatrix(n, s): RngIntElt, RngElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-scalarsparsematrix-rngintelt-rngelt)
    - [`ScalarSparseMatrix(R, n, s): Rng, RngIntElt, RngElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-scalarsparsematrix-rng-rngintelt-rngelt)
    - [`DiagonalSparseMatrix(R, n, Q): Rng, RngIntElt, [ RngElt ] → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-diagonalsparsematrix-rng-rngintelt-rngelt)
    - [`DiagonalSparseMatrix(R, Q): Rng, [ RngElt ] → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-diagonalsparsematrix-rng-rngelt)
    - [`DiagonalSparseMatrix(Q): [ RngElt ] → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-diagonalsparsematrix-rngelt)
    - [`SparseMonomialMatrix(g): GrpPermElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-sparsemonomialmatrix-grppermelt)
  - [Parents of Sparse Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#parents-of-sparse-matrices)
    - [`SparseMatrixStructure(R): [ Rng ] → MtrxSprsStr`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/creation.md#function-sparsematrixstructure-rng)
- [Accessing Sparse Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md)
  - [Elementary Properties](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#elementary-properties)
    - [`BaseRing(A): MtrxSprs → Rng`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-basering-mtrxsprs)
    - [`CoefficientRing(A): MtrxSprs → Rng`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-coefficientring-mtrxsprs)
    - [`NumberOfRows(A): MtrxSprs → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-numberofrows-mtrxsprs)
    - [`Nrows(A): MtrxSprs → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-nrows-mtrxsprs)
    - [`NumberOfColumns(A): MtrxSprs → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-numberofcolumns-mtrxsprs)
    - [`Ncols(A): MtrxSprs → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-ncols-mtrxsprs)
    - [`ElementToSequence(A): MtrxSprs → [ <RngIntElt, RngIntElt, RngElt> ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-elementtosequence-mtrxsprs)
    - [`Eltseq(A): MtrxSprs → [ <RngIntElt, RngIntElt, RngElt> ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-eltseq-mtrxsprs)
    - [`NumberOfNonZeroEntries(A): MtrxSprs → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-numberofnonzeroentries-mtrxsprs)
    - [`NNZEntries(A): MtrxSprs → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-nnzentries-mtrxsprs)
    - [`Density(A): MtrxSprs → FldRe`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-density-mtrxsprs)
    - [`Support(A, i): MtrxSprs, RngIntElt → [RngIntElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-support-mtrxsprs-rngintelt)
    - [`Support(A): MtrxSprs → [ <RngIntElt, RngIntElt, RngElt> ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-support-mtrxsprs)
  - [Weights](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#weights)
    - [`RowWeight(A, i): MtrxSprs, RngIntElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-rowweight-mtrxsprs-rngintelt)
    - [`RowWeights(A): MtrxSprs → [RngIntElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-rowweights-mtrxsprs)
    - [`ColumnWeight(A, j): MtrxSprs, RngIntElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-columnweight-mtrxsprs-rngintelt)
    - [`ColumnWeights(A): MtrxSprs → [RngIntElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/access.md#function-columnweights-mtrxsprs)
- [Accessing or Modifying Entries](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md)
  - [`A[i]: MtrxSprs, RngIntElt → ModTupRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#indexed-indexed-a-mtrxsprs-rngintelt-modtuprngelt)
  - [`A[i, j]: MtrxSprs, RngIntElt, RngIntElt → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#indexed-indexed-a-mtrxsprs-rngintelt-rngintelt-rngelt)
  - [`A[i, j] := x: MtrxSprs, RngIntElt, RngIntElt, RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#literal-literal-a-i-j-x-mtrxsprs-rngintelt-rngintelt-rngelt)
  - [`SetEntry(~A, i, j, x): MtrxSprs, RngIntElt, RngIntElt, RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-smat-setentry)
  - [Example: Accessing Sparse Matrix Entries](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#example-ex-167588)
  - [Extracting and Inserting Blocks](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#extracting-and-inserting-blocks)
    - [`Submatrix(A, i, j, p, q): MtrxSprs, RngIntElt, RngIntElt, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-submatrix-mtrxsprs-rngintelt-rngintelt-rngintelt-rngintelt)
    - [`ExtractBlock(A, i, j, p, q): MtrxSprs, RngIntElt, RngIntElt, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-extractblock-mtrxsprs-rngintelt-rngintelt-rngintelt-rngintelt)
    - [`SubmatrixRange(A, i, j, r, s): MtrxSprs, RngIntElt, RngIntElt, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-submatrixrange-mtrxsprs-rngintelt-rngintelt-rngintelt-rngintelt)
    - [`ExtractBlockRange(A, i, j, r, s): MtrxSprs, RngIntElt, RngIntElt, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-extractblockrange-mtrxsprs-rngintelt-rngintelt-rngintelt-rngintelt)
    - [`Submatrix(A, I, J): MtrxSprs, [RngIntElt], [RngIntElt] → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-submatrix-mtrxsprs-rngintelt-rngintelt)
    - [`InsertBlock(A, B, i, j): MtrxSprs, MtrxSprs, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-insertblock-mtrxsprs-mtrxsprs-rngintelt-rngintelt)
    - [`InsertBlock(~A, B, i, j): MtrxSprs, MtrxSprs, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-insertblock-mtrxsprs-mtrxsprs-rngintelt-rngintelt-ref)
    - [`RowSubmatrix(A, i, k): MtrxSprs, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-rowsubmatrix-mtrxsprs-rngintelt-rngintelt)
    - [`RowSubmatrix(A, i): MtrxSprs, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-rowsubmatrix-mtrxsprs-rngintelt)
    - [`RowSubmatrixRange(A, i, j): MtrxSprs, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-rowsubmatrixrange-mtrxsprs-rngintelt-rngintelt)
    - [`ColumnSubmatrix(A, i, k): MtrxSprs, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-columnsubmatrix-mtrxsprs-rngintelt-rngintelt)
    - [`ColumnSubmatrix(A, i): MtrxSprs, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-columnsubmatrix-mtrxsprs-rngintelt)
    - [`ColumnSubmatrixRange(A, i, j): MtrxSprs, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-columnsubmatrixrange-mtrxsprs-rngintelt-rngintelt)
  - [Row and Column Operations](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#row-and-column-operations)
    - [`SwapRows(A, i, j): MtrxSprs, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-swaprows-mtrxsprs-rngintelt-rngintelt)
    - [`SwapRows(~A, i, j): MtrxSprs, RngIntElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-swaprows-mtrxsprs-rngintelt-rngintelt-ref)
    - [`SwapColumns(A, i, j): MtrxSprs, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-swapcolumns-mtrxsprs-rngintelt-rngintelt)
    - [`SwapColumns(~A, i, j): MtrxSprs, RngIntElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-swapcolumns-mtrxsprs-rngintelt-rngintelt-ref)
    - [`ReverseRows(A): MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-reverserows-mtrxsprs)
    - [`ReverseRows(~A): MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-reverserows-mtrxsprs-ref)
    - [`ReverseColumns(A): MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-reversecolumns-mtrxsprs)
    - [`ReverseColumns(~A): MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-reversecolumns-mtrxsprs-ref)
    - [`AddRow(A, c, i, j): MtrxSprs, RngElt, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-addrow-mtrxsprs-rngelt-rngintelt-rngintelt)
    - [`AddRow(~A, c, i, j): MtrxSprs, RngElt, RngIntElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-addrow-mtrxsprs-rngelt-rngintelt-rngintelt-ref)
    - [`AddColumn(A, c, i, j): MtrxSprs, RngElt, RngIntElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-addcolumn-mtrxsprs-rngelt-rngintelt-rngintelt)
    - [`AddColumn(~A, c, i, j): MtrxSprs, RngElt, RngIntElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-addcolumn-mtrxsprs-rngelt-rngintelt-rngintelt-ref)
    - [`MultiplyRow(A, c, i): MtrxSprs, RngElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-multiplyrow-mtrxsprs-rngelt-rngintelt)
    - [`MultiplyRow(~A, c, i): MtrxSprs, RngElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-multiplyrow-mtrxsprs-rngelt-rngintelt-ref)
    - [`MultiplyColumn(A, c, i): MtrxSprs, RngElt, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-multiplycolumn-mtrxsprs-rngelt-rngintelt)
    - [`MultiplyColumn(~A, c, i): MtrxSprs, RngElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-multiplycolumn-mtrxsprs-rngelt-rngintelt-ref)
    - [`RemoveRow(A, i): MtrxSprs, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-removerow-mtrxsprs-rngintelt)
    - [`RemoveRow(~A, i): MtrxSprs, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-removerow-mtrxsprs-rngintelt-ref)
    - [`RemoveColumn(A, j): MtrxSprs, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-removecolumn-mtrxsprs-rngintelt)
    - [`RemoveColumn(~A, j): MtrxSprs, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-removecolumn-mtrxsprs-rngintelt-ref)
    - [`RemoveRowColumn(A, i, j): MtrxSprs, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-removerowcolumn-mtrxsprs-rngintelt)
    - [`RemoveRowColumn(~A, i, j): MtrxSprs, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-removerowcolumn-mtrxsprs-rngintelt-ref)
    - [`RemoveZeroRows(A): MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#function-removezerorows-mtrxsprs)
    - [`RemoveZeroRows(~A): MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-removezerorows-mtrxsprs-ref)
- [Building Block Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/join.md)
  - [`HorizontalJoin(A, B): MtrxSprs, MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/join.md#function-horizontaljoin-mtrxsprs-mtrxsprs)
  - [`VerticalJoin(A, B): MtrxSprs, MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/join.md#function-verticaljoin-mtrxsprs-mtrxsprs)
  - [`DiagonalJoin(A, B): MtrxSprs, MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/join.md#function-diagonaljoin-mtrxsprs-mtrxsprs)
- [Conversion to and from Dense Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/conversion.md)
  - [`Matrix(A): MtrxSprs → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/conversion.md#function-smat-matrix)
  - [`SparseMatrix(A): Mtrx → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/conversion.md#function-sparsematrix-mtrx)
- [Changing Ring](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/change-ring.md)
  - [`ChangeRing(A, R): MtrxSprs, Rng → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/change-ring.md#function-changering-mtrxsprs-rng)
  - [`SparseMatrix(R, A): Rng, MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/change-ring.md#function-sparsematrix-rng-mtrxsprs)
- [Predicates](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md)
  - [`A eq B: MtrxSprs, MtrxSprs → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md#operation-op-eq-mtrxsprs-mtrxsprs)
  - [`IsZero(A): MtrxSprs → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md#function-iszero-mtrxsprs)
  - [`IsOne(A): MtrxSprs → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md#function-isone-mtrxsprs)
  - [`IsMinusOne(A): MtrxSprs → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md#function-isminusone-mtrxsprs)
  - [`IsScalar(A): MtrxSprs → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md#function-isscalar-mtrxsprs)
  - [`IsDiagonal(A): MtrxSprs → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md#function-isdiagonal-mtrxsprs)
  - [`IsSymmetric(A): MtrxSprs → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md#function-issymmetric-mtrxsprs)
  - [`IsUpperTriangular(A): MtrxSprs → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md#function-isuppertriangular-mtrxsprs)
  - [`IsLowerTriangular(A): MtrxSprs → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/predicates.md#function-islowertriangular-mtrxsprs)
- [Elementary Arithmetic](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md)
  - [`A + B: MtrxSprs, MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md#operation-op-plus-mtrxsprs-mtrxsprs)
  - [`A - B: MtrxSprs, MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md#operation-op-minus-mtrxsprs-mtrxsprs)
  - [`A * B: MtrxSprs, MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md#operation-op-times-mtrxsprs-mtrxsprs)
  - [`x * A: RngElt, MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md#operation-op-times-rngelt-mtrxsprs)
  - [`A * x: MtrxSprs, RngElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md#operation-op-times-mtrxsprs-rngelt)
  - [`-A: MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md#operation-operation-mtrxsprs-mtrxsprs)
  - [`A ^-1: MtrxSprs, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md#operation-operation-1-mtrxsprs-rngintelt-mtrxsprs)
  - [`A ^ n: MtrxSprs, RngIntElt → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md#operation-op-pow-mtrxsprs-rngintelt)
  - [`Transpose(A): MtrxSprs → MtrxSprs`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/arithmetic.md#function-transpose-mtrxsprs)
- [Multiplying Vectors or Matrices by Sparse Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/multiply.md)
  - [`v * A: ModTupRng, MtrxSprs → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/multiply.md#operation-op-times-modtuprng-mtrxsprs)
  - [`V * A: Mtrx, MtrxSprs → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/multiply.md#operation-op-times-mtrx-mtrxsprs)
  - [`MultiplyByTranspose(v, A): ModTupRng, MtrxSprs → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/multiply.md#function-multiplybytranspose-modtuprng-mtrxsprs)
  - [`MultiplyByTranspose(V, A): Mtrx, MtrxSprs → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/multiply.md#function-multiplybytranspose-mtrx-mtrxsprs)
- [Non-trivial Properties](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md)
  - [Nullspace and Rowspace](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md#nullspace-and-rowspace)
    - [`Nullspace(A): MtrxSprs → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md#function-nullspace-mtrxsprs)
    - [`Kernel(A): MtrxSprs → ModTupRng, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md#function-kernel-mtrxsprs)
    - [`NullspaceMatrix(A): MtrxSprs → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md#function-nullspacematrix-mtrxsprs)
    - [`KernelMatrix(A): MtrxSprs → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md#function-kernelmatrix-mtrxsprs)
    - [`NullspaceOfTranspose(A): MtrxSprs → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md#function-nullspaceoftranspose-mtrxsprs)
    - [`Rowspace(A): MtrxSprs → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md#function-rowspace-mtrxsprs)
  - [Rank](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md#rank)
    - [`Rank(A): MtrxSprs → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/non-trivial.md#function-rank-mtrxsprs)
- [Determinant and Other Properties](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/determinant.md)
  - [`Determinant(A: parameters): MtrxSprs → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/determinant.md#function-determinant-mtrxsprs)
- [Minimal and Characteristic Polynomials and Eigenvalues](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md)
  - [`MinimalPolynomial(A: parameters): MtrxSprs → RngUPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-minimalpolynomial-mtrxsprs)
  - [`CharacteristicPolynomial(A: parameters): MtrxSprs → RngUPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-characteristicpolynomial-mtrxsprs)
  - [`MinimalAndCharacteristicPolynomials(A: parameters): MtrxSprs → RngUPolElt, RngUPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-minimalandcharacteristicpolynomials-mtrxsprs)
  - [`MCPolynomials(A): MtrxSprs → RngUPolElt, RngUPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-mcpolynomials-mtrxsprs)
  - [`FactoredMinimalPolynomial(A: parameters): MtrxSprs → [ <RngUPolElt, RngIntElt>]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-factoredminimalpolynomial-mtrxsprs)
  - [`FactoredCharacteristicPolynomial(A: parameters): MtrxSprs → [ <RngUPolElt, RngIntElt>]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-factoredcharacteristicpolynomial-mtrxsprs)
  - [`FactoredMinimalAndCharacteristicPolynomials(A: parameters): MtrxSprs → [<RngUPolElt, RngIntElt>], [<RngUPolElt, RngIntElt>]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-factoredminimalandcharacteristicpolynomials-mtrxsprs)
  - [`FactoredMCPolynomials(A: parameters): MtrxSprs → [<RngUPolElt, RngIntElt>], [<RngUPolElt, RngIntElt>]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-factoredmcpolynomials-mtrxsprs)
  - [`Eigenvalues(A): MtrxSprs → { <FldElt, RngIntElt> }`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-eigenvalues-mtrxsprs)
  - [`Eigenspace(A, e): AlgMatElt, FldElt → ModTup`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-eigenspace-algmatelt-fldelt)
  - [Elementary Divisors (Smith Form)](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#elementary-divisors-smith-form)
    - [`ElementaryDivisors(A): MtrxSprs → [RngElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#function-elementarydivisors-mtrxsprs)
  - [Verbosity](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#verbosity)
    - [`SetVerbose("SparseMatrix", v): MonStgElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/min-char-poly.md#procedure-setverbose-monstgelt-rngintelt-sparsematrix)
- [Linear Systems (Structured Gaussian Elimination)](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/solution.md)
  - [`ModularSolution(A, M): MtrxSprs, RngIntElt → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/solution.md#function-smat-modularsolution)
  - [`ModularSolution(A, L): MtrxSprs, RngIntEltFact → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/solution.md#function-modularsolution-mtrxsprs-rnginteltfact)
  - [Example: Discrete Logarithms by Linear Sieve](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/solution.md#example-ex-a75220)
- [Bibliography](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/bibliography.md)

### Introduction

A separate type is provided for sparse matrices to allow the user to construct such matrices and apply algorithms which take advantage of sparsity. Sparse matrices are distinct from normal matrices in Magma, which have a dense representation. This chapter describes the operations available for creating and working with sparse matrices.

The operations provided for sparse matrices include dynamic construction, simple properties, and the calculation of a number of non-trivial and important invariants (such as rank, determinant, or computing a non-zero vector in the nullspace). In particular, this datatype supports the class of *index-calculus* algorithms which involve generating a very large sparse system and then solving the system or finding the elementary divisors of the corresponding matrix (for example, to compute the abelian group structure). An extended example presented at the end of the chapter ([Discrete Logarithms by Linear Sieve](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/solution.md#example-ex-a75220)) illustrates how an index-calculus method may be implemented in practice in the Magma language using the sparse matrix facilities.

The type name for the category of sparse matrices is `MtrxSprs`. All sparse matrices over a given ring $R$ lie in the same *sparse matrix structure*, whose type name is `MtrxSprsStr`. The user will, in practice, rarely need to refer explicitly to the parent structure.

### Creation of Sparse Matrices

This section describes the constructs provided for creating sparse matrices.

#### Construction of Initialized Sparse Matrices

<a id="function-sparsematrix-rng-rngintelt-rngintelt-rngintelt-rngintelt-rngelt"></a>
##### `SparseMatrix(R, m, n, Q): Rng, RngIntElt, RngIntElt, [ <RngIntElt, RngIntElt, RngElt> ] -> MtrxSprs`

<a id="function-sparsematrix-rngintelt-rngintelt-rngintelt-rngintelt-rngelt"></a>
##### `SparseMatrix(m, n, Q): RngIntElt, RngIntElt, [ <RngIntElt, RngIntElt, RngElt> ] -> MtrxSprs`

Given a ring $R$ (optional), integers $m,n\ge 0$, and a sequence $Q$, return the $m\times n$ sparse matrix over $R$ whose non-zero entries are those specified by $Q$, coerced into $R$. If $R$ is not given, it is derived from the entries in $Q$. Either of $m$ and $n$ may be 0, in which case $Q$ must have length 0 (and may be null if $R$ is given), and the $m\times n$ zero sparse matrix over $R$ is returned. There are two possibilities for $Q$:

**(a)**
The sequence $Q$ is a sequence of tuples, each of the form `<i, j, x>`, where $1\leq i\leq m$, $1\leq j\leq n$, and $x\in S$ for some ring $S$. Such a tuple specifies that the $(i, j)$-th entry of the matrix is $x$. If $R$ is given, then $x$ is coerced into $R$; otherwise the matrix is created over $S$. If an entry position is not given then its value is zero, while if an entry position is repeated then the last value overrides any previous values.

**(b)**
The sequence $Q$ is a “flat” sequence of integers, giving the entries of the matrix in compact form. To be precise, $Q$ begins with the number of non-zero entries $n$ for the first row, then $2\cdot n$ integers giving column-entry pairs for the first row, and this format is immediately followed for the second row and so on. A zero row is specified by a zero value for $n$. If $R$ is given, the integer entries are coerced into $R$; otherwise the matrix is defined over ${\mathbb{Z}}$. (Thus this method will not allow elements of $R$ which cannot be created by coercing integers into $R$ alone; another way of saying this is that the entries must all lie in the prime ring of $R$). This allows a very compact way to create (and store) sparse matrices. The examples below illustrate this format.

<a id="function-sparsematrix-rng-rngintelt-rngintelt"></a>
##### `SparseMatrix(R, m, n): Rng, RngIntElt, RngIntElt -> MtrxSprs`

Given a ring $R$, and integers $m,n\ge 0$, create the $m\times n$ sparse matrix over $R$.

<a id="function-sparsematrix-rngintelt-rngintelt"></a>
##### `SparseMatrix(m, n): RngIntElt, RngIntElt -> MtrxSprs`

Given integers $m,n\ge 0$, create the $m\times n$ sparse matrix over the integer ring ${\mathbb{Z}}$.

#### Construction of Trivial Sparse Matrices

<a id="function-sparsematrix-rng"></a>
##### `SparseMatrix(R): Rng -> MtrxSprs`

<a id="function-sparsematrix"></a>
##### `SparseMatrix() -> MtrxSprs`

Create the $0\times 0$ sparse matrix over $R$. If $R$ is omitted (so there are no arguments), then $R$ is taken to be the integer ring ${\mathbb{Z}}$. These functions will usually be called when the user wishes to create a sparse matrix whose final dimensions are initially unknown, and for which the [`SetEntry`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-smat-setentry) procedure below will be used to extend the matrix automatically, as needed.

<a id="example-ex-a5eec8"></a>
##### `Example: Creating Sparse Matrices (ex-a5eec8)`

This example demonstrates simple ways of creating matrices using the general `SparseMatrix(R, m, n, Q)` function. Sparse matrices may be displayed in the sparse representation using the `Magma` print-format. Also, the function [`Matrix`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/conversion.md#function-smat-matrix) (described below) takes a sparse matrix and returns a normal (dense-representation) matrix, so this function provides a means of printing a small sparse matrix as a normal matrix.

(a) A sparse $2 \times 2$ matrix is defined over ${\mathbb{Z}}$, using the first (sequence of tuples) method. We specify that there is a $3$ in the $(1,2)$ position and a $-1$ in the $(2,3)$ position. The ring need not be given since the entries are in ${\mathbb{Z}}$ already.

```magma
> A := SparseMatrix(2, 3, [<1,2,3>, <2,3,-1>]);
> A;
Sparse matrix with 2 rows and 3 columns over Integer Ring
> Matrix(A);
[ 0  3  0]
[ 0  0 -1]
```

(b) The same matrix is now defined over ${\bf F}_{23}$. We could also coerce the 3rd component of each tuple into ${\bf F}_{23}$ and thus omit the first argument.

```magma
> A := SparseMatrix(GF(23), 2, 3, [<1,2,3>, <2,3,-1>]);
> A;
Sparse matrix with 2 rows and 3 columns over GF(23)
> Matrix(A);
[ 0  3  0]
[ 0  0 22]
```

(c) A similar sparse matrix is defined over ${\bf F}_{2^4}$. When $A$ is printed in `Magma` format, the sequence-of-tuples form is used (because the entries cannot be printed as integers).

```magma
> K<w> := GF(2^4);
> A := SparseMatrix(K, 2, 3, [<1,2,3>, <2,3,w>]);
> A;
Sparse matrix with 2 rows and 3 columns over GF(2^4)
> Matrix(A);
[   0    1    0]
[   0    0    w]
> A: Magma;
SparseMatrix(GF(2, 4), 2, 3, [
    <1, 2, 1>,
    <2, 3, w>
])
```

(d) A sparse $4 \times 5$ matrix $A$ is defined over ${\mathbb{Z}}$, using the second (flat integer sequence) method. Here row 1 has one non-zero entry: -1 at column 3; then row 2 has three non-zero entries: 9 at column 2, 7 at column 3, and $-3$ at column 4; row 3 has no non-zero entries (so we give a 0 at this point); and finally row 4 has one non-zero entry $3$ at column 4. Note that when $A$ is printed in `Magma` format, this time the compact “flat” sequence of integers form is used, since this is possible.

```magma
> A := SparseMatrix(4,5, [1,3,-1, 3,2,9,3,7,4,-3, 0, 1,4,3]);
> A;
Sparse matrix with 4 rows and 5 columns over Integer Ring
> Matrix(A);
[ 0  0 -1  0  0]
[ 0  9  7 -3  0]
[ 0  0  0  0  0]
[ 0  0  0  3  0]
> A: Magma;
SparseMatrix(4, 5, \\[
    1, 3,-1,
    3, 2,9, 3,7, 4,-3,
    0,
    1, 4,3
])
```

#### Construction of Structured Matrices

<a id="function-identitysparsematrix-rng-rngelt"></a>
##### `IdentitySparseMatrix(R, n): Rng, RngElt -> MtrxSprs`

Given a ring $R$, and an integer $n\ge 0$, return the $n\times n$ identity sparse matrix over $R$.

<a id="function-scalarsparsematrix-rngintelt-rngelt"></a>
##### `ScalarSparseMatrix(n, s): RngIntElt, RngElt -> MtrxSprs`

Given an integer $n\ge 0$ and an element $s$ of a ring $R$, return the $n \times n$ scalar sparse matrix over $R$ which has $s$ on the diagonal and zeros elsewhere. The argument $n$ may be 0, in which case the $0 \times 0$ sparse matrix over $R$ is returned.

<a id="function-scalarsparsematrix-rng-rngintelt-rngelt"></a>
##### `ScalarSparseMatrix(R, n, s): Rng, RngIntElt, RngElt -> MtrxSprs`

Given a ring $R$, an integer $n\ge 0$, and an element $s$ of a ring $S$, return the $n \times n$ scalar sparse matrix over $R$ which has $s$, coerced into $R$, on the diagonal and zeros elsewhere. $n$ may be 0, in which case in which case the $0 \times 0$ sparse matrix over $R$ is returned.

<a id="function-diagonalsparsematrix-rng-rngintelt-rngelt"></a>
##### `DiagonalSparseMatrix(R, n, Q): Rng, RngIntElt, [ RngElt ] -> MtrxSprs`

Given a ring $R$, an integer $n\ge 0$, and a sequence $Q$ of $n$ ring elements, return the $n \times n$ diagonal sparse matrix over $R$ whose diagonal entries correspond to the entries of $Q$, coerced into $R$.

<a id="function-diagonalsparsematrix-rng-rngelt"></a>
##### `DiagonalSparseMatrix(R, Q): Rng, [ RngElt ] -> MtrxSprs`

Given a ring $R$ and a sequence $Q$ of $n$ ring elements, return the $n \times n$ diagonal sparse matrix over $R$ whose diagonal entries correspond to the entries of $Q$, coerced into $R$.

<a id="function-diagonalsparsematrix-rngelt"></a>
##### `DiagonalSparseMatrix(Q): [ RngElt ] -> MtrxSprs`

Given a sequence $Q$ of $n$ elements from a ring $R$, return the $n \times n$ diagonal sparse matrix over $R$ whose diagonal entries

<a id="function-sparsemonomialmatrix-grppermelt"></a>
##### `SparseMonomialMatrix(g): GrpPermElt -> MtrxSprs`

Given a degree-$(2d)$ permutation $g$, return the $d \times d$ monomial matrix corresponding to $g$.

#### Parents of Sparse Matrices

<a id="function-sparsematrixstructure-rng"></a>
##### `SparseMatrixStructure(R): [ Rng ] -> MtrxSprsStr`

Create the structure containing all sparse matrices (of any shape) over ring $R$. This structure does not need to be created explicitly by the user (it will be the parent of any sparse matrix over $R$), but it may be useful to create it in this way occasionally.

### Accessing Sparse Matrices

The following functions access basic properties of sparse matrices.

#### Elementary Properties

<a id="function-basering-mtrxsprs"></a>
##### `BaseRing(A): MtrxSprs -> Rng`

<a id="function-coefficientring-mtrxsprs"></a>
##### `CoefficientRing(A): MtrxSprs -> Rng`

Given a sparse matrix $A$ with entries lying in a ring $R$, return $R$.

<a id="function-numberofrows-mtrxsprs"></a>
##### `NumberOfRows(A): MtrxSprs -> RngIntElt`

<a id="function-nrows-mtrxsprs"></a>
##### `Nrows(A): MtrxSprs -> RngIntElt`

Given an $m \times n$ sparse matrix $A$, return $m$, the number of rows of $A$.

<a id="function-numberofcolumns-mtrxsprs"></a>
##### `NumberOfColumns(A): MtrxSprs -> RngIntElt`

<a id="function-ncols-mtrxsprs"></a>
##### `Ncols(A): MtrxSprs -> RngIntElt`

Given an $m \times n$ sparse matrix $A$, return $n$, the number of columns of $A$.

<a id="function-elementtosequence-mtrxsprs"></a>
##### `ElementToSequence(A): MtrxSprs -> [ <RngIntElt, RngIntElt, RngElt> ]`

<a id="function-eltseq-mtrxsprs"></a>
##### `Eltseq(A): MtrxSprs -> [ <RngIntElt, RngIntElt, RngElt> ]`

Given a sparse matrix $A$ over the ring $R$ having $m$ rows and $n$ columns, return the entries of $A$ as a sequence of all tuples of the form `<i, j, x>` such that the $[i, j]$-th entry of $A$ equals $x$ and $x$ is non-zero. It is always true that `SparseMatrix(Nrows(A), Ncols(A), Eltseq(A))` equals $A$.

<a id="function-numberofnonzeroentries-mtrxsprs"></a>
##### `NumberOfNonZeroEntries(A): MtrxSprs -> RngIntElt`

<a id="function-nnzentries-mtrxsprs"></a>
##### `NNZEntries(A): MtrxSprs -> RngIntElt`

Given a sparse matrix $A$, return the number of non-zero entries in $A$.

<a id="function-density-mtrxsprs"></a>
##### `Density(A): MtrxSprs -> FldRe`

Given a sparse matrix $A$, return the density of $A$ as a real number, which is the number of non-zero entries in $A$ divided by the product of the number of rows of $A$ and the number of columns of $A$ (or zero if $A$ has zero rows or columns).

<a id="function-support-mtrxsprs-rngintelt"></a>
##### `Support(A, i): MtrxSprs, RngIntElt -> [RngIntElt]`

Given a sparse matrix $A$ having $r$ rows, and an integer $i$ such that $1\leq i\leq r$, return the support of row $i$ of $A$; i.e., the column numbers of the non-zero entries of row $i$ of $A$.

<a id="function-support-mtrxsprs"></a>
##### `Support(A): MtrxSprs -> [ <RngIntElt, RngIntElt, RngElt> ]`

Given a sparse matrix $A$, return the sequence of all pairs `<i, j>` such that the $[i, j]$-th entry of $A$ is non-zero.

#### Weights

<a id="function-rowweight-mtrxsprs-rngintelt"></a>
##### `RowWeight(A, i): MtrxSprs, RngIntElt -> RngIntElt`

Given a sparse matrix $A$ with $m$ rows and an integer $i$ such that $1\leq i\leq m$, return the weight (number of non-zero entries) of the $i$-th row of $A$.

<a id="function-rowweights-mtrxsprs"></a>
##### `RowWeights(A): MtrxSprs -> [RngIntElt]`

Given a sparse matrix $A$ with $m$ rows, return the length $m$ sequence of integers whose $i$-th entry is the weight of the $i$-th row of $A$.

<a id="function-columnweight-mtrxsprs-rngintelt"></a>
##### `ColumnWeight(A, j): MtrxSprs, RngIntElt -> RngIntElt`

Given a sparse matrix $A$ with $n$ columns and an integer $j$ such that $1\leq j\leq n$, return the weight (number of non-zero entries) of the $j$-th column of $A$.

<a id="function-columnweights-mtrxsprs"></a>
##### `ColumnWeights(A): MtrxSprs -> [RngIntElt]`

Given a sparse matrix $A$ with $n$ columns, return the length $n$ sequence of integers whose $j$-th entry is the weight of the $j$-th column of $A$.

### Accessing or Modifying Entries

The following functions and procedures enable the user to access or set individual entries of sparse matrices.

<a id="indexed-indexed-a-mtrxsprs-rngintelt-modtuprngelt"></a>
#### `A[i]: MtrxSprs, RngIntElt -> ModTupRngElt`

Given a sparse matrix $A$ over a ring $R$ having $m$ rows and $n$ columns, and an integer $i$ such that $1 \leq i \leq m$, return the $i$-th row of $A$, as a dense vector of length $n$ (lying in $R^n$).

<a id="indexed-indexed-a-mtrxsprs-rngintelt-rngintelt-rngelt"></a>
#### `A[i, j]: MtrxSprs, RngIntElt, RngIntElt -> RngElt`

Given a sparse matrix $A$ over a ring $R$ having $m$ rows and $n$ columns, integers $i$ and $j$ such that $1 \leq i \leq m$ and $1 \leq j \leq n$, return the $(i,j)$-th entry of $A$, as an element of the ring $R$.

<a id="literal-literal-a-i-j-x-mtrxsprs-rngintelt-rngintelt-rngelt"></a>
#### `A[i, j] := x: MtrxSprs, RngIntElt, RngIntElt, RngElt`

Given a sparse matrix $A$ over a ring $R$ having $m$ rows and $n$ columns, integers $i$ and $j$ such that $1 \leq i \leq m$ and $1 \leq j \leq n$, and a ring element $x$ coercible into $R$, modify the $(i,j)$-th entry of $A$ to be $x$. Here $i$ and $j$ must be within the ranges given by the current dimensions of $A$; see [`SetEntry`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/entries.md#procedure-smat-setentry) below for a procedure to automatically extend $A$ if necessary.

<a id="procedure-smat-setentry"></a>
#### `SetEntry(~A, i, j, x): MtrxSprs, RngIntElt, RngIntElt, RngElt`

(Procedure.) Given a sparse matrix $A$ over a ring $R$, integers $i,j\geq 1$, and a ring element $x$ coercible into $R$, modify the $(i,j)$-th entry of $A$ to be $x$. The entry specified by $i$ and $j$ is allowed to be beyond the current dimensions of $A$; if so, $A$ is automatically extended to have at least $i$ rows and $j$ columns.

This procedure will be commonly used in situations where the final size of the matrix is not known as an algorithm proceeds (e.g., in index-calculus methods). One can create the $0\times 0$ sparse matrix over ${\mathbb{Z}}$, say, and then call `SetEntry` to build up the matrix dynamically. See the example [Discrete Logarithms by Linear Sieve](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/solution.md#example-ex-a75220) below, which uses this technique.

Note that extending the dimensions of $A$ with a very large $i$ or $j$ will not in itself consume much memory, but if $A$ then becomes dense or is passed to some algorithm, then the memory needed may of course be proportional to the dimensions of $A$.

<a id="example-ex-167588"></a>
#### `Example: Accessing Sparse Matrix Entries (ex-167588)`

This example demonstrates simple ways of accessing the entries of sparse matrices.

```magma
> A := SparseMatrix(2, 3, [<1,2,3>, <2,3,-1>]);
> A;
Sparse matrix with 2 rows and 3 columns over Integer Ring
> Matrix(A);
[ 0  3  0]
[ 0  0 -1]
> A[1];
(0 3 0)
> A[1, 3]:=5;
> A[1];
(0 3 5)
```

We next extend $A$ using the procedure `SetEntry`.

```magma
> SetEntry(~A, 1, 5, -7);
> A;
Sparse matrix with 2 rows and 5 columns over Integer Ring
> Matrix(A);
[ 0  3  5  0 -7]
[ 0  0 -1  0  0]
```

A common situation is to start with the empty $0\times 0$ matrix over ${\mathbb{Z}}$ and then to extend it dynamically.

```magma
> A := SparseMatrix();
> A;
Sparse matrix with 0 rows and 0 columns over Integer Ring
> SetEntry(~A, 1, 4, -2);
> A;
Sparse matrix with 1 row and 4 columns over Integer Ring
> SetEntry(~A, 2, 3, 8);
> A;
Sparse matrix with 2 rows and 4 columns over Integer Ring
> Matrix(A);
[ 0  0  0 -2]
[ 0  0  8  0]
> SetEntry(~A, 200, 319, 1);
> SetEntry(~A, 200, 3876, 1);
> A;
Sparse matrix with 200 rows and 3876 columns over Integer Ring
> Nrows(A);
200
> Ncols(A);
3876
> NNZEntries(A);
4
> Density(A);
0.000005159958720330237358101135190
> Support(A, 200);
[ 319, 3876 ]
```

#### Extracting and Inserting Blocks

The following functions enable the extraction of certain rows, columns, or general submatrices, or the replacement of a block by another sparse matrix.

<a id="function-submatrix-mtrxsprs-rngintelt-rngintelt-rngintelt-rngintelt"></a>
##### `Submatrix(A, i, j, p, q): MtrxSprs, RngIntElt, RngIntElt, RngIntElt, RngIntElt -> MtrxSprs`

<a id="function-extractblock-mtrxsprs-rngintelt-rngintelt-rngintelt-rngintelt"></a>
##### `ExtractBlock(A, i, j, p, q): MtrxSprs, RngIntElt, RngIntElt, RngIntElt, RngIntElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ and integers $i$, $j$, $p$, and $q$ such that $1\leq i \leq i + p \leq m+1$, and $1 \leq j \leq j + q \leq n+1$, return the $p \times q$ submatrix of $A$ rooted at $(i, j)$. Either or both of $p$ and $q$ may be zero, while $i$ may be $m+1$ if $p$ is zero and $j$ may be $n+1$ if $q$ is zero.

<a id="function-submatrixrange-mtrxsprs-rngintelt-rngintelt-rngintelt-rngintelt"></a>
##### `SubmatrixRange(A, i, j, r, s): MtrxSprs, RngIntElt, RngIntElt, RngIntElt, RngIntElt -> MtrxSprs`

<a id="function-extractblockrange-mtrxsprs-rngintelt-rngintelt-rngintelt-rngintelt"></a>
##### `ExtractBlockRange(A, i, j, r, s): MtrxSprs, RngIntElt, RngIntElt, RngIntElt, RngIntElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ and integers $i$, $j$, $r$, and $s$ such that $1\leq i$, $i-1 \leq r \leq m$, $1 \leq j$, and $j-1 \leq s \leq n$, return the $r-i+1\times s-j+1$ submatrix of $A$ rooted at the $(i, j)$-th entry and extending to the $(r, s)$-th entry, inclusive. $r$ may equal $i-1$ or $s$ may equal $j-1$, in which case a sparse matrix with zero rows or zero columns, respectively, will be returned.

<a id="function-submatrix-mtrxsprs-rngintelt-rngintelt"></a>
##### `Submatrix(A, I, J): MtrxSprs, [RngIntElt], [RngIntElt] -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ and integer sequences $I$ and $J$, return the submatrix of $A$ given by the row indices in $I$ and the column indices in $J$.

<a id="function-insertblock-mtrxsprs-mtrxsprs-rngintelt-rngintelt"></a>
##### `InsertBlock(A, B, i, j): MtrxSprs, MtrxSprs, RngIntElt, RngIntElt -> MtrxSprs`

<a id="function-insertblock-mtrxsprs-mtrxsprs-rngintelt-rngintelt-ref"></a>
##### `InsertBlock(~A, B, i, j): MtrxSprs, MtrxSprs, RngIntElt, RngIntElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, a $p \times q$ sparse matrix $B$ over $R$, and integers $i$ and $j$ such that $1\leq i \leq i + p \leq m+1$ and $1 \leq j \leq j + q \leq n+1$, insert $B$ at position $(i,j)$ in $A$. In the functional version ($A$ is a value argument), this function returns the new sparse matrix and leaves $A$ untouched, while in the procedural version ($\sim A$ is a reference argument), $A$ is modified in place so that the $p \times q$ submatrix of $A$ rooted at $(i, j)$ is now equal to $B$.

<a id="function-rowsubmatrix-mtrxsprs-rngintelt-rngintelt"></a>
##### `RowSubmatrix(A, i, k): MtrxSprs, RngIntElt, RngIntElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ and integers $i$ and $k$ such that $1 \le i \leq i + k \leq m+1$, return the $k \times n$ submatrix of $X$ consisting of rows $[i \ldots i + k - 1]$ inclusive. The integer $k$ may be zero and $i$ may also be $m+1$ if $k$ is zero, but the result will always have $n$ columns.

<a id="function-rowsubmatrix-mtrxsprs-rngintelt"></a>
##### `RowSubmatrix(A, i): MtrxSprs, RngIntElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ and an integer $i$ such that $0 \le i \leq m$, return the $i\times n$ submatrix of $X$ consisting of the first $i$ rows. The integer $i$ may be $0$, but the result will always have $n$ columns.

<a id="function-rowsubmatrixrange-mtrxsprs-rngintelt-rngintelt"></a>
##### `RowSubmatrixRange(A, i, j): MtrxSprs, RngIntElt, RngIntElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ and integers $i$ and $j$ such that $1 \le i$ and $i-1 \leq j \leq m$, return the $j-i+1 \times n$ submatrix of $X$ consisting of rows $[i \ldots j]$ inclusive. The integer $j$ may equal $i-1$, in which case a sparse matrix with zero rows and $n$ columns will be returned.

<a id="function-columnsubmatrix-mtrxsprs-rngintelt-rngintelt"></a>
##### `ColumnSubmatrix(A, i, k): MtrxSprs, RngIntElt, RngIntElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ and integers $i$ and $k$ such that $1 \le i \leq i + k \leq n+1$, return the $m \times k$ submatrix of $X$ consisting of columns $[i \ldots i + k - 1]$ inclusive. The integer $k$ may be zero and $i$ may also be $n+1$ if $k$ is zero, but the result will always have $m$ rows.

<a id="function-columnsubmatrix-mtrxsprs-rngintelt"></a>
##### `ColumnSubmatrix(A, i): MtrxSprs, RngIntElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ and an integer $i$ such that $0 \le i \leq n$, return the $m\times i$ submatrix of $X$ consisting of the first $i$ columns. The integer $i$ may be $0$, but the result will always have $m$ rows.

<a id="function-columnsubmatrixrange-mtrxsprs-rngintelt-rngintelt"></a>
##### `ColumnSubmatrixRange(A, i, j): MtrxSprs, RngIntElt, RngIntElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ and integers $i$ and $j$ such that $1 \le i$ and $i-1 \leq j \leq n$, return the $m\times j-i+1$ submatrix of $X$ consisting of columns $[i \ldots j]$ inclusive. The integer $j$ may equal $i-1$, in which case a sparse matrix with zero columns and $n$ rows will be returned.

#### Row and Column Operations

The following functions and procedures provide elementary row or column operations on sparse matrices. For each operation, there is a corresponding function which creates a new sparse matrix for the result (leaving the input sparse matrix unchanged), and a corresponding procedure which modifies the input sparse matrix in place.

<a id="function-swaprows-mtrxsprs-rngintelt-rngintelt"></a>
##### `SwapRows(A, i, j): MtrxSprs, RngIntElt, RngIntElt -> MtrxSprs`

<a id="procedure-swaprows-mtrxsprs-rngintelt-rngintelt-ref"></a>
##### `SwapRows(~A, i, j): MtrxSprs, RngIntElt, RngIntElt`

Given an $m \times n$ sparse matrix $A$ and integers $i$ and $j$ such that $1 \le i\le m$ and $1 \leq j \leq m$, swap the $i$-th and $j$-th rows of $A$.

<a id="function-swapcolumns-mtrxsprs-rngintelt-rngintelt"></a>
##### `SwapColumns(A, i, j): MtrxSprs, RngIntElt, RngIntElt -> MtrxSprs`

<a id="procedure-swapcolumns-mtrxsprs-rngintelt-rngintelt-ref"></a>
##### `SwapColumns(~A, i, j): MtrxSprs, RngIntElt, RngIntElt`

Given an $m \times n$ sparse matrix $A$ and integers $i$ and $j$ such that $1 \le i\le n$ and $1 \leq j \leq n$, swap the $i$-th and $j$-th columns of $A$.

<a id="function-reverserows-mtrxsprs"></a>
##### `ReverseRows(A): MtrxSprs -> MtrxSprs`

<a id="procedure-reverserows-mtrxsprs-ref"></a>
##### `ReverseRows(~A): MtrxSprs`

Given a sparse matrix $A$, reverse all the rows of $A$.

<a id="function-reversecolumns-mtrxsprs"></a>
##### `ReverseColumns(A): MtrxSprs -> MtrxSprs`

<a id="procedure-reversecolumns-mtrxsprs-ref"></a>
##### `ReverseColumns(~A): MtrxSprs`

Given a sparse matrix $A$, reverse all the columns of $A$.

<a id="function-addrow-mtrxsprs-rngelt-rngintelt-rngintelt"></a>
##### `AddRow(A, c, i, j): MtrxSprs, RngElt, RngIntElt, RngIntElt -> MtrxSprs`

<a id="procedure-addrow-mtrxsprs-rngelt-rngintelt-rngintelt-ref"></a>
##### `AddRow(~A, c, i, j): MtrxSprs, RngElt, RngIntElt, RngIntElt`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, a ring element $c$ coercible into $R$, and integers $i$ and $j$ such that $1 \le i\le m$ and $1 \leq j \leq m$, add $c$ times row $i$ of $A$ to row $j$ of $A$.

<a id="function-addcolumn-mtrxsprs-rngelt-rngintelt-rngintelt"></a>
##### `AddColumn(A, c, i, j): MtrxSprs, RngElt, RngIntElt, RngIntElt -> MtrxSprs`

<a id="procedure-addcolumn-mtrxsprs-rngelt-rngintelt-rngintelt-ref"></a>
##### `AddColumn(~A, c, i, j): MtrxSprs, RngElt, RngIntElt, RngIntElt`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, a ring element $c$ coercible into $R$, and integers $i$ and $j$ such that $1 \le i\le n$ and $1 \leq j \leq n$, add $c$ times column $i$ of $A$ to column $j$.

<a id="function-multiplyrow-mtrxsprs-rngelt-rngintelt"></a>
##### `MultiplyRow(A, c, i): MtrxSprs, RngElt, RngIntElt -> MtrxSprs`

<a id="procedure-multiplyrow-mtrxsprs-rngelt-rngintelt-ref"></a>
##### `MultiplyRow(~A, c, i): MtrxSprs, RngElt, RngIntElt`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, a ring element $c$ coercible into $R$, and an integer $i$ such that $1 \le i\le m$, multiply row $i$ of $A$ by $c$ (on the left).

<a id="function-multiplycolumn-mtrxsprs-rngelt-rngintelt"></a>
##### `MultiplyColumn(A, c, i): MtrxSprs, RngElt, RngIntElt -> MtrxSprs`

<a id="procedure-multiplycolumn-mtrxsprs-rngelt-rngintelt-ref"></a>
##### `MultiplyColumn(~A, c, i): MtrxSprs, RngElt, RngIntElt`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, a ring element $c$ coercible into $R$, and an integer $i$ such that $1 \le i\le n$, multiply column $i$ of $A$ by $c$ (on the left).

<a id="function-removerow-mtrxsprs-rngintelt"></a>
##### `RemoveRow(A, i): MtrxSprs, RngIntElt -> MtrxSprs`

<a id="procedure-removerow-mtrxsprs-rngintelt-ref"></a>
##### `RemoveRow(~A, i): MtrxSprs, RngIntElt`

Given an $m \times n$ sparse matrix $A$ and an integer $i$ such that $1 \le i\le m$, remove row $i$ from $A$ (leaving an $(m-1) \times n$ sparse matrix).

<a id="function-removecolumn-mtrxsprs-rngintelt"></a>
##### `RemoveColumn(A, j): MtrxSprs, RngIntElt -> MtrxSprs`

<a id="procedure-removecolumn-mtrxsprs-rngintelt-ref"></a>
##### `RemoveColumn(~A, j): MtrxSprs, RngIntElt`

Given an $m \times n$ sparse matrix $A$ and an integer $j$ such that $1 \le j\le n$, remove column $j$ from $A$ (leaving an $m \times (n-1)$ sparse matrix).

<a id="function-removerowcolumn-mtrxsprs-rngintelt"></a>
##### `RemoveRowColumn(A, i, j): MtrxSprs, RngIntElt -> MtrxSprs`

<a id="procedure-removerowcolumn-mtrxsprs-rngintelt-ref"></a>
##### `RemoveRowColumn(~A, i, j): MtrxSprs, RngIntElt`

Given an $m \times n$ sparse matrix $A$ and integers $i$ and $j$ such that $1 \le i\le m$ and $1 \le j\le n$, remove row $i$ and column $j$ from $A$ (leaving an $(m-1) \times (n-1)$ sparse matrix).

<a id="function-removezerorows-mtrxsprs"></a>
##### `RemoveZeroRows(A): MtrxSprs -> MtrxSprs`

<a id="procedure-removezerorows-mtrxsprs-ref"></a>
##### `RemoveZeroRows(~A): MtrxSprs`

Given a sparse matrix $A$, remove all the zero rows of $A$.

### Building Block Matrices

<a id="function-horizontaljoin-mtrxsprs-mtrxsprs"></a>
#### `HorizontalJoin(A, B): MtrxSprs, MtrxSprs -> MtrxSprs`

Given a sparse matrix $A$ with $r$ rows and $c$ columns, and a sparse matrix $B$ with $r$ rows and $d$ columns, both over the same coefficient ring $R$, return the sparse matrix over $R$ with $r$ rows and $(c+d)$ columns obtained by joining $A$ and $B$ horizontally (placing $B$ to the right of $A$).

<a id="function-verticaljoin-mtrxsprs-mtrxsprs"></a>
#### `VerticalJoin(A, B): MtrxSprs, MtrxSprs -> MtrxSprs`

Given a sparse matrix $A$ with $r$ rows and $c$ columns, and a sparse matrix $B$ with $s$ rows and $c$ columns, both over the same coefficient ring $R$, return the sparse matrix with $(r+s)$ rows and $c$ columns over $R$ obtained by joining $A$ and $B$ vertically (placing $B$ underneath $A$).

<a id="function-diagonaljoin-mtrxsprs-mtrxsprs"></a>
#### `DiagonalJoin(A, B): MtrxSprs, MtrxSprs -> MtrxSprs`

Given matrices $A$ with $a$ rows and $b$ columns and $B$ with $c$ rows and $d$ columns, both over the same coefficient ring $R$, return the sparse matrix with $(a+c)$ rows and $(b+d)$ columns over $R$ obtained by joining $A$ and $B$ diagonally (placing $B$ diagonally to the right of and underneath $A$, with zero blocks above and below the diagonal).

### Conversion to and from Dense Matrices

The following functions convert between sparse matrices and normal (dense-representation) matrices.

<a id="function-smat-matrix"></a>
#### `Matrix(A): MtrxSprs -> Mtrx`

Given a sparse matrix $A$, return the normal (dense-representation) matrix equal to $A$. This function should only be used if the size of $A$ is reasonably small since otherwise the amount of memory needed to represent the dense-representation matrix may be huge. Printing the result of this operation is a convenient way to display $A$ as a normal (dense) matrix if $A$ is small.

<a id="function-sparsematrix-mtrx"></a>
#### `SparseMatrix(A): Mtrx -> MtrxSprs`

Given a normal (dense-representation) matrix $A$, return the sparse matrix equal to $A$. Note that if there is a fast algorithm available for the sparse matrix type, there is no need to convert a dense-representation matrix to the sparse matrix type first and then to use that algorithm, since Magma does this automatically.

### Changing Ring

<a id="function-changering-mtrxsprs-rng"></a>
#### `ChangeRing(A, R): MtrxSprs, Rng -> MtrxSprs`

<a id="function-sparsematrix-rng-mtrxsprs"></a>
#### `SparseMatrix(R, A): Rng, MtrxSprs -> MtrxSprs`

Given a sparse matrix $A$ over a ring $S$ having $m$ rows and $n$ columns, and another ring $R$, return the $m\times n$ sparse matrix over $R$ obtained by coercing the entries of $A$ from $S$ into $R$.

The argument order to `ChangeRing(A, R)` here is consistent with other forms of `ChangeRing`, while the `SparseMatrix(R, A)` form of this function is provided to be consistent with the sparse matrix creation functions above, for which the destination ring is the first argument, if supplied.

### Predicates

The functions in this section test various properties of sparse matrices.

<a id="operation-op-eq-mtrxsprs-mtrxsprs"></a>
#### `A eq B: MtrxSprs, MtrxSprs -> BoolElt`

Given sparse matrices $A$ and $B$, return `true` if and only if $A$ and $B$ are equal.

<a id="function-iszero-mtrxsprs"></a>
#### `IsZero(A): MtrxSprs -> BoolElt`

Given an $m \times n$ sparse matrix $A$ over the ring $R$, return `true` iff $A$ is the $m \times n$ zero sparse matrix.

<a id="function-isone-mtrxsprs"></a>
#### `IsOne(A): MtrxSprs -> BoolElt`

Given a square $m \times m$ sparse matrix $A$ over the ring $R$, return `true` iff $A$ is the $m \times m$ identity sparse matrix.

<a id="function-isminusone-mtrxsprs"></a>
#### `IsMinusOne(A): MtrxSprs -> BoolElt`

Given a square $m \times m$ sparse matrix $A$ over the ring $R$, return `true` iff $A$ is the negation of the $m \times m$ identity sparse matrix.

<a id="function-isscalar-mtrxsprs"></a>
#### `IsScalar(A): MtrxSprs -> BoolElt`

Given a square $m \times m$ sparse matrix $A$ over the ring $R$, return `true` iff $A$ is scalar, i.e., iff $A$ is the product of some element of $R$ and the $m \times m$ identity sparse matrix.

<a id="function-isdiagonal-mtrxsprs"></a>
#### `IsDiagonal(A): MtrxSprs -> BoolElt`

Given a square sparse matrix $A$ over the ring $R$, return `true` iff $A$ is diagonal, i.e., iff the only non-zero entries of $A$ are on the diagonal.

<a id="function-issymmetric-mtrxsprs"></a>
#### `IsSymmetric(A): MtrxSprs -> BoolElt`

Given a square sparse matrix $A$ over the ring $R$, return `true` iff $A$ is symmetric, i.e., iff $A$ equals its transpose.

<a id="function-isuppertriangular-mtrxsprs"></a>
#### `IsUpperTriangular(A): MtrxSprs -> BoolElt`

Given a sparse matrix $A$ over the ring $R$, return `true` iff $A$ is upper triangular, i.e., iff the only non-zero entries of $A$ are on or above the diagonal.

<a id="function-islowertriangular-mtrxsprs"></a>
#### `IsLowerTriangular(A): MtrxSprs -> BoolElt`

Given a sparse matrix $A$ over the ring $R$, return `true` iff $A$ is lower triangular, i.e., iff the only non-zero entries of $A$ are on or below the diagonal.

### Elementary Arithmetic

<a id="operation-op-plus-mtrxsprs-mtrxsprs"></a>
#### `A + B: MtrxSprs, MtrxSprs -> MtrxSprs`

Given $m \times n$ sparse matrices $A$ and $B$ over a ring $R$, return $A+B$.

<a id="operation-op-minus-mtrxsprs-mtrxsprs"></a>
#### `A - B: MtrxSprs, MtrxSprs -> MtrxSprs`

Given $m \times n$ sparse matrices $A$ and $B$ over a ring $R$, return $A-B$.

<a id="operation-op-times-mtrxsprs-mtrxsprs"></a>
#### `A * B: MtrxSprs, MtrxSprs -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ over a ring $R$ and an $n \times p$ sparse matrix $B$ over $R$, return the $m \times p$ sparse matrix $A\cdot B$ over $R$.

<a id="operation-op-times-rngelt-mtrxsprs"></a>
#### `x * A: RngElt, MtrxSprs -> MtrxSprs`

<a id="operation-op-times-mtrxsprs-rngelt"></a>
#### `A * x: MtrxSprs, RngElt -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ over a ring $R$ and a ring element $x$ coercible into $R$, return the scalar product $x\cdot A$.

<a id="operation-operation-mtrxsprs-mtrxsprs"></a>
#### `-A: MtrxSprs -> MtrxSprs`

Given a sparse matrix $A$, return $-A$.

<a id="operation-operation-1-mtrxsprs-rngintelt-mtrxsprs"></a>
#### `A ^-1: MtrxSprs, RngIntElt -> MtrxSprs`

Given a invertible square sparse matrix $A$ over a ring $R$, return the inverse $B$ of $A$ so that $A\cdot B = B\cdot A = 1$. The coefficient ring $R$ must be either a field, a Euclidean domain, or a ring with an exact division algorithm and having characteristic equal to zero or greater than $m$ (this includes most commutative rings).

<a id="operation-op-pow-mtrxsprs-rngintelt"></a>
#### `A ^ n: MtrxSprs, RngIntElt -> MtrxSprs`

Given a square sparse matrix $A$ over a ring $R$ and an integer $n$, return the matrix power $A^n$. $A^0$ is defined to be the identity matrix for any square matrix $A$ (even if $A$ is zero). If $n$ is negative, $A$ must be invertible (see the previous function), and the result is $(A^{-1})^{-n}$.

<a id="function-transpose-mtrxsprs"></a>
#### `Transpose(A): MtrxSprs -> MtrxSprs`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, return the transpose of $A$, which is simply the $n \times m$ sparse matrix over $R$ whose $(i,j)$-th entry is the $(j,i)$-th entry of $A$.

### Multiplying Vectors or Matrices by Sparse Matrices

These functions allow the multiplication of a normal (dense-representation) vector by a sparse matrix.

<a id="operation-op-times-modtuprng-mtrxsprs"></a>
#### `v * A: ModTupRng, MtrxSprs -> ModTupRng`

<a id="operation-op-times-mtrx-mtrxsprs"></a>
#### `V * A: Mtrx, MtrxSprs -> Mtrx`

Given a dense-representation vector $v$ or dense-representation matrix $V$ with $c$ columns, together with a sparse $c\times n$ matrix $A$, both over a ring $R$, return the product $v\cdot A$ or $V\cdot A$.

This is generally fast if $A$ is sparse and uses minimal memory.

<a id="function-multiplybytranspose-modtuprng-mtrxsprs"></a>
#### `MultiplyByTranspose(v, A): ModTupRng, MtrxSprs -> ModTupRng`

<a id="function-multiplybytranspose-mtrx-mtrxsprs"></a>
#### `MultiplyByTranspose(V, A): Mtrx, MtrxSprs -> Mtrx`

Given a dense-representation vector $v$ or dense-representation matrix $V$ with $c$ columns, together with a sparse $n\times c$ matrix $A$, both over a ring $R$, return the product of $v$ or $V$ by the transpose of $A$.

This is generally fast if $A$ is sparse, and is much faster than computing the transpose of $A$ first. For example, if the vector-matrix product $v\cdot A\cdot A^{tr}$ is required, then the function call `MultiplyByTranspose(v*A, A)` should be used to avoid forming the matrix $A\cdot A^{tr}$ which is usually dense. This product occurs in iterative algorithms such as Lanzcos.

### Non-trivial Properties

The following functions compute non-trivial properties of sparse matrices.

#### Nullspace and Rowspace

The following functions compute nullspaces (solving equations of the form $V\cdot A=0$) or rowspaces of sparse matrices.

<a id="function-nullspace-mtrxsprs"></a>
##### `Nullspace(A): MtrxSprs -> ModTupRng`

<a id="function-kernel-mtrxsprs"></a>
##### `Kernel(A): MtrxSprs -> ModTupRng, Map`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, return the nullspace of $A$ (or the kernel of $A$, considered as a linear transformation or map), which is the $R$-space consisting of all vectors $v$ of length $m$ such that $v\cdot A = 0$. Since the result will be given in the dense representation, both the nullity of $A$ and the number of rows of $A$ must both be reasonably small.

The algorithm first performs sparse elimination using Markowitz pivoting ([[DEJ84](https://docs.magma-maths.org/references.md#cite-smatbook), Sec. 9.2]) to obtain a smaller dense matrix, then the nullspace algorithm for dense-representation matrices is applied to this matrix.

<a id="function-nullspacematrix-mtrxsprs"></a>
##### `NullspaceMatrix(A): MtrxSprs -> Mtrx`

<a id="function-kernelmatrix-mtrxsprs"></a>
##### `KernelMatrix(A): MtrxSprs -> Mtrx`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, return a (dense-representation) basis matrix of the nullspace of $A$. This is a matrix $N$ having $m$ columns and the maximal number of independent rows subject to the condition that $N\cdot A = 0$. This function has the advantage that the nullspace is not returned as a $R$-space, so echelonization of the resulting nullspace may be avoided.

<a id="function-nullspaceoftranspose-mtrxsprs"></a>
##### `NullspaceOfTranspose(A): MtrxSprs -> ModTupRng`

This function is equivalent to `Nullspace(Transpose(A))`, but will be more efficient in space for large matrices, since the transpose may not have to be explicitly constructed to compute the nullspace.

<a id="function-rowspace-mtrxsprs"></a>
##### `Rowspace(A): MtrxSprs -> ModTupRng`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, return the rowspace of $A$, which is the $R$-space generated by the rows of $A$. Since the result will be given in the dense representation, the rank and the number of columns of $A$ must both be reasonably small.

#### Rank

<a id="function-rank-mtrxsprs"></a>
##### `Rank(A): MtrxSprs -> RngIntElt`

Given an $m \times n$ sparse matrix $A$ over a ring $R$, return the rank of $A$. The algorithm first performs sparse elimination using Markowitz pivoting ([[DEJ84](https://docs.magma-maths.org/references.md#cite-smatbook), Sec. 9.2]) to obtain a smaller dense matrix, then the rank algorithm for dense-representation matrices is applied to this matrix.

### Determinant and Other Properties

<a id="function-determinant-mtrxsprs"></a>
#### `Determinant(A: parameters): MtrxSprs -> RngElt`

```magma
MonteCarloSteps: RngIntElt                    Default: 
```

Given a square sparse matrix $A$ over the ring $R$, return the determinant of $A$ as an element of $R$. $R$ may be any commutative ring. The algorithm first performs sparse elimination using Markowitz pivoting ([[DEJ84](https://docs.magma-maths.org/references.md#cite-smatbook), Sec. 9.2]) to obtain a smaller dense matrix, then the determinant algorithm for dense-representation matrices is applied to this matrix. If the parameter `MonteCarloSteps` is given, then this is passed to the dense algorithm for the dense matrix.

### Minimal and Characteristic Polynomials and Eigenvalues

The functions in this section deal with minimal and characteristic polynomials and related operations and they match the functions defined for dense matrices; see Section [Minimal and Characteristic Polynomials and Eigenvalues](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/properties-2.md#sec-matmincharpoly) for more information on the functions and the possible parameters.

<a id="function-minimalpolynomial-mtrxsprs"></a>
#### `MinimalPolynomial(A: parameters): MtrxSprs -> RngUPolElt`

Given a square sparse matrix $A$ over a ring $R$, return the minimal polynomial of $A$.

<a id="function-characteristicpolynomial-mtrxsprs"></a>
#### `CharacteristicPolynomial(A: parameters): MtrxSprs -> RngUPolElt`

```magma
Al   : MonStg                     Default: "Modular"
Proof: BoolElt                    Default: true
```

Given a square sparse matrix $A$ over a ring $R$, return the characteristic polynomial of $A$.

<a id="function-minimalandcharacteristicpolynomials-mtrxsprs"></a>
#### `MinimalAndCharacteristicPolynomials(A: parameters): MtrxSprs -> RngUPolElt, RngUPolElt`

<a id="function-mcpolynomials-mtrxsprs"></a>
#### `MCPolynomials(A): MtrxSprs -> RngUPolElt, RngUPolElt`

Given a square sparse matrix $A$ over a ring $R$, return the minimal and characteristic polynomials of $A$.

<a id="function-factoredminimalpolynomial-mtrxsprs"></a>
#### `FactoredMinimalPolynomial(A: parameters): MtrxSprs -> [ <RngUPolElt, RngIntElt>]`

Given a square sparse matrix $A$ over a ring $R$, return the factorization of the minimal polynomial of $A$.

<a id="function-factoredcharacteristicpolynomial-mtrxsprs"></a>
#### `FactoredCharacteristicPolynomial(A: parameters): MtrxSprs -> [ <RngUPolElt, RngIntElt>]`

Given a square sparse matrix $A$ over a ring $R$, return the factorisation of the characteristic polynomial of $A$.

<a id="function-factoredminimalandcharacteristicpolynomials-mtrxsprs"></a>
#### `FactoredMinimalAndCharacteristicPolynomials(A: parameters): MtrxSprs -> [<RngUPolElt, RngIntElt>], [<RngUPolElt, RngIntElt>]`

<a id="function-factoredmcpolynomials-mtrxsprs"></a>
#### `FactoredMCPolynomials(A: parameters): MtrxSprs -> [<RngUPolElt, RngIntElt>], [<RngUPolElt, RngIntElt>]`

Given a square matrix sparse $A$ over a ring $R$, return the factorizations of the minimal and characteristic polynomials of $A$, respectively.

<a id="function-eigenvalues-mtrxsprs"></a>
#### `Eigenvalues(A): MtrxSprs -> { <FldElt, RngIntElt> }`

Given a square matrix $A$ over a ring $R$, return the eigenvalues of $A$ as a set of pairs, each of which gives the value of a distinct eigenvalue and its multiplicity.

<a id="function-eigenspace-algmatelt-fldelt"></a>
#### `Eigenspace(A, e): AlgMatElt, FldElt -> ModTup`

Given a square matrix $A$ over a ring $R$, and an element $e$ of $R$, return the eigenspace of $A$ corresponding to $e$.

#### Elementary Divisors (Smith Form)

<a id="function-elementarydivisors-mtrxsprs"></a>
##### `ElementaryDivisors(A): MtrxSprs -> [RngElt]`

Given an $m \times n$ matrix $A$ over the Euclidean ring or field $R$, return the elementary divisors of $A$. These are simply the non-zero diagonal entries of the Smith form of $A$, in order.

The divisors are returned as a sequence $Q = [e_1, \ldots, e_d]$, $e_i | e_{i+1}$ ($i=1, \ldots, d-1$) of $d$ elements of $R$ (which may include ones), where $d$ is the rank of $A$. If $R$ is a field, the result is always a sequence of $r$ ones, where $r$ is the rank of $A$.

A function for computing the Smith normal form is not supplied for sparse matrices since the form may be trivially derived from the elementary divisors, and the sequence $Q$ containing the divisors is often more convenient (and takes less memory). As transformation matrices are dense in general, they are not supported for the sparse representation.

The algorithm first performs sparse elimination using Markowitz pivoting to obtain a smaller dense matrix ([[DEJ84](https://docs.magma-maths.org/references.md#cite-smatbook), Sec. 9.2]; this is similar to the techniques described in [[HHR93](https://docs.magma-maths.org/references.md#cite-hhr-smith)]). Then it invokes the dense Smith normal form algorithm for normal (dense-representation) matrices ([`SmithForm`](https://docs.magma-maths.org/MatricesLinearAlgebra/Matrices/canonical.md#function-mat-smithform)).

#### Verbosity

<a id="procedure-setverbose-monstgelt-rngintelt-sparsematrix"></a>
##### `SetVerbose("SparseMatrix", v): MonStgElt, RngIntElt`

(Procedure.) Set the verbose printing level for all sparse matrix algorithms to be $v$. Currently the legal values for $v$ are `true`, `false`, 0, 1, 2, and 3 (`false` has the same effect as 0, and `true` has the same effect as 1).

### Linear Systems (Structured Gaussian Elimination)

<a id="function-smat-modularsolution"></a>
#### `ModularSolution(A, M): MtrxSprs, RngIntElt -> ModTupRng`

<a id="function-modularsolution-mtrxsprs-rnginteltfact"></a>
#### `ModularSolution(A, L): MtrxSprs, RngIntEltFact -> ModTupRng`

```magma
Lanczos: BoolElt                    Default: false
```

Given a sparse $m\times n$ matrix $A$, defined over the integer ring ${\mathbb{Z}}$, and a positive integer $M$, compute a vector $v$ such that $v$ satisfies the equation $v\cdot A^{tr}=0$ modulo $M$. $v$ will be non-zero with high probability.

This function is designed for index-calculus-type algorithms where a large sparse linear system defined by the matrix $A$ is first constructed and then a vector satisfying the above equation modulo $M$ is required. For this reason it is natural that the transpose of $A$ appears in this equation. The example [Discrete Logarithms by Linear Sieve](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/solution.md#example-ex-a75220) below illustrates such a situation in detail.

The first version of the function takes the actual integer $M$ as the second argument given and so must be factored as part of the calculation, while the second version of the function takes the factorization sequence $L$ of $M$. If possible, the solution vector is multiplied by a unit modulo $M$ so that its first entry is 1.

The function uses the *Structured Gaussian Elimination* algorithm [[LO91b](https://docs.magma-maths.org/references.md#cite-lo-slinalg), Sec. 5]. This reduces the linear system to be solved to a much smaller but denser system. By default, the function recurses on the smaller system until it is almost completely dense, and then this dense system is solved using the fast dense modular nullspace algorithm of Magma.

If the parameter `Lanczos` is set to `true`, then the *Lanczos* algorithm [[LO91b](https://docs.magma-maths.org/references.md#cite-lo-slinalg), Sec. 3] will be used instead. This is generally *very much* slower than the default method (it is often 10 to 50 times slower), but it will take considerably less memory, so may be preferable in the case of extremely large matrices.

For typical matrices arising in index-calculus problems, and for most machines, the default method (reducing to a completely dense system) should solve a linear system of size roughly $100,000\times 100,000$ using about 500MB of memory while a linear system of size roughly $200,000\times 200,000$ should require about 1.5GB to 2.0GB of memory.

<a id="example-ex-a75220"></a>
#### `Example: Discrete Logarithms by Linear Sieve (ex-a75220)`

In this extended example, we demonstrate the application of the function [`ModularSolution`](https://docs.magma-maths.org/MatricesLinearAlgebra/SparseMatrices/solution.md#function-smat-modularsolution) to a sparse matrix arising in an index-calculus algorithm. We present Magma code which performs the first stage of the basic linear sieve [[COS86](https://docs.magma-maths.org/references.md#cite-cos-log), [LO91a](https://docs.magma-maths.org/references.md#cite-lo-log)] for computing discrete logarithms in a prime finite field ${\bf F}_{p}$. This first stage determines most of the logarithms of the elements of the *factor basis* (which is the set of small primes up to a given limit) by using a *sieve* to compute a sparse linear system which is then solved modulo $p-1$.

Even though the following sieving code is written in the Magma language and so is *much* slower than a serious C implementation, it is sufficiently powerful to be able to compute the first stage logarithms in less than a minute for fields ${\bf F}_{p}$ where $p$ is about $10^{20}$ and $(p-1)/2$ is prime. In comparison, the standard Pohlig-Hellman algorithm based on the Pollard-Rho method would take many hours for such fields. This Magma code can also be adapted for other index-calculus methods.

Suppose $p$ is an odd prime and let $K={\bf F}_{p}$. Let $Q$ be the *factor base*, an ordered set consisting of all positive primes from 2 to a given limit `qlimit`. Fix a primitive element $\alpha$ of $K$ which is also *prime* as an integer, so $\alpha$ is in $Q$. We wish to compute the discrete logarithms of most of the elements of $Q$ with respect to $\alpha$; i.e., we wish to compute $l_q$ with $\alpha^{l_q}=q$ for most $q\in Q$.

The algorithm uses a *sieve* to search for linear relations involving the logarithms of the elements of $Q$. Let $H=\lfloor \sqrt p\rfloor + 1$ and $J=H^2 - p$. We search for pairs of integers $(c_1, c_2)$ with $1\leq c_1,c_2 \leq$ `climit` (where `climit` is a given limit which is much less than $H$) such that

$$
[(H + c_1)(H + c_2)] \bmod p = J + (c_1 + c_2)H + c_1 c_2
$$

is *smooth* with respect to $Q$ (i.e., all of its prime factors are in $Q$). If we include these $H+c_i$ in the factor base, then this gives a linear relation modulo $(p-1)$ among the logarithms of the elements of the extended factor base.

Fix $c_1$ with $1\leq c \leq$ `climit` and suppose we initialize a sieve array (to be indexed by $c_2$) to have zero in each position. For each prime power $q^h$ with $q\in Q$ and $h$ sufficiently small, we compute

$$
d = [(J + c_1 H)(H + c_1)^{-1}] \bmod q^h.
$$

Then for all $c_2\equiv d\pmod {q^h}$, it turns out that

$$
(H + c_1)(H + c_2) \equiv 0 \pmod {q^h}.
$$

So for each $c_2$ with $c_1\leq c_2\leq$ `climit` and $c_2\equiv d\pmod {q^h}$, we add $\log(q)$ to the position of the sieve corresponding to $c_2$. (Ensuring that $c_2\geq c_1$ avoids redundant relations.) When we have done this for each $q\in Q$, we perform trial division to obtain relations for each of the $c_2$ whose sieve values are beneath a suitable threshold.

We repeat this with a new $c_1$ value until we have more relations than elements of the factor base (typically we make the ratio be 1.1 or 1.2), then we solve the corresponding linear system modulo $M=p-1$ to obtain the desired logarithms. We ensure that $\alpha$ is the first element of $Q$ so that when the vector is normalized modulo $M$ (so that its first entry is 1), the logarithms will be with respect to $\alpha$. For derivations of the above equations and for further details concerning the sieving, see [[LO91a](https://docs.magma-maths.org/references.md#cite-lo-log)].

In practice, one first writes $M=p-1=M_1\cdot M_2$ where $M_1$ contains the maximal powers of all the small primes dividing $M$ (say, for primes $\leq 10000$). The solution space modulo $M_1$ will often have high dimension, so the logarithms modulo $M_1$ usually cannot be correctly computed from the linear system alone. So we only compute the solution of the linear system modulo $M_2$. It is still possible that some logarithms cannot be determined modulo $M_2$ (e.g., if 2 unknowns occur only in one equation), but usually most of the logarithms will be correctly computed modulo $M_2$. Then the logarithm of each factor basis element can be easily computed modulo $M_1$ by the Pohlig-Hellman algorithm, and the Chinese Remainder Theorem can be used to combine these with the correct modulo-$M_2$ logarithms to compute the logarithms modulo $M$ of most elements of the factor basis.

Similar index-calculus-type algorithms should have techniques for handling small prime divisors of the modulus $M$ when the solution of the linear system has high nullity modulo these small primes.

The following function `Sieve` has been developed by Allan Steel, based on code by Benjamin Costello. Its arguments are the field $K={\bf F}_{p}$, the factor base prime limit `qlimit`, the $c_1, c_2$ range limit `climit`, and the desired stopping ratio of relations to unknowns. The function returns the sparse relation matrix $A$ together with an indexed set containing the corresponding extended factor base (the small primes and the $H+c_i$ values which yield relations).

```magma
> function Sieve(K, qlimit, climit, ratio)
>     p := #K;
>     Z := Integers();
>     H := Iroot(p, 2) + 1;
>     J := H^2 - p;
>
>     // Get factor basis of all primes <= qlimit.
>     fb_primes := [p: p in [2 .. qlimit] | IsPrime(p)];
>
>     printf "Factor base has %o primes, climit is %o\n", #fb_primes, climit;
>
>     // Ensure that the primitive element of K is prime (as an integer).
>     a := rep{x: x in [2..qlimit] | IsPrime(x) and IsPrimitive(K!x)};
>     SetPrimitiveElement(K,K!a);
>
>     // Initialize extended factor base FB to fb_primes (starting with a).
>     FB := {@ Z!a @};
>     for x in fb_primes do
>         Include(~FB, x);
>     end for;
>
>     // Initialize A to 0 by 0 sparse matrix over Z.
>     A := SparseMatrix();
>
>     // Get logs of all factor basis primes.
>     log2 := Log(2.0);
>     logqs := [Log(q)/log2: q in fb_primes];
>
>     for c1 in [1 .. climit] do
>
>         // Stop if ratio of relations to unknowns is high enough.
>         if Nrows(A)/#FB ge ratio then break; end if;
>
>         if c1 mod 50 eq 0 then
>             printf "c1: %o, #rows: %o, #cols: %o, ratio: %o\n",
>                 c1, Nrows(A), #FB, RealField(8)!Nrows(A)/#FB;
>         end if;
>
>         // Initialize sieve.
>         sieve := [z: i in [1 .. climit]] where z := Log(1.0);
>         den := H + c1;                  // denominator of relation
>         num := -(J + c1*H);             // numerator
>
>         for i := 1 to #fb_primes do
>             // For each prime q in factor base...
>             q := fb_primes[i];
>             logq := logqs[i];
>
>             qpow := q;
>             while qpow le qlimit do
>                 // For all powers qpow of q up to qlimit...
>
>                 if den mod qpow eq 0 then break; end if;
>                 c2 := num * Modinv(den, qpow) mod qpow;
>                 if c2 eq 0 then c2 := qpow; end if;
>
>                 nextqpow := qpow*q;
>                 // Ensure c2 >= c1 to remove redundant relations.
>                 while c2 lt c1 do
>                     c2 +:= qpow;
>                 end while;
>
>                 while c2 le #sieve do
>                     // Add logq into sieve for c2.
>                     sieve[c2] +:= logq;
>
>                     // Test higher powers of q if nextqpow is too large.
>                     if nextqpow gt qlimit then
>                         prod := (J + (c1 + c2)*H + c1*c2) mod p;
>                         nextp := nextqpow;
>                         while prod mod nextp eq 0 do
>                             sieve[c2] +:= logq;
>                             nextp *:= q;
>                         end while;
>                     end if;
>                     c2 +:= qpow;
>                 end while;
>                 qpow := nextqpow;
>             end while;
>         end for;
>
>         // Check sieve for full factorizations.
>         rel := den * (H + 1);   // the relation
>         relinc := H + c1;       // add to relation to get next relation
>         count := 0;
>         for c2 in [1 .. #sieve] do
>             n := rel mod p;
>             if Abs(sieve[c2] - Ilog2(n)) lt 1 then
>                 fact, r := TrialDivision(n, qlimit);
>                 if r eq 1 then // n is qlimit-smooth
>                     // Include each H + c_i in extended factor basis.
>                     Include(~FB, H + c1);
>                     Include(~FB, H + c2);
>
>                     // Include relation (H + c1)*(H + c2) = fact.
>                     row := Nrows(A) + 1;
>                     for t in fact do
>                         SetEntry(~A, row, Index(FB, t[1]), t[2]);
>                     end for;
>                     if c1 eq c2 then
>                         SetEntry(~A, row, Index(FB, H + c1), -2);
>                     else
>                         SetEntry(~A, row, Index(FB, H + c1), -1);
>                         SetEntry(~A, row, Index(FB, H + c2), -1);
>                     end if;
>                 end if;
>             end if;
>             rel +:= relinc;
>         end for;
>     end for;
>
>     // Check matrix by multiplying out relations in field.
>     assert {&*[(K!FB[j])^A[k, j]: j in Support(A, k)]: k in [1..Nrows(A)]}
>             eq {1};
>
>     return A, FB;
> end function;
```

We first apply the function to a trivial example to illustrate the main points. We let $K$ be ${\bf F}_{103}$, and we make the factor basis include primes up to 35, the $c_i$ range be up to 27, and the stopping ratio be 1.1. We first compute the relation matrix $A$ and the extended factor basis $F$.

```magma
> K := GF(103);
> A, F := Sieve(K, 35, 27, 1.1);
Factor base has 11 primes, climit is 27
> A;
Sparse matrix with 33 rows and 30 columns over Integer Ring
```

We examine a few rows of $A$ and the extended factor basis $F$. Note that 5 is the smallest prime which is primitive in $K$, so it has been inserted first in $F$.

```magma
> A[1]; A[2]; A[30];
(1 0 0 0 0 1 0 0 0 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
(0 0 0 1 1 0 0 0 0 0 0 -1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 -1 0 0 0 0 0)
> F;
{@ 5, 2, 3, 7, 11, 13, 17, 19, 23, 29, 31, 12, 14, 15, 16, 21, 38,
20, 26, 35, 22, 33, 34, 24, 25, 28, 30, 37, 32, 36 @}
```

Next we compute a solution vector $v$ such that $v\cdot A^{tr} = 0$ modulo $M=\#K - 1$.

```magma
> Factorization(#K-1);
[ <2, 1>, <3, 1>, <17, 1> ]
> v := ModularSolution(A, #K - 1);
> v;
(1 44 39 4 61 72 70 80 24 86 57 25 48 40 74 43 22 0 1 5 3 100 12 69 2
    92 84 93 16 64)
```

Notice that 0 occurs in $v$, so the corresponding logarithm is not known. The vector is normalized so that the logarithm of 5 is 1, as desired. We finally compute the powers of the primitive element of $K$ by each element of $v$ and check that all of these match the entries of $F$ except for the one missed entry. Note also that because $M$ has small prime divisors, it is fortunate that the logarithms are all correct, apart from the missed one.

```magma
> a := PrimitiveElement(K);
> a;
5
> Z := IntegerRing();
> [a^Z!x: x in Eltseq(v)];
[ 5, 2, 3, 7, 11, 13, 17, 19, 23, 29, 31, 12, 14, 15, 16, 21, 38, 1,
5, 35, 22, 33, 34, 24, 25, 28, 30, 37, 32, 36 ]
> F;
{@ 5, 2, 3, 7, 11, 13, 17, 19, 23, 29, 31, 12, 14, 15, 16, 21, 38, 20,
26, 35, 22, 33, 34, 24, 25, 28, 30, 37, 32, 36 @}
```

Finally, we take $K={\bf F}_{p}$, where $p$ is the smallest prime above $10^{20}$ such that $(p-1)/2$ is prime. The sparse matrix constructed here is close to $1000\times 1000$, but the solution vector is still found in less than a second.

```magma
> K := GF(100000000000000000763);
> Factorization(#K - 1);
[ <2, 1>, <50000000000000000381, 1> ]
> time A, F := Sieve(K, 2200, 800, 1.1);
Factor base has 327 primes, climit is 800
c1: 50, #rows: 222, #cols: 555, ratio: 0.4
c1: 100, #rows: 444, #cols: 738, ratio: 0.60162602
c1: 150, #rows: 595, #cols: 836, ratio: 0.71172249
c1: 200, #rows: 765, #cols: 921, ratio: 0.83061889
c1: 250, #rows: 908, #cols: 973, ratio: 0.9331963
c1: 300, #rows: 1014, #cols: 1011, ratio: 1.003
c1: 350, #rows: 1105, #cols: 1023, ratio: 1.0802
Time: 3.990
> A;
Sparse matrix with 1141 rows and 1036 columns over Integer Ring
> time v := ModularSolution(A, #K - 1);
Time: 0.170
```

We observe that the list consisting of the primitive element powered by the computed logarithms agrees with the factor basis for at least the first 30 elements.

```magma
> a := PrimitiveElement(K);
> a;
2
> v[1], v[2];
1 71610399209536789314
> a^71610399209536789314;
3
> P := [a^x: x in Eltseq(v)];
> [P[i]: i in [1 .. 30]];
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113 ]
> [F[i]: i in [1 .. 30]];
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113 ]
```

There are in fact 8 logarithms which could not be computed correctly.

```magma
> [i: i in [1..#F] | P[i] ne F[i]];
[ 671, 672, 673, 737, 738, 947, 1024, 1025 ]
```

A zero value appearing in the place of a logarithm indicates that the nullity of the system was larger than 1, even considered modulo $(\#K - 1)/2$.

```magma
> [v[i]: i in [1..#F] | P[i] ne F[i]];
[ 0, 22076788376647522787, 73252391663364176895, 0,
33553634905886614528, 42960107136526083388, 0, 57276316725691590267 ]
> [P[i]: i in [1..#F] | P[i] ne F[i]];
[ 1, 7480000052677, 7960000056517, 1, 5220000041437,
8938028430619715763, 1, 11360000275636 ]
```

However, we have found the correct logarithms for nearly all factor basis elements. As pointed out above, the Pollard-Rho method applied to an element of the factor basis for this field would take many hours!

<a id="vector-space-linear-transformation"></a>
<a id="chapvectspace"></a>
## Vector Spaces

- [Introduction](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/introduction.md)
  - [Vector Space Categories](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/introduction.md#vector-space-categories)
  - [The Construction of a Vector Space](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/introduction.md#the-construction-of-a-vector-space)
- [Creation of Vector Spaces and Arithmetic with Vectors](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md)
  - [Construction of a Vector Space](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#construction-of-a-vector-space)
    - [`VectorSpace(K, n): Fld, RngIntElt → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-vectorspace-fld-rngintelt)
    - [`KSpace(K, n): Fld, RngIntElt → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-kspace-fld-rngintelt)
    - [`KModule(K, n): Fld, RngIntElt → ModFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-kmodule-fld-rngintelt)
    - [`KMatrixSpace(K, m, n): Fld, RngIntElt, RngIntElt → ModMatFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-kmatrixspace-fld-rngintelt-rngintelt)
    - [`Hom(V, W): ModTupFld, ModTupFld → ModMatFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-hom-modtupfld-modtupfld)
    - [Example: Rational Vector Space of Dimension 6](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#example-ex-d5b27e)
    - [Example: Matrix Space over a Quadratic Field](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#example-ex-4fca7f)
  - [Construction of a Vector Space with Inner Product Matrix](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#construction-of-a-vector-space-with-inner-product-matrix)
    - [`VectorSpace(K, n, F): Fld, RngIntElt, Mtrx → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-vectorspace-fld-rngintelt-mtrx)
    - [`KSpace(K, n, F): Fld, RngIntElt, Mtrx → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-kspace-fld-rngintelt-mtrx)
  - [Construction of a Vector](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#construction-of-a-vector)
    - [`elt<V | L>: ModTupFld, List → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#constructor-constructor-elt-modtupfld-list-modtupfldelt)
    - [`V ! Q: ModTupFld, [RngElt] → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#operation-op-modtupfld-rngelt)
    - [`CharacteristicVector(V, S): ModTupFld, { RngElt } → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-characteristicvector-modtupfld-rngelt)
    - [`V ! 0: ModTupFld, RngIntElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#operation-op-modtupfld-rngintelt)
    - [`Zero(V): ModTupFld → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-zero-modtupfld)
    - [`Random(V): ModTupFld → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-random-modtupfld)
    - [Example: Vector over a Finite Field](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#example-ex-df9b72)
    - [Example: Matrix over a Number Field](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#example-ex-d17116)
  - [Deconstruction of a Vector](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#deconstruction-of-a-vector)
    - [`ElementToSequence(u): ModTupFldElt → [RngElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-elementtosequence-modtupfldelt)
    - [`Eltseq(u): ModTupFldElt → [RngElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-eltseq-modtupfldelt)
  - [Arithmetic with Vectors](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#arithmetic-with-vectors)
    - [`u + v: ModTupFldElt, ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#operation-op-plus-modtupfldelt-modtupfldelt)
    - [`- u: ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#operation-operation-modtupfldelt-modtupfldelt)
    - [`u - v: ModTupFldElt, ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#operation-op-minus-modtupfldelt-modtupfldelt)
    - [`x * u: FldElt, ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#operation-op-times-fldelt-modtupfldelt)
    - [`u * x: ModTupFldElt, FldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#operation-op-times-modtupfldelt-fldelt)
    - [`u / x: ModTupFldElt, FldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#operation-op-div-modtupfldelt-fldelt)
    - [`NumberOfColumns(u): ModTupFldElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-numberofcolumns-modtupfldelt)
    - [`Ncols(u): ModTupFldElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-ncols-modtupfldelt)
    - [`Depth(u): ModTupRngElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-depth-modtuprngelt)
    - [`(u, v): ModTupFldElt, ModTupFldElt → FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#literal-literal-u-v-modtupfldelt-modtupfldelt-fldelt)
    - [`InnerProduct(u, v): ModTupFldElt, ModTupFldElt → FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-innerproduct-modtupfldelt-modtupfldelt)
    - [`IsZero(u): ModElt → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-iszero-modelt)
    - [`Norm(u): ModTupFldElt → FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-norm-modtupfldelt)
    - [`Normalise(u): ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-normalise-modtupfldelt)
    - [`Normalize(u): ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-normalize-modtupfldelt)
    - [`Rotate(u, k): ModTupFldElt, RngIntElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-rotate-modtupfldelt-rngintelt)
    - [`Rotate(~u, k): ModTupFldElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#procedure-rotate-modtupfldelt-rngintelt-ref)
    - [`NumberOfRows(u): ModTupFldElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-numberofrows-modtupfldelt)
    - [`Nrows(u): ModTupFldElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-nrows-modtupfldelt)
    - [`Support(u): ModTupFldElt → { RngElt }`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-support-modtupfldelt)
    - [`TensorProduct(u, v): ModTupFldElt, ModTupFldElt → FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-tensorproduct-modtupfldelt-modtupfldelt)
    - [`Trace(u, F): ModTupFldElt, Fld → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-trace-modtupfldelt-fld)
    - [`Trace(u): ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-trace-modtupfldelt)
    - [`Weight(u): ModTupFldElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#function-weight-modtupfldelt)
    - [Example: Vector Arithmetic over a Cyclotomic Field](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#example-ex-ca5d9a)
    - [Example: Defining a Nontrivial Inner Product](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#example-ex-e5eb13)
  - [Indexing Vectors and Matrices](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#indexing-vectors-and-matrices)
    - [`u[i]: ModTupFldElt, RngIntElt → RngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#literal-literal-u-i-modtupfldelt-rngintelt-rngelt)
    - [`u[i]: ModTupFldElt, RngIntElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#indexed-indexed-u-modtupfldelt-rngintelt-modtupfldelt)
    - [`u[i, j]: ModTupFldElt, RngIntElt, RngIntElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#indexed-indexed-u-modtupfldelt-rngintelt-rngintelt-modtupfldelt)
    - [`u[i] := x: ModTupFldElt, RngIntElt, RngElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#literal-literal-u-i-x-modtupfldelt-rngintelt-rngelt-modtupfldelt)
    - [`u[i] := x: ModTupFldElt, RngIntElt, ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#literal-literal-u-i-x-modtupfldelt-rngintelt-modtupfldelt-modtupfldelt)
    - [`u[i, j] := x: ModTupFldElt, RngIntElt, RngIntElt, ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#literal-literal-u-i-j-x-modtupfldelt-rngintelt-rngintelt-modtupfldelt-modtupfldelt)
    - [Example: Indexing Tuple and Matrix Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/creation-arithmetic.md#example-ex-876f3e)
- [Subspaces, Quotient Spaces, and Homomorphisms](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md)
  - [Construction of Subspaces](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#construction-of-subspaces)
    - [`sub<V | L>: ModTupFld, List → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#constructor-constructor-sub-modtupfld-list-modtupfld)
    - [`Morphism(U, V): ModTupFld, ModTupFld → RModMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#function-morphism-modtupfld-modtupfld)
    - [Example: Golay Code in a Vector Space](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#example-ex-466045)
    - [Example: Golay Code in an R-Module](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#example-ex-1f57d1)
  - [Construction of Quotient Vector Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#construction-of-quotient-vector-spaces)
    - [`quo<V | L>: ModTupFld, List → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#constructor-constructor-quo-modtupfld-list-modtupfld-map)
    - [`V / U: ModTupFld, ModTupFld → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#operation-op-div-modtupfld-modtupfld)
    - [Example: Quotient by the Golay Code](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#example-ex-4d668d)
    - [Example: Golay Quotient as a Complement](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#example-ex-e0a05b)
    - [Example: Quotient of a Rational Matrix Space](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/subspace-quotient-homomorphism.md#example-ex-aceeb2)
- [Changing the Coefficient Field](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/modification-coefficient-field.md)
  - [`ExtendField(V, L): ModTupFld, Fld → ModTupFld, MapHom`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/modification-coefficient-field.md#function-extendfield-modtupfld-fld)
  - [`RestrictField(V, L): ModTupFld, Fld → ModTupFld, MapHom`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/modification-coefficient-field.md#function-restrictfield-modtupfld-fld)
  - [`VectorSpace(V, F): ModTupFld, Fld → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/modification-coefficient-field.md#function-vectorspace-modtupfld-fld)
  - [`KSpace(V, F): ModTupFld, Fld → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/modification-coefficient-field.md#function-kspace-modtupfld-fld)
  - [`KMatrixSpace(V, F): ModTupFld, Fld → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/modification-coefficient-field.md#function-kmatrixspace-modtupfld-fld)
  - [`KModule(V, F): ModTupFld, Fld → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/modification-coefficient-field.md#function-kmodule-modtupfld-fld)
- [Basic Operations](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md)
  - [Accessing Vector Space Invariants](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#accessing-vector-space-invariants)
    - [`V . i: ModTupFld, RngIntElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-operation-modtupfld-rngintelt-modtupfldelt)
    - [`CoefficientField(V): ModTupFld → Fld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-coefficientfield-modtupfld)
    - [`BaseField(V): ModTupFld → Fld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-basefield-modtupfld)
    - [`Degree(V): ModTupFld → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-degree-modtupfld)
    - [`Degree(u): ModTupFldElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-degree-modtupfldelt)
    - [`Dimension(V): ModTupFld → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-dimension-modtupfld)
    - [`Generators(V): ModTupFld → { ModElt}`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-generators-modtupfld)
    - [`NumberOfGenerators(M): ModTupFld → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-numberofgenerators-modtupfld)
    - [`Ngens(M): ModTupFld → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-ngens-modtupfld)
    - [`OverDimension(V): ModTupFld → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-overdimension-modtupfld)
    - [`OverDimension(u): ModTupFldElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-overdimension-modtupfldelt)
    - [`Generic(V): ModFld → ModFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-generic-modfld)
    - [`Parent(V): ModFld → SetPow`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-parent-modfld)
  - [Membership and Equality](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#membership-and-equality)
    - [`v in V: ModTupFldElt, ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-op-in-modtupfldelt-modtupfld)
    - [`v notin V: ModTupFldElt, ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-op-notin-modtupfldelt-modtupfld)
    - [`U subset V: ModTupFld, ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-op-subset-modtupfld-modtupfld)
    - [`U notsubset V: ModTupFld, ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-operation-notsubset-modtupfld-modtupfld-boolelt)
    - [`U eq V: ModTupFld, ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-op-eq-modtupfld-modtupfld)
    - [`U ne V: ModTupFld, ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-op-ne-modtupfld-modtupfld)
  - [Operations on Subspaces](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operations-on-subspaces)
    - [`U + V: ModTupFld, ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-op-plus-modtupfld-modtupfld)
    - [`U meet V: ModTupFld, ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-op-meet-modtupfld-modtupfld)
    - [`U meet:= V: ModTupFld, ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-operation-meet-modtupfld-modtupfld-modtupfld)
    - [`&meet S: [ ModTupFld ] → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#operation-operation-meet-modtupfld-modtupfld)
    - [`TensorProduct(U, V): ModTupFld, ModTupFld → FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-tensorproduct-modtupfld-modtupfld)
    - [`Complement(V, U): ModTupFld, ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-complement-modtupfld-modtupfld)
    - [`Transversal(V, U): ModTupFld, ModTupFld → { ModTupFldELt}`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/operation.md#function-transversal-modtupfld-modtupfld)
- [Reducing Vectors Relative to a Subspace](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/reducing-vectors.md)
  - [`ReduceVector(W, v): ModTupRng, ModTupRngElt → ModTupRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/reducing-vectors.md#function-reducevector-modtuprng-modtuprngelt)
  - [`ReduceVector(W, ~v): ModTupRng, ModTupRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/reducing-vectors.md#procedure-reducevector-modtuprng-modtuprngelt-2)
  - [`DecomposeVector(U, v): ModTupRng, ModTupRngElt → ModTupRngElt, ModTupRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/reducing-vectors.md#function-decomposevector-modtuprng-modtuprngelt)
- [Bases](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md)
  - [`VectorSpaceWithBasis(Q): [ModTupFldElt] → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-vectorspacewithbasis-modtupfldelt)
  - [`VectorSpaceWithBasis(a): AlgMatElt → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-vectorspacewithbasis-algmatelt)
  - [`VectorSpaceWithBasis(a): ModMatFldElt → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-vectorspacewithbasis-modmatfldelt)
  - [`KSpaceWithBasis(Q): [ModTupFldElt] → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-kspacewithbasis-modtupfldelt)
  - [`KSpaceWithBasis(a): AlgMatElt → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-kspacewithbasis-algmatelt)
  - [`KSpaceWithBasis(a): ModMatFldElt → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-kspacewithbasis-modmatfldelt)
  - [`KModuleWithBasis(Q): [ModTupFldElt] → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-kmodulewithbasis-modtupfldelt)
  - [`Basis(V): ModTupFld → [ModTupFldElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-basis-modtupfld)
  - [`BasisElement(V, i): ModTupFld, RngIntElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-basiselement-modtupfld-rngintelt)
  - [`BasisMatrix(V): ModTupFld → ModMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-basismatrix-modtupfld)
  - [`Coordinates(V, v): ModTupFld, ModTupFldElt → [FldElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-coordinates-modtupfld-modtupfldelt)
  - [`Dimension(V): ModTupFld → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-dimension-modtupfld-2)
  - [`ExtendBasis(Q, U): [ModTupFldElt], ModTupFld → [ModTupFldElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-extendbasis-modtupfldelt-modtupfld)
  - [`ExtendBasis(U, V): ModTupFld, ModTupFld → [ModTupFldElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-extendbasis-modtupfld-modtupfld)
  - [`IsIndependent(S): { ModTupFldElt} → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-isindependent-modtupfldelt)
  - [`IsIndependent(Q): [ ModTupFldElt ] → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#function-isindependent-modtupfldelt-2)
  - [Example: Bases of the Ternary Golay Code](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/basis.md#example-ex-a4fb0c)
- [Operations with Linear Transformations](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md)
  - [`v * a: ModTupFldElt, ModMatFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#operation-op-times-modtupfldelt-modmatfldelt)
  - [`a(v): ModMatFldElt, ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#literal-a-modmatfldelt-modtupfldelt)
  - [`a * b: ModMatRngElt, ModMatRngElt → ModMatRngElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#operation-op-times-modmatrngelt-modmatrngelt)
  - [`Domain(a): ModMatRngElt → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#function-domain-modmatrngelt)
  - [`Codomain(a): ModMatRngElt → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#function-codomain-modmatrngelt)
  - [`Image(a): ModMatRngElt → ModTupRng, Map, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#function-image-modmatrngelt)
  - [`Rank(a): ModMatRngElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#function-rank-modmatrngelt)
  - [`Kernel(a): ModMatRngElt → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#function-kernel-modmatrngelt)
  - [`NullSpace(a): ModMatRngElt → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#function-nullspace-modmatrngelt)
  - [`Cokernel(a): ModMatRngElt → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#function-cokernel-modmatrngelt)
  - [Example: Operations on Linear Transformations](https://docs.magma-maths.org/MatricesLinearAlgebra/VectorSpaces/linear-transformation.md#example-ex-135cf0)

### Introduction

In this chapter we will discuss vector spaces and their linear transformations. Let $K$ be a field. In Magma, the standard $K$-vector space is taken to be the set of $n$-tuples over the field $K$, which we shall write as $K^{(n)}$. A rectangular matrix over a field $K$ is considered to be an element of the vector space consisting of all $m \times n$ matrices over $K$. This vector space will be written as $K^{(m \times n)}$. Let $U$ and $V$ be $K$-vector spaces of dimensions $m$ and $n$, respectively. The set of all linear transformations with domain $U$ and codomain $V$ will be denoted by ${\operatorname{Hom}}_K(U, V)$. Once bases have been chosen for $U$ and $V$, we may identify ${\operatorname{Hom}}_K(U, V)$ with $K^{(m \times n)}$. Thus, $K^{(m \times n)}$ is first of all a vector space and all the normal vector space operations apply. However, since it is also a set of mappings, some additional operations arising from this characterization apply. We shall use the term *vector space* or $K$*-vector space* (if we wish to emphasize the coefficient field) to refer to both the space $K^{(n)}$ and the space $K^{(m \times n)}$. If we wish to differentiate between the two, we shall use the term *tuple space* when referring to $K^{(n)}$ and the term *matrix space* referring to $K^{(m \times n)}$.

#### Vector Space Categories

The family of all finite dimensional vector spaces over a given field $K$ forms a category, while the set of all finite dimensional vector spaces forms a family of categories indexed by the field $K$. In this family of categories, objects are vector spaces and the morphisms are linear transformations. The (indexed family of) categories consisting of vector spaces of $n$-tuples has the name `ModTupFld`, while the (indexed family of) categories consisting of vector spaces of $m \times n$-matrices has the name `ModMatFld`.

#### The Construction of a Vector Space

Every vector space $V$ defined over a field $K$ is created either as a subspace of the row space $K^{(n)}$ (tuple spaces) or as a subspace of $K^{(m \times n)}$ (matrix modules). Thus, the construction of a general vector space is a two step process:

**(i)**
The appropriate row space $K^{(n)}$, is constructed;

**(ii)**
The required vector space $V$ is then defined as a subspace or quotient space of $K^{(n)}$.

### Creation of Vector Spaces and Arithmetic with Vectors

#### Construction of a Vector Space

<a id="function-vectorspace-fld-rngintelt"></a>
##### `VectorSpace(K, n): Fld, RngIntElt -> ModTupFld`

<a id="function-kspace-fld-rngintelt"></a>
##### `KSpace(K, n): Fld, RngIntElt -> ModTupFld`

Given a field $K$ and a non-negative integer $n$, create the $n$-dimensional vector space $V = K^{(n)}$, consisting of all $n$-tuples over $K$. The vector space is created with respect to the standard basis, $e_1, \ldots, e_n$, where $e_i$ $(i = 1, \ldots, n)$ is the vector containing a $1$ in the $i$-th position and zeros elsewhere.

Use of the functions `VectorSpace` and `KSpace` ensures that subspaces of $V$ will be presented in embedded form.

<a id="function-kmodule-fld-rngintelt"></a>
##### `KModule(K, n): Fld, RngIntElt -> ModFld`

Given a field $K$ and a non-negative integer $n$, create the $n$-dimensional vector space $V = K^{(n)}$, consisting of all $n$-tuples over $K$. The vector space is created with respect to the standard basis, $e_1, \ldots, e_n$, where $e_i$ $(i = 1, \ldots, n)$ is the vector containing a $1$ in the $i$-th position and zeros elsewhere.

Use of the function `KModule` ensures that subspaces of $V$ will be presented in reduced form. In all other respects, a vector space created by this function is identical to one created by `KSpace`.

<a id="function-kmatrixspace-fld-rngintelt-rngintelt"></a>
##### `KMatrixSpace(K, m, n): Fld, RngIntElt, RngIntElt -> ModMatFld`

Given a field $K$ and integers $m$ and $n$ greater than one, create the vector space $K^{(m \times n)}$, consisting of all $m \times n$ matrices over $K$. The vector space is created with the standard basis, $\{E_{ij}\  |\  i = 1 \ldots, m, j = 1 \ldots, n\}$, where $E_{ij}$ is the matrix having a $1$ in the ($i, j$)-th position and zeros elsewhere. Note that for a matrix space, subspaces will always be presented in embedded form, i.e. there is no reduced mode available for matrix spaces.

<a id="function-hom-modtupfld-modtupfld"></a>
##### `Hom(V, W): ModTupFld, ModTupFld -> ModMatFld`

If $V$ is the vector space $K^{(m)}$ and $W$ is the vector space $K^{(n)}$, create the matrix space ${\operatorname{Hom}}_{K}(V, W)$ as the vector space $K^{(m \times n)}$, represented as the set of all $m \times n$ matrices over $K$. The vector space is created with the standard basis, $\{E_{ij}\  |\  i = 1 \ldots, m, j = 1 \ldots, n\}$, where $E_{ij}$ is the matrix having a $1$ in the ($i, j$)-th position and zeros elsewhere.

<a id="example-ex-d5b27e"></a>
##### `Example: Rational Vector Space of Dimension 6 (ex-d5b27e)`

We construct the vector space $V$ consisting of $6$-tuples over the rational field.

```magma
> Q := RationalField();
> V := VectorSpace(Q, 6);
> V;
Vector space of dimension 6 over Rational Field
```

<a id="example-ex-4fca7f"></a>
##### `Example: Matrix Space over a Quadratic Field (ex-4fca7f)`

We construct the matrix space $M$ consisting of $3 \times 5$ matrices over the field ${\mathbb{Q}}(\sqrt{5})$.

```magma
> K<w> := QuadraticField(5);
> V := KMatrixSpace(K, 3, 5);
> V;
Full Vector Space of 3 by 5 matrices over Quadratic Field Q(w)
```

#### Construction of a Vector Space with Inner Product Matrix

<a id="function-vectorspace-fld-rngintelt-mtrx"></a>
##### `VectorSpace(K, n, F): Fld, RngIntElt, Mtrx -> ModTupFld`

<a id="function-kspace-fld-rngintelt-mtrx"></a>
##### `KSpace(K, n, F): Fld, RngIntElt, Mtrx -> ModTupFld`

Given a field $K$, a non-negative integer $n$, and a square $n \times n$ symmetric matrix $F$, create the $n$-dimensional vector space $V = K^{(n)}$ (in embedded form), with inner product matrix $F$. This is the same as `VectorSpace(K, n)`, except that the functions `Norm` and `InnerProduct` (see below) will be with respect to the inner product matrix $F$.

#### Construction of a Vector

<a id="constructor-constructor-elt-modtupfld-list-modtupfldelt"></a>
##### `elt<V | L>: ModTupFld, List -> ModTupFldElt`

**(1)**
Suppose $V$ is a subspace of the vector space $K^{(n)}$. Given elements $a_1, \ldots, a_n$ belonging to $K$, construct the vector $v = (a_1, \ldots, a_n)$ as a vector of $V$. Note that if $v$ is not an element of $V$, an error will result.

**(2)**
Suppose $V$ is a subspace of the matrix space $K^{(m \times n)}$. Given elements $a_1, \ldots, a_{mn}$ belonging to $K$, construct the matrix $m = (a_1, \ldots, a_{mn})$ as an element of $V$. Note that if $m$ is not an element of $V$, an error will result.

<a id="operation-op-modtupfld-rngelt"></a>
##### `V ! Q: ModTupFld, [RngElt] -> ModTupFldElt`

**(1)**
Suppose $V$ is a subspace of the vector space $K^{(n)}$. Given elements $a_1, \ldots, a_n$ belonging to $K$, construct the vector $v = (a_1, \ldots, a_n)$ as a vector of $V$. Note that if $v$ is not an element of $V$, an error will result.

**(2)**
Suppose $V$ is a subspace of the matrix space $K^{(m \times n)}$. Given elements $a_1, \ldots, a_{mn}$ belonging to $K$, construct the matrix $m = (a_1, \ldots, a_{mn})$ as an element of $V$. Note that if $m$ is not an element of $V$, an error will result.

<a id="function-characteristicvector-modtupfld-rngelt"></a>
##### `CharacteristicVector(V, S): ModTupFld, { RngElt } -> ModTupFldElt`

Given a subspace $V$ of the vector space $K^{(n)}$ together with a set $S$ of integers lying in the interval $[1, n]$, return the characteristic number of $S$ as a vector of $V$.

<a id="operation-op-modtupfld-rngintelt"></a>
##### `V ! 0: ModTupFld, RngIntElt -> ModTupFldElt`

<a id="function-zero-modtupfld"></a>
##### `Zero(V): ModTupFld -> ModTupFldElt`

The zero element for the vector space $V$.

<a id="function-random-modtupfld"></a>
##### `Random(V): ModTupFld -> ModTupFldElt`

Given a vector space $V$ defined over a finite field, return a random vector.

<a id="example-ex-df9b72"></a>
##### `Example: Vector over a Finite Field (ex-df9b72)`

We create the 5-dimensional vector space $V$ over ${\bf F}_{4}$ and define the vector $u = (1, w, 1+w, 0, 0)$, where $w$ is a primitive element of ${\bf F}_{4}$.

```magma
> K<w> := GaloisField(4);
> V    := VectorSpace(K, 5);
> u    := V ! [1, w, 1+w, 0, 0];
> u;
(1 w w + 1 0 0)
> zero := V ! 0;
> zero;
(0 0 0 0 0)
r := Random(V);
(1 0 w 1 w + 1)
```

<a id="example-ex-d17116"></a>
##### `Example: Matrix over a Number Field (ex-d17116)`

We create an element belonging to the space of $3 \times 4$ matrices over the number field ${\mathbb{Q}}(w)$, where $w$ is a root of $x^7 - 7x + 3$.

```magma
> R<x> := PolynomialRing(RationalField());
> L<w> := NumberField(x^7 - 7*x + 3);
> L34 := KMatrixSpace(L, 3, 4);
> a := L34 ! [ 1, w, 0, -w, 0, 1+w, 2, -w^3, w-w^3, 2*w, 1/3, 1 ];
> a;
[1    w    0    -1 * w]
[0    w + 1    2    -1 * w^3]
[-1 * w^3 + w    2 * w    1/3    1]
```

#### Deconstruction of a Vector

<a id="function-elementtosequence-modtupfldelt"></a>
##### `ElementToSequence(u): ModTupFldElt -> [RngElt]`

<a id="function-eltseq-modtupfldelt"></a>
##### `Eltseq(u): ModTupFldElt -> [RngElt]`

Given an element $u$ belonging to the $K$-vector space $V$, return $u$ in the form of a sequence $Q$ of elements of $V$. Thus, if $u$ is an element of $K^{(n)}$, then $Q[i] = u[i]$, $1 \leq i \leq n$.

#### Arithmetic with Vectors

For the following operations the vectors $u$ and $v$ must belong to the same vector space i.e. the same tuple space $K^{(n)}$ or the same matrix space $K^{(m \times n)}$. The scalar $a$ must belong to the field $K$.

<a id="operation-op-plus-modtupfldelt-modtupfldelt"></a>
##### `u + v: ModTupFldElt, ModTupFldElt -> ModTupFldElt`

Sum of the vectors $u$ and $v$, where $u$ and $v$ lie in the same vector space.

<a id="operation-operation-modtupfldelt-modtupfldelt"></a>
##### `- u: ModTupFldElt -> ModTupFldElt`

Additive inverse of the vector $u$.

<a id="operation-op-minus-modtupfldelt-modtupfldelt"></a>
##### `u - v: ModTupFldElt, ModTupFldElt -> ModTupFldElt`

Difference of the vectors $u$ and $v$, where $u$ and $v$ lie in the same vector space.

<a id="operation-op-times-fldelt-modtupfldelt"></a>
##### `x * u: FldElt, ModTupFldElt -> ModTupFldElt`

<a id="operation-op-times-modtupfldelt-fldelt"></a>
##### `u * x: ModTupFldElt, FldElt -> ModTupFldElt`

The scalar product of the vector $u$ belonging to the $K$-vector space and the field element $x$ belonging to $K$.

<a id="operation-op-div-modtupfldelt-fldelt"></a>
##### `u / x: ModTupFldElt, FldElt -> ModTupFldElt`

The scalar product of the vector $u$ belonging to the $K$-vector space and the field element $1/x$ belonging to $K$ where $x$ is non-zero.

<a id="function-numberofcolumns-modtupfldelt"></a>
##### `NumberOfColumns(u): ModTupFldElt -> RngIntElt`

<a id="function-ncols-modtupfldelt"></a>
##### `Ncols(u): ModTupFldElt -> RngIntElt`

The number of columns in the vector $u$.

<a id="function-depth-modtuprngelt"></a>
##### `Depth(u): ModTupRngElt -> RngIntElt`

The index of the first non-zero entry of the vector $u$ (0 if none such).

<a id="literal-literal-u-v-modtupfldelt-modtupfldelt-fldelt"></a>
##### `(u, v): ModTupFldElt, ModTupFldElt -> FldElt`

<a id="function-innerproduct-modtupfldelt-modtupfldelt"></a>
##### `InnerProduct(u, v): ModTupFldElt, ModTupFldElt -> FldElt`

Return the inner product of the vectors $u$ and $v$ with respect to the inner product defined on the space. If an inner product matrix $F$ is given when the space is created, then this is defined to be $u\cdot F\cdot v^{tr}$. Otherwise, this is simply $u\cdot v^{tr}$.

<a id="function-iszero-modelt"></a>
##### `IsZero(u): ModElt -> BoolElt`

Returns `true` iff the vector $u$ belonging to a vector space is the zero element.

<a id="function-norm-modtupfldelt"></a>
##### `Norm(u): ModTupFldElt -> FldElt`

Return the norm product of the vector $u$ with respect to the inner product defined on the space. If an inner product matrix $F$ is given when the space is created, then this is defined to be $u\cdot F\cdot u^{tr}$. Otherwise, this is simply $u\cdot u^{tr}$.

<a id="function-normalise-modtupfldelt"></a>
##### `Normalise(u): ModTupFldElt -> ModTupFldElt`

<a id="function-normalize-modtupfldelt"></a>
##### `Normalize(u): ModTupFldElt -> ModTupFldElt`

Given an element $u$, not the zero element, belonging to the $K$-vector space $V$, return ${1\over a}*u$, where $a$ is the first non-zero component of $u$. If $u$ is the zero vector, it is returned. The net effect is that `Normalize(u)` always returns a vector $v$ in the subspace generated by $u$, such that the first non-zero component of $v$ (if existent) is $K!1$.

<a id="function-rotate-modtupfldelt-rngintelt"></a>
##### `Rotate(u, k): ModTupFldElt, RngIntElt -> ModTupFldElt`

Given a vector $u$, return the vector obtained from $u$ by rotating by k coordinate positions.

<a id="procedure-rotate-modtupfldelt-rngintelt-ref"></a>
##### `Rotate(~u, k): ModTupFldElt, RngIntElt`

Given a vector $u$, destructively rotate $u$ by k coordinate positions.

<a id="function-numberofrows-modtupfldelt"></a>
##### `NumberOfRows(u): ModTupFldElt -> RngIntElt`

<a id="function-nrows-modtupfldelt"></a>
##### `Nrows(u): ModTupFldElt -> RngIntElt`

The number of rows in the vector $u$ (1 of course; included for completeness).

<a id="function-support-modtupfldelt"></a>
##### `Support(u): ModTupFldElt -> { RngElt }`

A set of integers giving the positions of the non-zero components of the vector $u$.

<a id="function-tensorproduct-modtupfldelt-modtupfldelt"></a>
##### `TensorProduct(u, v): ModTupFldElt, ModTupFldElt -> FldElt`

The tensor (Kronecker) product of the vectors $u$ and $v$. The resulting vector has degree equal to the product of the degrees of $u$ and $v$.

<a id="function-trace-modtupfldelt-fld"></a>
##### `Trace(u, F): ModTupFldElt, Fld -> ModTupFldElt`

<a id="function-trace-modtupfldelt"></a>
##### `Trace(u): ModTupFldElt -> ModTupFldElt`

Given a vector belonging to the space $K^{(n)}$, and a subfield $F$ of $K$, return the vector obtained by replacing each component of $u$ by its trace over the subfield $F$. If $F$ is the prime field of $K$, it may be omitted.

<a id="function-weight-modtupfldelt"></a>
##### `Weight(u): ModTupFldElt -> RngIntElt`

The number of non-zero components of the vector $u$.

<a id="example-ex-ca5d9a"></a>
##### `Example: Vector Arithmetic over a Cyclotomic Field (ex-ca5d9a)`

We illustrate the use of the arithmetic operators for module elements by applying them to elements of the $4$-dimensional vector space over the field ${\mathbb{Q}}(w)$, where $w$ is an $8$-th root of unity.

```magma
> K<w> := CyclotomicField(8);
> V := VectorSpace(K, 4);
> x := V ! [ w, w^2, w^4, 0];
> y := V ! [1, w, w^2, w^4];
> x + y;
(  w + 1 w^2 + w w^2 - 1      -1)
> -x;
(  -w -w^2    1    0)
> x - y;
(   w - 1  w^2 - w -w^2 - 1        1)
> w * x;
(w^2 w^3  -w   0)
> y * w^ -4;
(  -1   -w -w^2    1)
> Normalize(x);
(  1   w w^3   0)
> InnerProduct(x, y);
w^2 + 2*w
> z := V ! [1, 0, w, 0 ];
> z;
(1 0 w 0)
> Support(z);
{ 1, 3 }
```

<a id="example-ex-e5eb13"></a>
##### `Example: Defining a Nontrivial Inner Product (ex-e5eb13)`

We illustrate how one can define a non-trivial inner product on a space.

```magma
> Q := RationalField();
> F := SymmetricMatrix(Q, [1, 0,2, 0,0,3, 1,2,3,4]);
> F;
[1 0 0 1]
[0 2 0 2]
[0 0 3 3]
[1 2 3 4]
> V := VectorSpace(Q, 4, F);
> V;
Full Vector space of degree 4 over Rational Field
Inner Product Matrix:
[1 0 0 1]
[0 2 0 2]
[0 0 3 3]
[1 2 3 4]
> v := V![1,0,0,0];
> Norm(v);
1
> w := V![0,1,0,0];
> Norm(w);
2
> InnerProduct(v, w);
0
> z := V![0,0,0,1];
> Norm(z);
4
> InnerProduct(v, z);
1
> InnerProduct(w, z);
2
```

#### Indexing Vectors and Matrices

The indexing operations have a different meaning depending upon whether they are applied to a tuple space or a matrix space.

<a id="literal-literal-u-i-modtupfldelt-rngintelt-rngelt"></a>
##### `u[i]: ModTupFldElt, RngIntElt -> RngElt`

<a id="indexed-indexed-u-modtupfldelt-rngintelt-modtupfldelt"></a>
##### `u[i]: ModTupFldElt, RngIntElt -> ModTupFldElt`

<a id="indexed-indexed-u-modtupfldelt-rngintelt-rngintelt-modtupfldelt"></a>
##### `u[i, j]: ModTupFldElt, RngIntElt, RngIntElt -> ModTupFldElt`

Given a vector $u$ belonging to a $K$-vector space $V$, the result of this operation depends upon whether $V$ is a tuple or matrix space. If $V$ is a subspace of $K^{(n)}$, and $i$, $1 \leq i\leq n$, is a positive integer, the $i$-th component of the vector $u$ is returned (as an element of the field $K$). If $V$ is a subspace of $K^{(m \times n)}$, and $i$, $1 \leq i\leq m$, is a positive integer, $u[i]$ will return the $i$-th row of the matrix $u$ (as an element of the vector space $K^{(n)}$). Similarly, if $i$ and $j$, $1 \leq i\leq m$, $1 \leq j\leq n$, are positive integers, $u[i, j]$ will return the $(i,j)$-th component of the matrix $u$ (as an element of $K$).

<a id="literal-literal-u-i-x-modtupfldelt-rngintelt-rngelt-modtupfldelt"></a>
##### `u[i] := x: ModTupFldElt, RngIntElt, RngElt -> ModTupFldElt`

<a id="literal-literal-u-i-x-modtupfldelt-rngintelt-modtupfldelt-modtupfldelt"></a>
##### `u[i] := x: ModTupFldElt, RngIntElt, ModTupFldElt -> ModTupFldElt`

<a id="literal-literal-u-i-j-x-modtupfldelt-rngintelt-rngintelt-modtupfldelt-modtupfldelt"></a>
##### `u[i, j] := x: ModTupFldElt, RngIntElt, RngIntElt, ModTupFldElt -> ModTupFldElt`

Given a vector $u$ belonging to a $K$-vector space $V$, and an element $x$ of $K$, the result of this operation depends upon whether $V$ is a tuple or matrix space. If $V$ is a subspace of $K^{(n)}$, and $i$, $1 \leq i\leq n$, is a positive integer, the $i$-th component of the vector $u$ is redefined to be $x$. If $V$ is a subspace of $K^{(m \times n)}$ and $1 \leq i\leq m$ is a positive integer and $x$ is an element of $K^{(n)}$, `u[i] := x` will redefine the $i$-th row of the matrix $u$ to be the vector $x$, where $x$ must be an element of $K^{(n)}$. Similarly, if $1 \leq i\leq m$, $1 \leq j\leq n$, are positive integers, `u[i, j] := x` will redefine the $(i,j)$-th component of the matrix $u$ to be $x$, where $x$ must be an element of $K$.

<a id="example-ex-876f3e"></a>
##### `Example: Indexing Tuple and Matrix Spaces (ex-876f3e)`

We illustrate the use of the indexing operators for vector space elements by applying them to a $3$-dimensional tuple space and a $2 \times 3$ matrix space over the field ${\mathbb{Q}}(w)$, where $w$ is an $8$-th root of unity.

```magma
> K<w> := CyclotomicField(8);
> V := VectorSpace(K, 3);
> u := V ! [ 1 + w, w^ 2, w^ 4];
> u;
((1 + w)     (w^2)           -1)
> u[3];
-1
> u[3] := 1 + w - w^7;
> u;
((1 + w) (w^2) (1 + w + w^3))
> // We now demonstrate indexing a matrix space
> W := KMatrixSpace(K, 2, 3);
> l := W ! [ 1 - w, 1 + w, 1 + w + w^2, 0, 1 - w^7, 1 - w^3 + w^6 ];
> l;
[(1 - w) (1 + w) (1 + w + w^2)]
[0 (1 + w^3) (1 - w^2 - w^3)]
> l[2];
(0 (1 + w^3) (1 - w^2 - w^3))
> l[2,2];
(1 + w^3)
> m := l[2];
> m;
(0 (1 + w^3) (1 - w^2 - w^3))
> l[2] := u;
> l;
[(1 - w) (1 + w) (1 + w + w^2)]
[(1 + w) (w^2) -1]
> l[2, 3] := 1 + w - w^7;
> l;
[(1 - w) (1 + w) (1 + w + w^2)]
[(1 + w) (w^2) (1 + w + w^3)]
```

### Subspaces, Quotient Spaces, and Homomorphisms

#### Construction of Subspaces

The conventions defining the presentations of subspaces and quotient spaces are as follows:

**•**
If $V$ has been created using the function `VectorSpace` or `MatrixSpace`, then every subspace and quotient space of $V$ is given in terms of a basis consisting of elements of $V$, i.e. by means of an embedded basis.

**•**
If $V$ has been created using the function `RModule`, then every subspace and quotient space of $V$ is given in terms of a reduced basis.

<a id="constructor-constructor-sub-modtupfld-list-modtupfld"></a>
##### `sub<V | L>: ModTupFld, List -> ModTupFld`

Given a $K$-vector space $V$, construct the subspace $U$ generated by the elements of $V$ specified by the list $L$. Each term $L_i$ of the list $L$ must be an expression defining an object of one of the following types:

**(a)**
A sequence of $n$ elements of $K$ defining an element of $V$;

**(b)**
A set or sequence whose terms are elements of $V$;

**(c)**
A subspace of $V$;

**(d)**
A set or sequence whose terms are subspaces of $V$.

The generators stored for $U$ consist of the vectors specified by terms $L_i$ together with the stored generators for subspaces specified by terms of $L_i$. Repetitions of a vector and occurrences of the zero vector are removed (unless $U$ is the trivial subspace).

The constructor returns the subspace $U$ and the inclusion homomorphism $f : U \rightarrow V$. If $V$ is of embedded type, the basis constructed for $U$ consists of elements of $V$. If $V$ is of standard type, a standard basis is constructed for $U$.

<a id="function-morphism-modtupfld-modtupfld"></a>
##### `Morphism(U, V): ModTupFld, ModTupFld -> RModMatElt`

Assuming the vector space $U$ has been created as a subspace of $V$, the function returns the matrix defining the embedding of $U$ into $V$.

<a id="example-ex-466045"></a>
##### `Example: Golay Code in a Vector Space (ex-466045)`

The ternary Golay code is a six-dimensional subspace of the vector space $K^{(11)}$, where $K$ is ${\bf F}_{3}$. This subspace is first constructed in the space constructed by the `VectorSpace` function.

```magma
> K11 := VectorSpace(FiniteField(3), 11);
> G3 := sub< K11  |
>     [1,0,0,0,0,0,1,1,1,1,1], [0,1,0,0,0,0,0,1,2,2,1],
>     [0,0,1,0,0,0,1,0,1,2,2], [0,0,0,1,0,0,2,1,0,1,2],
>     [0,0,0,0,1,0,2,2,1,0,1], [0,0,0,0,0,1,1,2,2,1,0] >;
> G3;
Vector space of degree 11, dimension 6 over GF(3)
Generators:
(1 0 0 0 0 0 1 1 1 1 1)
(0 1 0 0 0 0 0 1 2 2 1)
(0 0 1 0 0 0 1 0 1 2 2)
(0 0 0 1 0 0 2 1 0 1 2)
(0 0 0 0 1 0 2 2 1 0 1)
(0 0 0 0 0 1 1 2 2 1 0)
Echelonized basis:
(1 0 0 0 0 0 1 1 1 1 1)
(0 1 0 0 0 0 0 1 2 2 1)
(0 0 1 0 0 0 1 0 1 2 2)
(0 0 0 1 0 0 2 1 0 1 2)
(0 0 0 0 1 0 2 2 1 0 1)
(0 0 0 0 0 1 1 2 2 1 0)
```

<a id="example-ex-1f57d1"></a>
##### `Example: Golay Code in an R-Module (ex-1f57d1)`

We now construct the ternary Golay code starting with the vector space constructed using the `RModule` function. In this case the subspace is presented on a reduced basis.

```magma
> K11 := RModule(FiniteField(3), 11);
> G3 := sub< K11 |
>     [1,0,0,0,0,0,1,1,1,1,1], [0,1,0,0,0,0,0,1,2,2,1],
>     [0,0,1,0,0,0,1,0,1,2,2], [0,0,0,1,0,0,2,1,0,1,2],
>     [0,0,0,0,1,0,2,2,1,0,1], [0,0,0,0,0,1,1,2,2,1,0] >;
> G3;
KModule G3 of dimension 6 with base ring GF(3)
> Basis(G3);

[
    G3: (1 0 0 0 0 0),
    G3: (0 1 0 0 0 0),
    G3: (0 0 1 0 0 0),
    G3: (0 0 0 1 0 0),
    G3: (0 0 0 0 1 0),
    G3: (0 0 0 0 0 1)
]
> f := Morphism(G3, K11);
> f;
[1 0 0 0 0 0 1 1 1 1 1]
[0 1 0 0 0 0 0 1 2 2 1]
[0 0 1 0 0 0 1 0 1 2 2]
[0 0 0 1 0 0 2 1 0 1 2]
[0 0 0 0 1 0 2 2 1 0 1]
[0 0 0 0 0 1 1 2 2 1 0]
```

#### Construction of Quotient Vector Spaces

<a id="constructor-constructor-quo-modtupfld-list-modtupfld-map"></a>
##### `quo<V | L>: ModTupFld, List -> ModTupFld, Map`

Given a $K$-vector space $V$, construct the quotient vector space $W = V/U$, where $U$ is the subspace generated by the elements of $V$ specified by the list $L$. Each term $L_i$ of the list $L$ must be an expression defining an object of one of the following types:

**(a)**
A sequence of $n$ elements of $K$ defining an element of $V$;

**(b)**
A set or sequence whose terms are elements of $V$;

**(c)**
A subspace of $V$;

**(d)**
A set or sequence whose terms are subspaces of $V$.

The generators constructed for $U$ consist of the elements specified by terms $L_i$ together with the stored generators for subspaces specified by terms of $L_i$.

The constructor returns the quotient space $W$ and the natural homomorphism $f : V \rightarrow W$.

<a id="operation-op-div-modtupfld-modtupfld"></a>
##### `V / U: ModTupFld, ModTupFld -> ModTupFld, Map`

Given a subspace $U$ of the vector space $V$, construct the quotient space $W$ of $V$ by $U$. If $r$ is defined to be $\dim(V) - \dim(U)$, then $W$ is created as an $r$-dimensional vector space relative to the standard basis.

The constructor returns the quotient space $W$ and the natural homomorphism $f : V \rightarrow W$.

<a id="example-ex-4d668d"></a>
##### `Example: Quotient by the Golay Code (ex-4d668d)`

We construct the quotient of $K^{(11)}$ by the Golay code.

```magma
> K11 := VectorSpace(FiniteField(3), 11);
> Q3, f := quo< K11 |
>  [1,0,0,0,0,0,1,1,1,1,1], [0,1,0,0,0,0,0,1,2,2,1],
>  [0,0,1,0,0,0,1,0,1,2,2], [0,0,0,1,0,0,2,1,0,1,2],
>  [0,0,0,0,1,0,2,2,1,0,1], [0,0,0,0,0,1,1,2,2,1,0] >;
> Q3;
Full Vector space of degree 5 over GF(3)
> f;
Mapping from: ModTupFld: K11 to ModTupFld: Q3
```

<a id="example-ex-e0a05b"></a>
##### `Example: Golay Quotient as a Complement (ex-e0a05b)`

If we wished to construct this quotient of $K^{(11)}$ as a subspace of the original space, we could do so using the `Complement` function.

```magma
> K11 := VectorSpace(FiniteField(3), 11);
> S := sub< K11 |
>     [1,0,0,0,0,0,1,1,1,1,1], [0,1,0,0,0,0,0,1,2,2,1],
>     [0,0,1,0,0,0,1,0,1,2,2], [0,0,0,1,0,0,2,1,0,1,2],
>     [0,0,0,0,1,0,2,2,1,0,1], [0,0,0,0,0,1,1,2,2,1,0] >;
> Complement(K11, S);
Vector space of degree 11, dimension 5 over GF(3)
Echelonized basis:
(0 0 0 0 0 0 1 0 0 0 0)
(0 0 0 0 0 0 0 1 0 0 0)
(0 0 0 0 0 0 0 0 1 0 0)
(0 0 0 0 0 0 0 0 0 1 0)
(0 0 0 0 0 0 0 0 0 0 1)
```

<a id="example-ex-aceeb2"></a>
##### `Example: Quotient of a Rational Matrix Space (ex-aceeb2)`

We construct a subspace and its quotient space in ${\mathbb{Q}}^{(3 \times 4)}$.

```magma
> Q := RationalField();
> Q3 := VectorSpace(Q, 3);
> Q4 := VectorSpace(Q, 4);
> H34 := Hom(Q3, Q4);
> a := H34 ! [ 2, 0, 1, -1/2,  1, 0, 3/2, 4,  4/5, 6/7, 0, -1/3];
> b := H34 ! [ 1/2, -3, 0, 5,  1/3, 2, 4/5, 0,  5, -1, 5, 7];
> c := H34 ! [ -1, 4/9, 1, -4,  5, -5/6, -3/2, 0,  4/3, 7, 0, 7/9];
> d := H34 ! [ -3, 5, 1/3, -1/2,  2/3, 4, -2, 0,  0, 4, -1, 0];
> a, b, c, d;
[   2    0    1 -1/2]
[   1    0  3/2    4]
[ 4/5  6/7    0 -1/3]

[1/2  -3   0   5]
[1/3   2 4/5   0]
[  5  -1   5   7]

[  -1  4/9    1   -4]
[   5 -5/6 -3/2    0]
[ 4/3    7    0  7/9]

[  -3    5  1/3 -1/2]
[ 2/3    4   -2    0]
[   0    4   -1    0]
> U := sub< H34 | a, b, c, d >;
> U:Maximal;
KMatrixSpace of 3 by 4 GHom matrices and dimension 4 over Rational Field
Echelonized basis:

[1    0    0    0]
[-33872/30351    -5164/10117    42559/50585    11560/10117]
[-10514/10117    -121582/70819    -8476/10117    -48292/30351]

[           0            1            0            0]
[ -7797/10117   4803/10117 12861/101170   5940/10117]
[ -7818/10117 -38214/70819  -7821/10117 -10967/10117]

[           0            0            1            0]
[ 31261/10117  28101/20234  -2157/20234  18552/10117]
[161802/50585 291399/70819  20088/10117  33419/10117]

[          0           0           0           1]
[-8624/30351  7445/10117  7696/50585  2408/10117]
[32388/50585 -3562/10117  6272/10117 27580/30351]
> W := H34/U;
> W;
Full Vector space of degree 8 over Rational Field
```

### Changing the Coefficient Field

The standard constructions described in [Standard Constructions](https://docs.magma-maths.org/Modules/FreeModules/operation.md#modules-standard-constructions) for $R$-modules may be applied to vector spaces. In addition, we may extend or restrict the field of scalars, using the functions described here.

<a id="function-extendfield-modtupfld-fld"></a>
#### `ExtendField(V, L): ModTupFld, Fld -> ModTupFld, MapHom`

Given a $K$-vector space $V$, with $K$ a field and $L$ an extension of $K$, construct the $L$-vector space $U = V \otimes_K L$. The function returns

**(a)**
the vector space $U$; and

**(b)**
the inclusion homomorphism $\phi\ : V \rightarrow U$.

<a id="function-restrictfield-modtupfld-fld"></a>
#### `RestrictField(V, L): ModTupFld, Fld -> ModTupFld, MapHom`

Given a $K$-vector space $V$, with $K$ a field and $L$ a subfield of $K$, construct the $L$-vector space $U$ consisting of those vectors of $V$ having all of their components lying in the subfield $L$. The function returns

**(a)**
the vector space $U$; and

**(b)**
the restriction homomorphism $\phi\ : V \rightarrow U$.

<a id="function-vectorspace-modtupfld-fld"></a>
#### `VectorSpace(V, F): ModTupFld, Fld -> ModTupFld, Map`

<a id="function-kspace-modtupfld-fld"></a>
#### `KSpace(V, F): ModTupFld, Fld -> ModTupFld, Map`

<a id="function-kmatrixspace-modtupfld-fld"></a>
#### `KMatrixSpace(V, F): ModTupFld, Fld -> ModTupFld, Map`

<a id="function-kmodule-modtupfld-fld"></a>
#### `KModule(V, F): ModTupFld, Fld -> ModTupFld, Map`

Given an $n$-dimensional $K$-vector space $V$, and a subfield $F$ of a finite field or cyclotomic field $K$ such that $K$ has degree $m$ over $F$, construct a vector space $U$ of dimension $mn$ over the field $F$. The function returns

**(a)**
the vector space $U$; and

**(b)**
a mapping $\phi\ : V \rightarrow U$ such that a vector $(v_1, \ldots, v_i, \ldots, v_n)$ of $V$ is mapped into the vector

$$
(u_{11},\ldots, u_{1n}, \ldots, u_{i1}, \ldots, u_{in}, \ldots, u_{n1}, \ldots u_{nn} ),
$$

where $(u_{i1}, \ldots, u_{in})$ is the field element $v_i$ written as a vector over the subfield $F$.

### Basic Operations

#### Accessing Vector Space Invariants

<a id="operation-operation-modtupfld-rngintelt-modtupfldelt"></a>
##### `V . i: ModTupFld, RngIntElt -> ModTupFldElt`

Given a vector space $V$ and a positive integer $i$, return the $i$-th generating element of $V$.

<a id="function-coefficientfield-modtupfld"></a>
##### `CoefficientField(V): ModTupFld -> Fld`

<a id="function-basefield-modtupfld"></a>
##### `BaseField(V): ModTupFld -> Fld`

Given a $K$-vector space $V$, return the field $K$.

<a id="function-degree-modtupfld"></a>
##### `Degree(V): ModTupFld -> RngIntElt`

Given a $K$-vector space $V$ which is a subspace of $K^{(n)}$, return $n$.

<a id="function-degree-modtupfldelt"></a>
##### `Degree(u): ModTupFldElt -> RngIntElt`

Given a vector $u$ belonging to a subspace of the vector space $K^{(n)}$, return $n$.

<a id="function-dimension-modtupfld"></a>
##### `Dimension(V): ModTupFld -> RngIntElt`

The dimension of the vector space $V$.

<a id="function-generators-modtupfld"></a>
##### `Generators(V): ModTupFld -> { ModElt}`

The generators for the vector space $V$, returned as a set.

<a id="function-numberofgenerators-modtupfld"></a>
##### `NumberOfGenerators(M): ModTupFld -> RngIntElt`

<a id="function-ngens-modtupfld"></a>
##### `Ngens(M): ModTupFld -> RngIntElt`

The number of generators for the vector space $V$.

<a id="function-overdimension-modtupfld"></a>
##### `OverDimension(V): ModTupFld -> RngIntElt`

Given a $K$-vector space $V$ which is a subspace of $K^{(n)}$, return $n$.

<a id="function-overdimension-modtupfldelt"></a>
##### `OverDimension(u): ModTupFldElt -> RngIntElt`

Given a vector $u$ belonging to a subspace of the vector space $K^{(n)}$, return $n$.

<a id="function-generic-modfld"></a>
##### `Generic(V): ModFld -> ModFld`

The generic vector space containing $V$, i.e. the full vector space in which $V$ is naturally embedded.

<a id="function-parent-modfld"></a>
##### `Parent(V): ModFld -> SetPow`

The power structure for the vector space $V$ (the set consisting of all finite dimensional vector spaces).

#### Membership and Equality

<a id="operation-op-in-modtupfldelt-modtupfld"></a>
##### `v in V: ModTupFldElt, ModTupFld -> BoolElt`

Returns `true` if the element $v$ lies in the vector space $V$, where $v$ and $V$ belong to a common space.

<a id="operation-op-notin-modtupfldelt-modtupfld"></a>
##### `v notin V: ModTupFldElt, ModTupFld -> BoolElt`

Returns `true` if the element $v$ does not lie in the vector space $V$, where $v$ and $V$ belong to a common space.

<a id="operation-op-subset-modtupfld-modtupfld"></a>
##### `U subset V: ModTupFld, ModTupFld -> BoolElt`

Returns `true` if the $K$-vector space $U$ is contained in the $K$-vector space $V$, where $U$ and $V$ are subspaces of some common vector space.

<a id="operation-operation-notsubset-modtupfld-modtupfld-boolelt"></a>
##### `U notsubset V: ModTupFld, ModTupFld -> BoolElt`

Returns `true` if the $K$-vector space $U$ is not contained in the $K$-vector space $V$, where $U$ and $V$ are subspaces of some common vector space.

<a id="operation-op-eq-modtupfld-modtupfld"></a>
##### `U eq V: ModTupFld, ModTupFld -> BoolElt`

Returns `true` if the subspaces $U$ and $V$ are equal, where $U$ and $V$ belong to a common vector space.

<a id="operation-op-ne-modtupfld-modtupfld"></a>
##### `U ne V: ModTupFld, ModTupFld -> BoolElt`

Returns `true` if the subspaces $U$ and $V$ are not equal, where $U$ and $V$ belong to a common vector space.

#### Operations on Subspaces

<a id="operation-op-plus-modtupfld-modtupfld"></a>
##### `U + V: ModTupFld, ModTupFld -> ModTupFld`

Sum of the subspaces $U$ and $V$, where $U$ and $V$ must be subspaces of a common vector space.

<a id="operation-op-meet-modtupfld-modtupfld"></a>
##### `U meet V: ModTupFld, ModTupFld -> ModTupFld`

Intersection of the subspaces $U$ and $V$, where $U$ and $V$ must be subspaces of a common vector space.

<a id="operation-operation-meet-modtupfld-modtupfld-modtupfld"></a>
##### `U meet:= V: ModTupFld, ModTupFld -> ModTupFld`

Replace $U$ with the intersection of the subspaces $U$ and $V$, where $U$ and $V$ must be subspaces of a common vector space.

<a id="operation-operation-meet-modtupfld-modtupfld"></a>
##### `&meet S: [ ModTupFld ] -> ModTupFld`

Intersection of the subspaces of the set or sequence $S$, which must be subspaces of a common vector space.

<a id="function-tensorproduct-modtupfld-modtupfld"></a>
##### `TensorProduct(U, V): ModTupFld, ModTupFld -> FldElt`

The tensor (Kronecker) product of the vector spaces $U$ and $V$, generated by all the tensor products of elements of $U$ by elements of $V$. The resulting vector space has degree equal to the product of the degrees of $U$ and $V$.

<a id="function-complement-modtupfld-modtupfld"></a>
##### `Complement(V, U): ModTupFld, ModTupFld -> ModTupFld`

Given a subspace $U$ of the vector space $V$, construct a complement for $U$ in $V$ (a subspace of $V$).

Note that this complement is always with respect to the standard inner product, and thus need not be orthogonal with respect to a given one.

<a id="function-transversal-modtupfld-modtupfld"></a>
##### `Transversal(V, U): ModTupFld, ModTupFld -> { ModTupFldELt}`

Given a subspace $U$ of the vector space $V$ over a finite field, return a transversal for $U$ in $V$ as a set of vectors.

### Reducing Vectors Relative to a Subspace

<a id="function-reducevector-modtuprng-modtuprngelt"></a>
#### `ReduceVector(W, v): ModTupRng, ModTupRngElt -> ModTupRngElt`

(Function.) Given a vector $v$ from a tuple module $V$ and a submodule $W$ of $V$, return the reduction of $v$ with respect to $W$ (that is, the canonical representative of the coset $v + W$).

Note that the reduction is done with respect to the standard inner product.

<a id="procedure-reducevector-modtuprng-modtuprngelt-2"></a>
#### `ReduceVector(W, ~v): ModTupRng, ModTupRngElt`

(Procedure.) Given a vector $v$ from a tuple module $V$ and a submodule $W$ of $V$, replace $v$ with its reduction of with respect to $W$ (that is, the canonical representative of the coset $v + W$).

Note that the reduction is done with respect to the standard inner product.

<a id="function-decomposevector-modtuprng-modtuprngelt"></a>
#### `DecomposeVector(U, v): ModTupRng, ModTupRngElt -> ModTupRngElt, ModTupRngElt`

Given a vector $v$ from a tuple module $V$ and a submodule $U$ of $V$, return the unique $u$ in $U$ and $w$ in the complement to $U$ in $U + <v>$ such that $v = u + w$.

Note that the reduction is done with respect to the standard inner product, and the complement noted above need not be orthogonal.

### Bases

This section is concerned with the construction of bases for vector spaces.

<a id="function-vectorspacewithbasis-modtupfldelt"></a>
#### `VectorSpaceWithBasis(Q): [ModTupFldElt] -> ModTupFld`

<a id="function-vectorspacewithbasis-algmatelt"></a>
#### `VectorSpaceWithBasis(a): AlgMatElt -> ModTupFld`

<a id="function-vectorspacewithbasis-modmatfldelt"></a>
#### `VectorSpaceWithBasis(a): ModMatFldElt -> ModTupFld`

<a id="function-kspacewithbasis-modtupfldelt"></a>
#### `KSpaceWithBasis(Q): [ModTupFldElt] -> ModTupFld`

<a id="function-kspacewithbasis-algmatelt"></a>
#### `KSpaceWithBasis(a): AlgMatElt -> ModTupFld`

<a id="function-kspacewithbasis-modmatfldelt"></a>
#### `KSpaceWithBasis(a): ModMatFldElt -> ModTupFld`

<a id="function-kmodulewithbasis-modtupfldelt"></a>
#### `KModuleWithBasis(Q): [ModTupFldElt] -> ModTupFld`

Create a vector space having as basis the terms of $B$ (rows of $a$).

<a id="function-basis-modtupfld"></a>
#### `Basis(V): ModTupFld -> [ModTupFldElt]`

The current basis for the vector space $V$, returned as a sequence of vectors.

<a id="function-basiselement-modtupfld-rngintelt"></a>
#### `BasisElement(V, i): ModTupFld, RngIntElt -> ModTupFldElt`

The $i$-th basis element for the vector space $V$.

<a id="function-basismatrix-modtupfld"></a>
#### `BasisMatrix(V): ModTupFld -> ModMatElt`

The current basis for the vector space $V$, returned as the rows of a matrix belonging to the matrix space $K^{(m \times n)}$, where $m$ is the dimension of $V$ and $n$ is the over-dimension of $V$.

<a id="function-coordinates-modtupfld-modtupfldelt"></a>
#### `Coordinates(V, v): ModTupFld, ModTupFldElt -> [FldElt]`

Given a vector $v$ belonging to the $r$-dimensional $K$-vector space $V$, with basis $v_1, \ldots, v_r$, return a sequence $[a_1, \ldots, a_r]$ of elements of $K$ giving the coordinates of $v$ relative to the $V$-basis: $v = a_1*v_1 + \cdots +a_r*v_r$.

<a id="function-dimension-modtupfld-2"></a>
#### `Dimension(V): ModTupFld -> RngIntElt`

The dimension of the vector space $V$.

<a id="function-extendbasis-modtupfldelt-modtupfld"></a>
#### `ExtendBasis(Q, U): [ModTupFldElt], ModTupFld -> [ModTupFldElt]`

Given a sequence $Q$ containing $r$ linearly independent vectors belonging to the vector space $U$, extend the vectors of $Q$ to a basis for $U$. The basis is returned in the form of a sequence $T$ such that $T[i] = Q[i], i = 1, \ldots r$.

<a id="function-extendbasis-modtupfld-modtupfld"></a>
#### `ExtendBasis(U, V): ModTupFld, ModTupFld -> [ModTupFldElt]`

Given an $r$-dimensional subspace $U$ of the vector space $V$, return a basis for $V$ in the form of a sequence $T$ of elements such that the first $r$ elements correspond to the given basis vectors for $U$.

<a id="function-isindependent-modtupfldelt"></a>
#### `IsIndependent(S): { ModTupFldElt} -> BoolElt`

Given a set $S$ of elements belonging to the vector space $V$, return `true` if the elements of $S$ are linearly independent.

<a id="function-isindependent-modtupfldelt-2"></a>
#### `IsIndependent(Q): [ ModTupFldElt ] -> BoolElt`

Given a sequence $Q$ of elements belonging to the vector space $V$, return `true` if the terms of $Q$ are linearly independent.

<a id="example-ex-a4fb0c"></a>
#### `Example: Bases of the Ternary Golay Code (ex-a4fb0c)`

These operations will be illustrated in the context of the subspace $G3$ of the $11$-dimensional vector space over ${\bf F}_{3}$ defining the ternary Golay code.

```magma
> V11 := VectorSpace(FiniteField(3), 11);
> G3  := sub< V11 |  [1,0,0,0,0,0,1,1,1,1,1], [0,1,0,0,0,0,0,1,2,2,1],
>                    [0,0,1,0,0,0,1,0,1,2,2], [0,0,0,1,0,0,2,1,0,1,2],
>                    [0,0,0,0,1,0,2,2,1,0,1], [0,0,0,0,0,1,1,2,2,1,0] >;
> Dimension(G3);
    6
> Basis(G3);
[
    (1 0 0 0 0 0 1 1 1 1 1),
    (0 1 0 0 0 0 0 1 2 2 1),
    (0 0 1 0 0 0 1 0 1 2 2),
    (0 0 0 1 0 0 2 1 0 1 2),
    (0 0 0 0 1 0 2 2 1 0 1),
    (0 0 0 0 0 1 1 2 2 1 0)
]
> S := ExtendBasis(G3, V11);
> S;
[
    (1 0 0 0 0 0 1 1 1 1 1),
    (0 1 0 0 0 0 0 1 2 2 1),
    (0 0 1 0 0 0 1 0 1 2 2),
    (0 0 0 1 0 0 2 1 0 1 2),
    (0 0 0 0 1 0 2 2 1 0 1),
    (0 0 0 0 0 1 1 2 2 1 0),
    (0 0 0 0 0 0 1 0 0 0 0),
    (0 0 0 0 0 0 0 1 0 0 0),
    (0 0 0 0 0 0 0 0 1 0 0),
    (0 0 0 0 0 0 0 0 0 1 0),
    (0 0 0 0 0 0 0 0 0 0 1)
]
> C3:= Complement(V11, G3);
> C3;
Vector space of degree 11, dimension 5 over GF(3)
Echelonized basis:
(0 0 0 0 0 0 1 0 0 0 0)
(0 0 0 0 0 0 0 1 0 0 0)
(0 0 0 0 0 0 0 0 1 0 0)
(0 0 0 0 0 0 0 0 0 1 0)
(0 0 0 0 0 0 0 0 0 0 1)
> G3 + C3;
Full Vector space of degree 11 over GF(3)
> G3 meet C3;
Vector space of degree 11, dimension 0 over GF(3)
> x := Random(G3);
> x;
(1 1 2 0 0 1 1 1 1 2 0)
> c := Coordinates(G3, x);
> c;
[ 1, 1, 2, 0, 0, 1 ]
> G3 ! &+[ c[i] * G3.i : i in [1 .. Dimension(G3)]];
(1 1 2 0 0 1 1 1 1 2 0)
```

### Operations with Linear Transformations

Throughout this section, $V$ is a subspace of $K^{(m)}$, $W$ is a subspace of $K^{(n)}$ and $a$ is a linear transformation belonging to ${\operatorname{Hom}}_{K}(V, W)$. See also the chapter on general matrices for many other functions applicable to such matrices (e.g., `EchelonForm)`.

<a id="operation-op-times-modtupfldelt-modmatfldelt"></a>
#### `v * a: ModTupFldElt, ModMatFldElt -> ModTupFldElt`

<a id="literal-a-modmatfldelt-modtupfldelt"></a>
#### `a(v): ModMatFldElt, ModTupFldElt -> ModTupFldElt`

Given an element $v$ belonging to the vector space $V$, and an element $a$ belonging to ${\operatorname{Hom}}_{K}(V, W)$, return the image of $v$ under the linear transformation $a$ as an element of the vector space $W$.

<a id="operation-op-times-modmatrngelt-modmatrngelt"></a>
#### `a * b: ModMatRngElt, ModMatRngElt -> ModMatRngElt`

Given a matrix $a$ belonging to $K^{(m \times n)}$ and a matrix $b$ belonging to $K^{(n \times p)}$, for some integers $m$, $n$, $p$, form the product of $a$ and $b$ as an element of $K^{(m \times p)}$.

<a id="function-domain-modmatrngelt"></a>
#### `Domain(a): ModMatRngElt -> ModTupRng`

The domain of the linear transformation $a$ belonging to ${\operatorname{Hom}}_{K}(V, W)$, returned as a subspace of $V$.

<a id="function-codomain-modmatrngelt"></a>
#### `Codomain(a): ModMatRngElt -> ModTupRng`

The codomain of the linear transformation $a$ belonging to ${\operatorname{Hom}}_{K}(V, W)$, returned as a subspace of $W$.

<a id="function-image-modmatrngelt"></a>
#### `Image(a): ModMatRngElt -> ModTupRng, Map, Map`

The image of the linear transformation $a$ belonging to ${\operatorname{Hom}}_{K}(V, W)$, returned as a subspace of $W$.

<a id="function-rank-modmatrngelt"></a>
#### `Rank(a): ModMatRngElt -> RngIntElt`

The dimension of the image of the linear transformation $a$, i.e., the rank of the matrix $a$.

<a id="function-kernel-modmatrngelt"></a>
#### `Kernel(a): ModMatRngElt -> ModTupFld, Map`

<a id="function-nullspace-modmatrngelt"></a>
#### `NullSpace(a): ModMatRngElt -> ModTupFld, Map`

The kernel of the linear transformation $a$ belonging to ${\operatorname{Hom}}_{K}(V, W)$, returned as a subspace of $V$.

<a id="function-cokernel-modmatrngelt"></a>
#### `Cokernel(a): ModMatRngElt -> ModTupFld, Map`

The cokernel of the linear transformation $a$ belonging to ${\operatorname{Hom}}_{K}(V, W)$.

<a id="example-ex-135cf0"></a>
#### `Example: Operations on Linear Transformations (ex-135cf0)`

We illustrate the map operations for matrix spaces in the following example:

```magma
> Q := RationalField();
> Q2 := VectorSpace(Q, 2);
> Q3 := VectorSpace(Q, 3);
> Q4 := VectorSpace(Q, 4);
> H23 := Hom(Q2, Q3);
> H34 := Hom(Q3, Q4);
> x := Q2 ! [ -1, 2 ];
> a := H23 ! [ 1/2, 3, 0,  2/3, 4/5, -1 ];
> a;
[1/2   3   0]
[2/3 4/5  -1]
> Domain(a);
Full Vector space of degree 2 over Rational Field
> Codomain(a);
Full Vector space of degree 3 over Rational Field
> x*a;
( 5/6 -7/5   -2)
> b := H34 ! [ 2, 0, 1, -1/2,  1, 0, 3/2, 4,  4/5, 6/7, 0, -9/7];
> b;
[   2    0    1 -1/2]
[   1    0  3/2    4]
[ 4/5  6/7    0 -9/7]
> c := a*b;
> c;
[      4       0       5    47/4]
[    4/3    -6/7   28/15 436/105]
> x*c;
(     -4/3     -12/7    -19/15 -1447/420)
> Image(c);
Vector space of degree 4, dimension 2 over Rational Field
Echelonized basis:
(     1      0    5/4  47/16)
(     0      1  -7/30 -11/40)
> Kernel(c);
Vector space of degree 2, dimension 0 over Rational Field
> Rank(c);
2
> EchelonForm(c);
[     1      0    5/4  47/16]
[     0      1  -7/30 -11/40]
```

<a id="field-forms"></a>
<a id="chappolarspace"></a>
## Polar Spaces

- [Introduction](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/Introduction.md)
- [Reflexive Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/reflexive-forms.md)
  - [Quadratic Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/reflexive-forms.md#quadratic-forms)
- [Inner Products](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md)
  - [Example: Vector Space with a General Form](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#example-ex-2f3d6e)
  - [`EnsureUpperTriangular(A): AlgMatElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-ensureuppertriangular-algmatelt)
  - [`DotProduct(u, v): ModTupFldElt, ModTupFldElt → FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-dotproduct-modtupfldelt-modtupfldelt)
  - [`DotProductMatrix(S): SeqEnum[ModTupFldElt] → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-dotproductmatrix-seqenum-modtupfldelt)
  - [`GramMatrix(V): ModTupRng → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-grammatrix-modtuprng)
  - [`InnerProductMatrix(V): ModTupRng → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-innerproductmatrix-modtuprng)
  - [Example: Gram Matrix Versus Inner Product Matrix](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#example-ex-9d71da)
  - [Example: Symmetric and Hermitian Products](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#example-ex-af15e4)
  - [Orthogonality](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#orthogonality)
    - [`OrthogonalComplement(V, X : parameters): ModTupFld, ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-orthogonalcomplement-modtupfld-modtupfld)
    - [`Radical(V : parameters): ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-radical-modtupfld)
    - [`IsNondegenerate(V): ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-isnondegenerate-modtupfld)
    - [`IsDegenerate(V): ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-isdegenerate-modtupfld)
    - [`SingularRadical(V): ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-singularradical-modtupfld)
    - [`IsNonsingular(V): ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/innerprod.md#function-isnonsingular-modtupfld)
- [Isotropic and Singular Vectors and Subspaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md)
  - [`HasIsotropicVector(V): ModTupFld → BoolElt, ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-hasisotropicvector-modtupfld)
  - [`HasSingularVector(V): ModTupFld → BoolElt, ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-hassingularvector-modtupfld)
  - [`IsTotallyIsotropic(V): ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-istotallyisotropic-modtupfld)
  - [`IsTotallySingular(V): ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-istotallysingular-modtupfld)
  - [`MaximalTotallyIsotropicSubspace(V): ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-maximaltotallyisotropicsubspace-modtupfld)
  - [`MaximalTotallySingularSubspace(V): ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-maximaltotallysingularsubspace-modtupfld)
  - [`WittIndex(V): ModTupFld → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-wittindex-modtupfld)
  - [`HyperbolicPair(V, u): ModTupFld, ModTupFldElt → ModTupFldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-hyperbolicpair-modtupfld-modtupfldelt)
  - [Example: Isotropic Vectors in a Pseudo-Symplectic Space](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#example-ex-ced2e7)
  - [Example: Hyperbolic Splitting in Characteristic 2](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#example-ex-b0692a)
  - [`HyperbolicSplitting(V): ModTupFld → Tup`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-hyperbolicsplitting-modtupfld)
  - [Example: Hyperbolic Splitting of a Symmetric Form](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#example-ex-7e8c7f)
  - [Example: Splitting Off the Radical](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#example-ex-621e11)
  - [`SymplecticBasis(V,U,W): ModTupFld, ModTupFld, ModTupFld → [ModTupFldElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-symplecticbasis-modtupfld-modtupfld-modtupfld)
  - [`WittDecomposition(V): ModTupFld → SeqEnum[ModTupFld]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-wittdecomposition-modtupfld)
  - [`WittDecomposition(M, a): AlgMatElt[FldFin], FldAut → AlgMatElt[FldFin], AlgMatElt[FldFin]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-wittdecomposition-algmatelt-fldfin-fldaut)
  - [`MetabolicSpace(V): ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#function-metabolicspace-modtupfld)
- [The Standard Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md)
  - [`StandardAlternatingForm(n,R): RngIntElt, Rng → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardalternatingform-rngintelt-rng)
  - [`StandardAlternatingForm(n,q): RngIntElt, RngIntElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardalternatingform-rngintelt-rngintelt)
  - [Example: Standard Alternating Form](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#example-ex-3c60cd)
  - [`StandardPseudoAlternatingForm(n,K): RngIntElt, Fld → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardpseudoalternatingform-rngintelt-fld)
  - [`StandardPseudoAlternatingForm(n,q): RngIntElt, RngIntElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardpseudoalternatingform-rngintelt-rngintelt)
  - [`StandardHermitianForm(n,K): RngIntElt, Fld → AlgMatElt, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardhermitianform-rngintelt-fld)
  - [`StandardHermitianForm(n,q): RngIntElt, RngIntElt → AlgMatElt, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardhermitianform-rngintelt-rngintelt)
  - [`StandardQuadraticForm(n, K : parameters): RngIntElt, Fld → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardquadraticform-rngintelt-fld)
  - [`StandardQuadraticForm(n, q : parameters): RngIntElt, RngIntElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardquadraticform-rngintelt-rngintelt)
  - [Example: Standard Quadratic Form of Minus Type](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#example-ex-78f890)
  - [Example: Revised Minus-Type Quadratic Form](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#example-ex-29b8f5)
  - [`StandardSymmetricForm(n, K): RngIntElt, Fld → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardsymmetricform-rngintelt-fld)
  - [`StandardSymmetricForm(n, q : parameters): RngIntElt, RngIntElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/standard.md#function-standardsymmetricform-rngintelt-rngintelt)
- [Constructing Polar Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md)
  - [`PolarSpace(F, a): AlgMatElt[FldFin], FldAut → ModTupFld[FldFin]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-polarspace-algmatelt-fldfin-fldaut)
  - [`TrivialPolarSpace(F, n): FldFin, RngIntElt → ModTupFld[FldFin]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-trivialpolarspace-fldfin-rngintelt)
  - [`IsPolarSpace(V): ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-ispolarspace-modtupfld)
  - [`PolarSpaceType(V): ModTupFld → MonStgElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-polarspacetype-modtupfld)
  - [Example: Testing for a Polar Space](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#example-ex-1d3f36)
  - [Isotropic Subspaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#isotropic-subspaces)
    - [`FirstIsotropicSubspace(V, k): ModTupFld[FldFin], RngIntElt → ModTupFld[FldFin]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-firstisotropicsubspace-modtupfld-fldfin-rngintelt)
    - [`NextIsotropicSubspace(V, k): ModTupFld[FldFin], RngIntElt → ModTupFld[FldFin]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-nextisotropicsubspace-modtupfld-fldfin-rngintelt)
    - [`AllIsotropicSubspaces(V, k): ModTupFld[FldFin], RngIntElt → [ ModTupFld[FldFin] ]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-allisotropicsubspaces-modtupfld-fldfin-rngintelt)
    - [`NumberOfIsotropicSubspaces(V, k): ModTupFld[FldFin], RngIntElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-numberofisotropicsubspaces-modtupfld-fldfin-rngintelt)
  - [Symplectic Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#symplectic-spaces)
    - [`SymplecticSpace(J): AlgMatElt → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-symplecticspace-algmatelt)
    - [`IsSymplecticSpace(W): ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-issymplecticspace-modtupfld)
    - [`IsPseudoSymplecticSpace(W): ModTupFld → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-ispseudosymplecticspace-modtupfld)
    - [`DirectSum(V,W): ModTupRng, ModTupRng → ModTupRng, Map, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-directsum-modtuprng-modtuprng)
  - [Unitary Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#unitary-spaces)
    - [`UnitarySpace(J, sigma): AlgMatElt, Map → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-unitaryspace-algmatelt-map)
    - [`IsUnitarySpace(W): ModTupFld → BoolElt, RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-isunitaryspace-modtupfld)
    - [Example: Isotropic Vector in a Unitary Space](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#example-ex-b9c1f1)
    - [`ConjugateTranspose(M, sigma): Mtrx, Map → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-conjugatetranspose-mtrx-map)
  - [Quadratic Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#quadratic-spaces)
    - [`QuadraticSpace(Q): AlgMatElt → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-quadraticspace-algmatelt)
    - [`QuadraticSpace(f): RngMPolElt → ModTupRng`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-quadraticspace-rngmpolelt)
    - [`SymmetricToQuadraticForm(J): AlgMatElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-symmetrictoquadraticform-algmatelt)
    - [`QuadraticFormMatrix(V): ModTupRng → ModAlgElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-quadraticformmatrix-modtuprng)
    - [`QuadraticNorm(v): ModTupFldElt → FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-quadraticnorm-modtupfldelt)
    - [`QuadraticFormPolynomial(V): ModTupRng → RngPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-quadraticformpolynomial-modtuprng)
    - [`QuadraticFormPolynomial(Q): AlgMatElt → RngPolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-quadraticformpolynomial-algmatelt)
    - [Example: Quadratic Space from a Polynomial](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#example-ex-474785)
    - [`OrthogonalSum(V, W): ModTupFld, ModTupFld → ModTupFld, Map, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-orthogonalsum-modtupfld-modtupfld)
    - [`OrthogonalTensorProduct(V, W): ModTupFld, ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-orthogonaltensorproduct-modtupfld-modtupfld)
    - [`TotallySingularComplement(V, U, W): ModTupFld, ModTupFld, ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-totallysingularcomplement-modtupfld-modtupfld-modtupfld)
    - [`Discriminant(V): ModTupFld → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-discriminant-modtupfld)
    - [`ArfInvariant(V): ModTupFld → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-arfinvariant-modtupfld)
    - [`DicksonInvariant(V, f): ModTupFld, Mtrx → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-dicksoninvariant-modtupfld-mtrx)
    - [`SpinorNorm(V, f): ModTupFld, Mtrx → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-spinornorm-modtupfld-mtrx)
    - [`SpinorNorm(Q, g): AlgMatElt[Fld], AlgMatElt[Fld] → FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-spinornorm-algmatelt-fld-algmatelt-fld)
    - [Example: Spinor Norm over a General Field](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#example-ex-ff51ba)
    - [`CharacterQQModSquares(d, r): RngIntElt, FldRatElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-characterqqmodsquares-rngintelt-fldratelt)
    - [`SpinorNormRho(d, g, Q): RngIntElt, GrpMatElt, AlgMatElt → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-spinornormrho-rngintelt-grpmatelt-algmatelt)
    - [`HyperbolicBasis(U, B, W): ModTupFld, SeqEnum, ModTupFld → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-hyperbolicbasis-modtupfld-seqenum-modtupfld)
    - [`OrthogonalReflection(a): ModTupFldElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-orthogonalreflection-modtupfldelt)
    - [`RootSequence(V, f): ModTupFld, Mtrx → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-rootsequence-modtupfld-mtrx)
    - [`ReflectionFactors(V, f): ModTupFld, Mtrx → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-reflectionfactors-modtupfld-mtrx)
    - [`SiegelTransformation(u, v): ModTupFldElt, ModTupFldElt → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#function-siegeltransformation-modtupfldelt-modtupfldelt)
    - [Example: Isometries from Siegel Transformations](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#example-ex-717e94)
- [Isometries and Similarities](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md)
  - [Isometries](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#isometries)
    - [`IsIsometry(U, V, f): ModTupFld, ModTupFld, Map → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-isisometry-modtupfld-modtupfld-map)
    - [`IsIsometry(f): Map → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-isisometry-map)
    - [`IsIsometry(V, g): ModTupFld, Mtrx → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-isisometry-modtupfld-mtrx)
    - [`IsIsometric(V, W): ModTupFld, ModTupFld → BoolElt, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-isisometric-modtupfld-modtupfld)
    - [Example: Isometric Polar Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#example-ex-9909e6)
    - [Example: Isometry Between Symplectic Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#example-ex-5a3a59)
    - [Example: Transforming Forms with TransformForm](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#example-ex-6727c3)
    - [`CommonComplement(V, U, W): ModTupFld, ModTupFld, ModTupFld → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-commoncomplement-modtupfld-modtupfld-modtupfld)
    - [`ExtendIsometry(V, U, f): ModTupFld, ModTupFld, Map → Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-extendisometry-modtupfld-modtupfld-map)
    - [`IsometryGroup(V): ModTupFld → GrpMat`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-isometrygroup-modtupfld)
    - [Example: Isometry Group of a Degenerate Quadratic Space](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#example-ex-833a77)
    - [Example: Conjugating Isometry Groups](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#example-ex-86d774)
  - [Similarities](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#similarities)
    - [`IsSimilarity(U, V, f): ModTupFld, ModTupFld, Map → BoolElt, FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-issimilarity-modtupfld-modtupfld-map)
    - [`IsSimilarity(f): Map → BoolElt, FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-issimilarity-map)
    - [`IsSimilarity(V, g): ModTupFld, Mtrx → BoolElt, FldElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-issimilarity-modtupfld-mtrx)
    - [`IsSimilar(V, W): ModTupFld, ModTupFld → BoolElt, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-issimilar-modtupfld-modtupfld)
    - [Example: Similar Hermitian and Skew-Hermitian Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#example-ex-86e68e)
    - [`SimilarityGroup(V): ModTupFld → GrpMat`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-similaritygroup-modtupfld)
  - [Gram-Schmidt Normalisation](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#gram-schmidt-normalisation)
    - [`GramSchmidtPair(J): AlgMatElt → AlgMatElt, AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#function-gramschmidtpair-algmatelt)
    - [Example: Gram-Schmidt for a Hermitian Form](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#example-ex-97668f)
    - [Example: Gram-Schmidt for an Alternating Form](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#example-ex-7c8257)
- [Classical Groups](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/classical.md)
  - [Example: Groups Fixing an Alternating Form](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/classical.md#example-ex-1225d3)
  - [Example: Special Unitary Group of a Hermitian Form](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/classical.md#example-ex-e06cca)
- [Lie Algebras and Bilinear Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/liealg.md)
  - [`DerivationAlgebra(J): AlgMatElt → AlgLie`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/liealg.md#function-derivationalgebra-algmatelt)
  - [Example: Lie Algebra of Type C3](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/liealg.md#example-ex-3caa04)
  - [Example: G2 Ideal in Characteristic 2](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/liealg.md#example-ex-196405)
  - [`HeisenbergAlgebra(J): AlgMatElt → AlgLie`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/liealg.md#function-heisenbergalgebra-algmatelt)
  - [Example: Heisenberg Algebra of a Form](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/liealg.md#example-ex-aa6842)
- [Wall Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/wallform.md)
  - [`WallForm(V, f): ModTupFld, Mtrx → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/wallform.md#function-wallform-modtupfld-mtrx)
  - [`WallIsometry(V, I, mu): ModTupFld, ModTupFld, Map → Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/wallform.md#function-wallisometry-modtupfld-modtupfld-map)
  - [`WallDecomposition(V, f): ModTupFld, Mtrx → Mtrx, Mtrx`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/wallform.md#function-walldecomposition-modtupfld-mtrx)
  - [`SemiOrthogonalBasis(V): ModTupFld → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/wallform.md#function-semiorthogonalbasis-modtupfld)
  - [`GeneralisedWallForm(V, f): ModTupFld, Mtrx → ModTupFld, Map`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/wallform.md#function-generalisedwallform-modtupfld-mtrx)
- [Invariant Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md)
  - [`InvariantBilinearForms(G): GrpMat → SeqEnum[AlgMatElt], SeqEnum[AlgMatElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-invariantbilinearforms-grpmat)
  - [Example: Invariant Form of a Reducible Group](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#example-ex-246b09)
  - [Example: Forms of a Non-Absolutely Irreducible Group](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#example-ex-8559f1)
  - [`InvariantQuadraticForms(G): GrpMat → SeqEnum[AlgMatElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-invariantquadraticforms-grpmat)
  - [Example: Invariant Quadratic Forms of a Cyclic Group](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#example-ex-e24e49)
  - [`SemilinearDual(M, mu): ModGrp, Map → ModGrp`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-semilineardual-modgrp-map)
  - [`InvariantSesquilinearForms(G): GrpMat → SeqEnum[AlgMatElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-invariantsesquilinearforms-grpmat)
  - [Example: Invariant Hermitian Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#example-ex-17b876)
  - [Example: Preserving Bilinear and Sesquilinear Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#example-ex-9dd62c)
  - [`InvariantFormBases(G): GrpMat → SeqEnum[AlgMatElt], SeqEnum[AlgMatElt], SeqEnum[AlgMatElt], SeqEnum[AlgMatElt]`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-invariantformbases-grpmat)
  - [Semi-invariant Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#semi-invariant-forms)
    - [`TwistedDual(M, lambda): ModGrp, Map → ModGrp`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-twisteddual-modgrp-map)
    - [`SemiInvariantBilinearForms(G): GrpMat → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-semiinvariantbilinearforms-grpmat)
    - [`SemiInvariantQuadraticForms(G): GrpMat → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-semiinvariantquadraticforms-grpmat)
    - [`TwistedSemilinearDual(M, lambda, mu): ModGrp, Map, Map → ModGrp`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-twistedsemilineardual-modgrp-map-map)
    - [`SemiInvariantSesquilinearForms(G): GrpMat → SeqEnum`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#function-semiinvariantsesquilinearforms-grpmat)
    - [Example: Semi-Invariant Forms of a Normal Subgroup](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/invform.md#example-ex-f6ba6b)
- [Polar Spaces More Generally](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md)
  - [Creation of PolarSpaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#creation-of-polarspaces)
    - [`AmbientPolarSpace(J): AlgMatElt → SpcPlr`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-ambientpolarspace-algmatelt)
    - [`AmbientPolarSpace(J, a): AlgMatElt, FldAut → SpcPlr`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-ambientpolarspace-algmatelt-fldaut)
    - [`PolarSpace(L): LatNF → SpcPlr`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-polarspace-latnf)
    - [`PolarSpace(L): Lat → SpcPlr`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-polarspace-lat)
    - [`AmbientSpace(L): LatNF → SpcPlr`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-ambientspace-latnf)
    - [`ChangeRing(V, R): SpcPlr, Rng → SpcPlr`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-changering-spcplr-rng)
  - [Properties of Polar Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#properties-of-polar-spaces)
    - [`BaseField(V): SpcPlr → Fld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-basefield-spcplr)
    - [`BaseRing(V): SpcPlr → Fld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-basering-spcplr)
    - [`CoefficientField(V): SpcPlr → Fld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-coefficientfield-spcplr)
    - [`CoefficientRing(V): SpcPlr → Fld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-coefficientring-spcplr)
    - [`VectorSpace(V): SpcPlr → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-vectorspace-spcplr)
    - [`KSpace(V): SpcPlr → ModTupFld`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-kspace-spcplr)
    - [`Dimension(V): SpcPlr → RngIntElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-dimension-spcplr)
    - [`InnerForm(V): SpcPlr → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-innerform-spcplr)
    - [`Involution(V): SpcPlr → FldAut`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-involution-spcplr)
    - [`SpaceType(V): SpcPlr → MonStgElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-spacetype-spcplr)
    - [`Diagonal(V): SpcPlr → AlgMatElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-diagonal-spcplr)
  - [Predicates on Polar Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#predicates-on-polar-spaces)
    - [`IsDefinite(V): SpcPlr → BoolElt`](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/SpcPlr.md#function-isdefinite-spcplr)
- [Bibliography](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/bibliography.md)

<a id="sectfldformsintro"></a>
<a id="id1"></a>
### Introduction

This chapter describes Magma functions for working with quadratic, bilinear, and sesquilinear forms defined on vector spaces. The emphasis is on vector spaces defined over finite fields but in some instances the functions apply more widely. For quadratic forms defined on lattices see Chapter [Quadratic Forms](https://docs.magma-maths.org/LatticesQuadraticForms/QuadraticForms/index-quadratic-forms.md#chapquadform). For the interpretation of reflexive forms as algebras with involution see Chapter [Algebras with Involution](https://docs.magma-maths.org/Algebras/AlgebrasWithInvolution/index-algebras-with-involution.md#chapstaralgebras). General references for this material are [[Bou07](https://docs.magma-maths.org/references.md#cite-bourbaki-forms), [Tay92](https://docs.magma-maths.org/references.md#cite-taylor-1992)].

<a id="sectfldformsref"></a>
<a id="id1"></a>
### Reflexive Forms

Let $V$ be a vector space of dimension $n$ over a field $K$. If $\sigma$ is an automorphism of $K$, a $\sigma$-sesquilinear form on the vector space $V$ over $K$ is a map $\beta : V\times V\to K$ such that

$$
\begin{aligned}\beta(u_1+u_2,v) &= \beta(u_1,v)+\beta(u_2,v),\\
  \beta(u,v_1+v_2) &= \beta(u,v_1)+\beta(u,v_2)\\ \text{and} &\\
  \beta(au,bv) &= a\sigma(b)\beta(u,v).\end{aligned}
$$

for all $u,u_1,u_2,v,v_1,v_2\in V$ and all $a,b\in K$. If $\sigma$ is the identity, the form is said to be *bilinear*.

A linear transformation $g$ of $V$ is an *isometry* if $g$ preserves $\beta$; it is a *similarity* if it preserves $\beta$ up to a non-zero scalar multiple.

A $\sigma$-sesquilinear form $\beta$ is *reflexive* if for all $u,v\in V$, $\beta(u,v) = 0$ implies $\beta(v,u) = 0$. Any non-zero multiple of a reflexive form is again reflexive with the same group of isometries. By a theorem of Brauer [[Bra36](https://docs.magma-maths.org/references.md#cite-brauer-1936)] (but sometimes referred to as the Birkhoff–von Neumann theorem), up to a non-zero scalar multiple, there are three types of *non-degenerate* reflexive forms:

**Alternating.** In this case $\sigma$ is the identity, $\beta(u,u) = 0$ for all $u\in V$ and consequently $\beta(u,v) = -\beta(v,u)$ for all $u,v \in V$. The group of isometries is a *symplectic* group.

**Symmetric.** In this case $\sigma$ is the identity and $\beta(u,v) = \beta(v,u)$ for all $u,v \in V$. If the characteristic of $K$ is not two, the group of isometries is an *orthogonal* group. If the characteristic is two, the form is either alternating or pseudo-alternating (see below).

**Hermitian.** In this case $\sigma$ is an automorphism of order two and $\beta(u,v) = \sigma\beta(v,u)$ for all $u,v \in V$. The group of isometries is a *unitary* group.

If $V$ is a vector space $V$ and if $\beta$ is a reflexive form defined on $V$, the partially ordered set of totally isotropic subspaces with respect to $\beta$ is often referred to as a . Similarly, there are polar spaces associated with quadratic forms (see Section [Quadratic Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/reflexive-forms.md#subsectquadratic)). But throughout this chapter by polar space we shall simply mean a vector space furnished with either a reflexive $\sigma$-sesquilinear form or a quadratic form. See [[Bue95](https://docs.magma-maths.org/references.md#cite-buekenhout95), Chap. 2] for an account of polar spaces in a more general context.

Let $K_0$ be the fixed field of $\sigma$. Multiplying an alternating, symmetric, or hermitian form by a non-zero element of $K_0$ leaves the type of the form unchanged.

However, multiplying an hermitian form by a non-zero element of $K$ produces a sesquilinear form $\xi$ and an element $\varepsilon\in K$ such that for all $u,v \in V$, $\xi(v,u) = \varepsilon\sigma\xi(u,v)$, where $\varepsilon\sigma(\varepsilon) = 1$. In this case $\xi$ is said to be $\varepsilon$-hermitian.

**Skew-hermitian.** A reflexive $\sigma$-sesquilinear form is skew-hermitian if the order of $\sigma$ is two and $\xi(v,u) = -\sigma\xi(v,u)$ for all $u,v\in V$. If $\beta$ is hermitian and if $d\in K$ is chosen so that $d\ne\sigma(d)$, then $e = d-\sigma(d)$ satisfies $\sigma(e) = -e$. Thus $\xi(u,v) = e\beta(u,v)$ is skew-hermitian. The group of isometries of $\xi$ coincides with the group of isometries of $\beta$ and it is therefore a *unitary* group.

In the case of fields of characteristic two there is no distinction between hermitian and skew-hermitian forms and moreover, every alternating form is symmetric.

**Pseudo-alternating.** A symmetric form (in characteristic two) which is not alternating is said to be *pseudo-alternating*.

The three types of forms—alternating, symmetric, and hermitian—correspond to the three types of classical groups of isometries: symplectic, orthogonal, and unitary. But this is not quite the whole story because it does not include orthogonal groups over fields of characteristic two. In order to include these groups it is necessary to consider quadratic forms in addition to symmetric bilinear forms.

<a id="quadratic"></a>
<a id="subsectquadratic"></a>
#### Quadratic Forms

If $\beta$ is a bilinear form, a *quadratic form* with *polar form* $\beta$ is a function $Q : V \to K$ such that

$$
\begin{aligned}Q(av) &= a^2Q(v)\\ \text{and} &\\
  \beta(u,v) &= Q(u+v) - Q(u) - Q(v)\end{aligned}
$$

for all $u,v\in V$ and all $a\in K$. We have $\beta(v,v) = 2Q(v)$ and therefore, if the characteristic of $K$ is not two, $\beta$ determines $Q$.

We extend the notion of polar space to include vector spaces $V$ with an associated quadratic form $Q$. The pair $(V,Q)$ is an orthogonal geometry and $V$ is a *quadratic* space.

<a id="innerprod"></a>
<a id="sectinnerprod"></a>
### Inner Products

Every vector space $V$ in Magma created via the `VectorSpace` intrinsic (or its synonym `KSpace`) has an associated bilinear form which is represented by a matrix and which can be accessed via `InnerProductMatrix(V)` or via the attribute `ip_form`. By default the inner product matrix is the identity. If the dimension of $V$ is $n$, then any $n\times n$ matrix defined over the base field of $V$ can serve as the inner product matrix by passing it to `VectorSpace` as an additional parameter.

If $e_1$, $e_2$, …, $e_n$ is a basis for $V$, the matrix of the form $\beta$ with respect to this basis is $J := \big(\beta(e_i,e_j)\big)$.

<a id="example-ex-2f3d6e"></a>
#### `Example: Vector Space with a General Form (ex-2f3d6e)`

```magma
> K := GF(11);
> J := Matrix(K,3,3,[1,2,3, 4,5,6, 7,8,9]);
> V := VectorSpace(K,3,J);
> InnerProductMatrix(V);
[ 1  2  3]
[ 4  5  6]
[ 7  8  9]
```

A vector space $V$ may also have an associated quadratic form. This can be assigned by attaching a matrix to $V$ via the function `QuadraticSpace` described in Section [Quadratic Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/constructions.md#subsectquadsp). If assigned, the matrix can be accessed as the return value of `QuadraticFormMatrix`.

The quadratic form defined by the matrix $A$ is $q(v) = vAv^\mathrm{tr}$, and the matrix of its polar form is $A + A^\mathrm{tr}$. It is always possible to represent a quadratic form by an upper triangular matrix. Furthermore, if the characteristic of the field is not two, the quadratic form may be represented by the symmetric matrix ${1\over 2}J$, where $J$ is the matrix of its polar form.

In order to accommodate hermitian forms, a vector space of type `ModTupFld` has an attribute `Involution`. This attribute is intended to hold an automorphism (of order two) of the base field.

<a id="function-ensureuppertriangular-algmatelt"></a>
#### `EnsureUpperTriangular(A): AlgMatElt -> AlgMatElt`

Given an $n\times n$ matrix $A$ this function returns the upper triangular matrix $Q$ which represents the same quadratic form as $A$. That is, for all $n$-tuples $v$ we have $vAv^\mathrm{tr}= vQv^\mathrm{tr}$.

<a id="function-dotproduct-modtupfldelt-modtupfldelt"></a>
#### `DotProduct(u, v): ModTupFldElt, ModTupFldElt -> FldElt`

If $V$ is the generic space of the parent of $u$ and $v$, let $\sigma$ be the field automorphism ``V`Involution`` if this attribute is assigned or the identity automorphism if ``V`Involution`` is not assigned. If $J$ is the inner product matrix of $V$, the expression `DotProduct(u,v)` evaluates to $uJ\sigma(v^\mathrm{tr})$. That is, it returns $\beta(u,v)$, where $\beta$ is a bilinear or sesquilinear form on $V$.

<a id="function-dotproductmatrix-seqenum-modtupfldelt"></a>
#### `DotProductMatrix(S): SeqEnum[ModTupFldElt] -> AlgMatElt`

The matrix of inner products of the vectors in the sequence $S$. The inner products are calculated using `DotProduct` and therefore take into account any field automorphism attached to the `Involution` attribute of the generic space of the universe of $S$.

<a id="function-grammatrix-modtuprng"></a>
#### `GramMatrix(V): ModTupRng -> AlgMatElt`

If $B$ is the basis matrix of $V$ and if $J$ is the inner product matrix, this function returns $BJB^{\hbox{tr}}$. In this case the `Involution` attribute is ignored.

<a id="function-innerproductmatrix-modtuprng"></a>
#### `InnerProductMatrix(V): ModTupRng -> AlgMatElt`

The inner product matrix attached to the generic space of $V$. This is the attribute ``V`ip_form``.

<a id="example-ex-9d71da"></a>
#### `Example: Gram Matrix Versus Inner Product Matrix (ex-9d71da)`

This example illustrates the difference between `GramMatrix` and `InnerProductMatrix`. The function `GramMatrix` uses the echelonised basis of the subspace $W$. To obtain the matrix of inner products between a given list of vectors, use `DotProductMatrix`.

```magma
> K<a> := QuadraticField(-2);
> J := Matrix(K,3,3,[1,2,1, 2,1,0, 1,0,2]);
> V := VectorSpace(K,3,J);
> W := sub<V| [a,a,a], [1,2,3]>;
> InnerProductMatrix(W);
[1 2 1]
[2 1 0]
[1 0 2]
> GramMatrix(W);
[1 0]
[0 9]
> DotProductMatrix([W.1,W.2]);
[ -20 19*a]
[19*a   37]
```

<a id="example-ex-af15e4"></a>
#### `Example: Symmetric and Hermitian Products (ex-af15e4)`

Continuing the previous example, the vector space $V$ does not have the attribute `Involution` assigned and therefore `DotProduct` uses the *symmetric* bilinear form represented by the inner product matrix $J$. However, the field $K$ has a well-defined operation of complex conjugation and so `InnerProduct` uses the *hermitian* form represented by $J$.

```magma
> u := W.1+W.2;
> DotProduct(u,u);
38*a + 17
> InnerProduct(u,u);
57
```

<a id="orthog"></a>
<a id="subsectorthog"></a>
#### Orthogonality

If $\beta$ is any bilinear or sesquilinear form, the vectors $u$ and $v$ are *orthogonal* if $\beta(u,v) = 0$. The *left orthogonal complement* of a subset $X$ of $V$ is the subspace

$$
{}^\perp X := \{\,u \in V \mid \beta(u,x) = 0\text{ for all }x\in X\,\}
$$

and the *right orthogonal complement* of $W$ is

$$
X^\perp := \{\,u \in V \mid \beta(x,u) = 0\text{ for all }x\in X\,\}.
$$

If $\beta$ is reflexive, then ${}^\perp X = X^\perp$.

<a id="function-orthogonalcomplement-modtupfld-modtupfld"></a>
##### `OrthogonalComplement(V, X : parameters): ModTupFld, ModTupFld -> ModTupFld`

```magma
Right: BoolElt                    Default: false
```

The default value is the left orthogonal complement of $X$ in $V$. To obtain the right orthogonal complement set `Right` to `true`.

<a id="function-radical-modtupfld"></a>
##### `Radical(V : parameters): ModTupFld -> ModTupFld`

```magma
Right: BoolElt                    Default: false
```

The left radical of the inner product space $V$, namely ${}^\perp V$. To obtain the right radical set `Right` to `true`.

A bilinear or sesquilinear form $\beta$ is *non-degenerate* if $\hbox{rad}(V) = 0$, where $V$ is the polar space of $\beta$.

<a id="function-isnondegenerate-modtupfld"></a>
##### `IsNondegenerate(V): ModTupFld -> BoolElt`

Returns `true` if the determinant of the matrix of inner products of the basis vectors of $V$ is non-zero, otherwise `false`. This function takes into account the field automorphism, if any, attached to the `Involution` attribute of the generic space of $V$.

<a id="function-isdegenerate-modtupfld"></a>
##### `IsDegenerate(V): ModTupFld -> BoolElt`

The opposite of the above.

If $V$ is a quadratic space over a perfect field of characteristic 2, the restriction of the quadratic form $Q$ to the radical is a semilinear functional (with respect to $x \mapsto x^2$) whose kernel is the *singular radical* of $V$. A quadratic space is *non-singular* if its singular radical is zero.

<a id="function-singularradical-modtupfld"></a>
##### `SingularRadical(V): ModTupFld -> ModTupFld`

The kernel of the restriction of the quadratic form of the quadratic space $V$ to the radical of $V$.

<a id="function-isnonsingular-modtupfld"></a>
##### `IsNonsingular(V): ModTupFld -> BoolElt`

Returns `true` if $V$ is a non-singular quadratic space, otherwise `false`.

<a id="structure"></a>
<a id="sectstructure"></a>
### Isotropic and Singular Vectors and Subspaces

Let $\beta$ be a reflexive bilinear or a sesquilinear form on the vector space $V$. A non-zero vector $v$ is *isotropic* (with respect to $\beta$) if $\beta(v,v) = 0$. If $Q$ is a quadratic form, a non-zero vector $v$ is *singular* if $Q(v) = 0$.

<a id="function-hasisotropicvector-modtupfld"></a>
#### `HasIsotropicVector(V): ModTupFld -> BoolElt, ModTupFldElt`

Determine whether the polar space $V$ contains an isotropic vector; if it does, the second return value is a representative.

<a id="function-hassingularvector-modtupfld"></a>
#### `HasSingularVector(V): ModTupFld -> BoolElt, ModTupFldElt`

Determine whether the quadratic space $V$ contains a singular vector; if it does, the second return value is a representative.

A subspace $W$ of a polar space is *totally isotropic* if every non-zero vector of $W$ is isotropic.

<a id="function-istotallyisotropic-modtupfld"></a>
#### `IsTotallyIsotropic(V): ModTupFld -> BoolElt`

Returns `true` if the polar space $V$ is totally isotropic, otherwise `false`.

A subspace $W$ of a quadratic space defined by a quadratic form $Q$ is *totally singular* if $Q(w) = 0$ for all $w\in W$.

<a id="function-istotallysingular-modtupfld"></a>
#### `IsTotallySingular(V): ModTupFld -> BoolElt`

Returns `true` if the quadratic space $V$ is totally singular, otherwise `false`.

<a id="function-maximaltotallyisotropicsubspace-modtupfld"></a>
#### `MaximalTotallyIsotropicSubspace(V): ModTupFld -> ModTupFld`

A representative maximal totally isotropic subspace of the polar space $V$.

<a id="function-maximaltotallysingularsubspace-modtupfld"></a>
#### `MaximalTotallySingularSubspace(V): ModTupFld -> ModTupFld`

A representative maximal totally singular subspace of the quadratic space $V$.

The *Witt index* of a polar space $V$ that is not a quadratic space is the dimension of a maximal totally isotropic space. The *Witt index* of a quadratic space is the dimension of a maximal totally singular subspace.

If the characteristic of the field is not 2 and if $\beta$ is the polar form of $Q$, a subspace is totally singular if and only if it is totally isotropic with respect to $\beta$; in this case the Witt index of $Q$ coincides with the Witt index of $\beta$.

<a id="function-wittindex-modtupfld"></a>
#### `WittIndex(V): ModTupFld -> RngIntElt`

The Witt index of the polar space $V$.

An ordered pair of vectors $(u,v)$ such that $u$ and $v$ are isotropic and $\beta(u,v) = 1$ is a *hyperbolic pair*. If $V$ is a quadratic space, $u$ and $v$ are required to be singular. The subspace spanned by a hyperbolic pair is a *hyperbolic plane*.

If $V$ is a pseudo-symplectic space defined by a symmetric bilinear form $\beta$ over a finite field of characteristic 2, define the *pseudo-radical* of $V$ to be the radical of the hyperplane $\{ v\in V\mid \beta(v,v) = 0\}$.

<a id="function-hyperbolicpair-modtupfld-modtupfldelt"></a>
#### `HyperbolicPair(V, u): ModTupFld, ModTupFldElt -> ModTupFldElt`

Given a singular or isotropic vector $u$ which is not in the radical or pseudo-radical, return a vector $v$ such that $(u,v)$ is a hyperbolic pair.

<a id="example-ex-ced2e7"></a>
#### `Example: Isotropic Vectors in a Pseudo-Symplectic Space (ex-ced2e7)`

The vector space of dimension 2 over ${\bf F}_{2}$ is pseudo-symplectic (the form is the identity matrix). It has three non-zero elements only one of which is isotropic. This confirms that not every isotropic vector in a non-degenerate pseudo-symplectic space belongs to a hyperbolic pair.

```magma
> V := VectorSpace(GF(2),2);
> IsPseudoSymplecticSpace(V);
true
> IsNondegenerate(V);
true
> { v : v in V | v ne V!0 and DotProduct(v,v) eq 0};
{
    (1 1)
}
```

A polar space $V$ has a *hyperbolic splitting*; namely, a direct sum decomposition

$$
V = L_1\perp L_2\perp \cdots\perp L_m \perp W
$$

where the $L_i$ are *hyperbolic planes* and $m$ is maximal.

The polar space is *hyperbolic* if $W = 0$; i.e., it is an orthogonal sum of hyperbolic planes. In Bourbaki [[Bou07](https://docs.magma-maths.org/references.md#cite-bourbaki-forms), p. 66] the corresponding form is said to be *neutral*.

If the form defining the polar space is non-degenerate and not pseudo-alternating, then every isotropic (resp. singular) vector belongs to a hyperbolic pair. Therefore if the charactersistic is not 2, $W$ is *anisotropic*; i.e., it does not contain any isotropic vectors. In this case the integer $m$ is the *Witt index* of the form and $W$ is called the *anisotropic component* of the splitting.

If the characteristic is 2 and $V$ is a quadratic space, $W$ does not contain singular vectors but it may contain isotropic vectors.

<a id="example-ex-b0692a"></a>
#### `Example: Hyperbolic Splitting in Characteristic 2 (ex-b0692a)`

The last term of a hyperbolic splitting of a quadratic space in characteristic 2 can contain an isotropic vector.

```magma
> Q := StandardQuadraticForm(6,4 : Minus);
> V := QuadraticSpace(Q);
> WittIndex(V);
2
> H := HyperbolicSplitting(V);
> W := sub< V | H[2] >;
> HasSingularVector(W);
false
> HasIsotropicVector(W);
true (    0     0     1     0     0     0)
```

<a id="function-hyperbolicsplitting-modtupfld"></a>
#### `HyperbolicSplitting(V): ModTupFld -> Tup`

A pair $(M,B)$, where $M$ is a maximal list of pairwise orthogonal hyperbolic pairs and $B$ is a basis for the orthogonal complement of the subspace they span. This function requires the form to be non-degenerate and, except for symplectic spaces, the base ring of $V$ must be a finite field.

<a id="example-ex-7e8c7f"></a>
#### `Example: Hyperbolic Splitting of a Symmetric Form (ex-7e8c7f)`

Find the hyperbolic splitting of a polar space defined by a symmetric bilinear form. In this example $W$ is a non-degenerate subspace of the polar space $V$.

```magma
> K<a> := GF(7,2);
> J := Matrix(K,3,3,[1,2,1, 2,1,0, 1,0,2]);
> V := VectorSpace(K,3,J);
> W := sub<V| [a,a,a], [1,2,3]>;
> IsNondegenerate(W);
true
> HyperbolicSplitting(W);
<[
    [
        (a^20    1 a^39),
        (a^12    2    a)
    ]
], []>
```

<a id="example-ex-621e11"></a>
#### `Example: Splitting Off the Radical (ex-621e11)`

The polar space $V$ of the previous example is degenerate and so `HyperbolicSplitting` cannot be applied directly. Instead, we first split off the radical.

```magma
> IsNondegenerate(V);
false
> R := Radical(V);
> H := (Dimension(R) eq 0) select V else
>   sub<V|[e : e in ExtendBasis(B,V) | e notin B] where B is Basis(R)>;
> HyperbolicSplitting(H);
<[
    [
        (   0 a^20    1),
        (   0 a^12    2)
    ]
], []>
```

A non-degenerate polar space $V$ of dimension $2m$ which is the direct sum of two totally isotropic subspaces is hyperbolic and it has a *symplectic basis*; i.e., a basis $e_1$, $f_1$, …, $e_m$, $f_m$ such that the pairs $(e_i, f_i)$, $1\le i\le m$ are mutually orthogonal hyperbolic pairs.

<a id="function-symplecticbasis-modtupfld-modtupfld-modtupfld"></a>
#### `SymplecticBasis(V, U, W): ModTupFld, ModTupFld, ModTupFld -> [ModTupFldElt]`

Given totally isotropic subspaces $U$ and $W$ of a non-degnerate polar space $V$ such that $V = U\oplus W$, return a symplectic basis for $V$ such that $e_1$, $e_2$, …, $e_m$ is a basis for $U$ and $f_1$, $f_2$, …, $f_m$ is a basis for $W$.

Let $V = L_1\perp\cdots\perp L_m \perp W \perp \hbox{rad}(V)$ be a hyperbolic splitting of the polar space $V$ where the $L_i$ are hyperbolic planes spanned by hyperbolic pairs $(e_i,f_i)$ for $1\le i\le m$. The subspaces $P = \langle e_1,\dots,e_m\rangle$ and $N = \langle f_1,\dots,f_m\rangle$ are totally isotropic (resp. totally singular) and we call the $4$-tuple $(\hbox{rad}(V),P,N,W)$ a *Witt decomposition* of $V$.

<a id="function-wittdecomposition-modtupfld"></a>
#### `WittDecomposition(V): ModTupFld -> SeqEnum[ModTupFld]`

The Witt decomposition of the space $V$.

<a id="function-wittdecomposition-algmatelt-fldfin-fldaut"></a>
#### `WittDecomposition(M, a): AlgMatElt[FldFin], FldAut -> AlgMatElt[FldFin], AlgMatElt[FldFin]`

Given a field automorphism $a$, and a matrix $M$ which is hermitian with respect to $a$, returns the Gram matrix with respect to a basis of a Witt decomposition of the polar space of $M$, in the order $(P, N, W, \hbox{rad}(V))$. Also returns the basis matrix.

A quadratic space is *metabolic* if it is a direct sum $E\oplus F$ of totally singular subspaces $E$ and $F$ such that $E = E^\perp$.

Given a quadratic space with quadratic form $q : V \to F$, the *metabolic space* based on $V$ is the quadratic space $M = V\oplus V^*$ with quadratic form $Q : M \to F$ defined by $Q(v,f) = q(v) + vf$.

<a id="function-metabolicspace-modtupfld"></a>
#### `MetabolicSpace(V): ModTupFld -> ModTupFld`

The metabolic space based on the quadratic space $V$.

<a id="standard"></a>
<a id="sectstandard"></a>
### The Standard Forms

This section describes the “standard” alternating, hermitian, quadratic, and symmetric forms defined on a finite dimensional vector space over a field. These are forms of maximal Witt index together with the quadratic forms of non-maximal Witt index over finite fields (see Section [Isotropic and Singular Vectors and Subspaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/structure.md#sectstructure)). The standard forms are preserved by the Magma implementation of the classical groups over finite fields.

If $J$ is the matrix of a bilinear form, $X$ preserves the form if $XJX^\mathrm{tr}= J$. If $J$ represents an hermitian form and if $\overline{X}$ is obtained from $X$ by application of the field automorphism, then $X$ preserves the form if $XJ\overline{X}^\mathrm{tr}= J$.

If $\beta$ is a non-degenerate alternating form, then $\hbox{rad}(V)$ and the anisotropic component of a hyperbolic splitting are zero. Thus the dimension of $V$ must be even and $V$ has a basis of mutually orthogonal hyperbolic pairs. In particular, up to equivalence, there is only one non-degenerate alternating form on $V$.

<a id="function-standardalternatingform-rngintelt-rng"></a>
#### `StandardAlternatingForm(n, R): RngIntElt, Rng -> AlgMatElt`

<a id="function-standardalternatingform-rngintelt-rngintelt"></a>
#### `StandardAlternatingForm(n, q): RngIntElt, RngIntElt -> AlgMatElt`

If $n = 2m$, this function returns the $n\times n$ matrix of a non-degenerate alternating form over the ring $R$ (or the field of $q$ elements) such that if $e_1$, $e_2$, …, $e_{2m}$ is the standard basis, then $(e_1,e_{2m})$, $(e_2,e_{2m-1})$, …, $(e_m,e_{m+1})$ are mutually orthogonal hyperbolic pairs.

The group of isometries of this form is the symplectic group $\hbox{Sp}(2m,R)$.

<a id="example-ex-3c60cd"></a>
#### `Example: Standard Alternating Form (ex-3c60cd)`

Create a symplectic geometry with the standard alternating form and then check that every non-zero vector is isotropic.

```magma
> K := GF(5);
> J := StandardAlternatingForm(4,K);
> J;
[0 0 0 1]
[0 0 1 0]
[0 4 0 0]
[4 0 0 0]
> V := VectorSpace(K,4,J);
> forall{ v : v in V | DotProduct(v,v) eq 0 };
true
```

<a id="function-standardpseudoalternatingform-rngintelt-fld"></a>
#### `StandardPseudoAlternatingForm(n, K): RngIntElt, Fld -> AlgMatElt`

<a id="function-standardpseudoalternatingform-rngintelt-rngintelt"></a>
#### `StandardPseudoAlternatingForm(n, q): RngIntElt, RngIntElt -> AlgMatElt`

The matrix of the standard pseudo-alternating form of degree $n$ over the field $K$ (or the finite field of order $q$), which must have characteristic 2; that is, a symmetric form which is not alternating.

<a id="function-standardhermitianform-rngintelt-fld"></a>
#### `StandardHermitianForm(n, K): RngIntElt, Fld -> AlgMatElt, Map`

<a id="function-standardhermitianform-rngintelt-rngintelt"></a>
#### `StandardHermitianForm(n, q): RngIntElt, RngIntElt -> AlgMatElt, Map`

The first return value of this function is the $n\times n$ anti-diagonal matrix $(\delta_{i,n-i+1})$ over the field $K$ (or the field of $q^2$ elements). If $K$ is the finite field of $q^2$ elements, the second return value is the field involution $K \to K :x \mapsto x^q$. If $K$ is a field which admits the operation of complex conjugation, the second return value is the field automorphism which sends each element to its complex conjugate.

If $\beta$ is a non-degenerate hermitian form over a finite field, then $\hbox{rad}(V)$ is zero and the dimension of the anisotropic component of a hyperbolic splitting is either 1 or 0.

In the finite field case, the group of isometries of this form is $\hbox{GU}(n,q)$.

<a id="function-standardquadraticform-rngintelt-fld"></a>
#### `StandardQuadraticForm(n, K : parameters): RngIntElt, Fld -> AlgMatElt`

<a id="function-standardquadraticform-rngintelt-rngintelt"></a>
#### `StandardQuadraticForm(n, q : parameters): RngIntElt, RngIntElt -> AlgMatElt`

```magma
Minus  : BoolElt                      Default: false
Variant: MonStgElt                    Default: "Default"
```

An $n\times n$ upper triangular matrix representing a quadratic form over the field $K$ (or the field of order $q$). The default option is to return a form of maximal Witt index, namely the upper triangular matrix whose non-zero entries are $\delta_{i,n-i+1}$, where $1 \le i \le (n+1)/2$.

If `Minus` is `true` and $n = 2m$, this function returns a form whose Witt index is $m-1$. If `Minus` is `true`, $n = 2m+1$ and $K$ is a finite field of odd characteristic, the return value is a form of Witt index $m$ which is similar to but not congruent to the default form. Use the `Revised` option of `Variant` to obtain the form preserved by the orthogonal groups `AltGOMinus(n,q)` and subgroups.

If $K$ is a finite field of order $q$ and $W$ is the anisotropic component of a hyperbolic splitting of a form of even rank and `Minus` type, then $W$ has basis vectors $e$ and $f$ such that $Q(e) = -1$, $\beta(e,f) = -\xi-\xi^q$, and $Q(f) = -\xi\xi^q$, where $\xi$ is a primitive element of ${\bf F}_{q^2}$. If the characteristic of $K$ is odd, the `Revised` option returns a form corresponding to an orthonormal basis for $W$.

<a id="example-ex-78f890"></a>
#### `Example: Standard Quadratic Form of Minus Type (ex-78f890)`

Construct a standard quadratic form of minus type.

```magma
> K<z> := GF(7,2);
> Q := StandardQuadraticForm(4,49 : Minus);
> Q;
[   0    0     0    1]
[   0    6     5    0]
[   0    0  z^29    0]
[   0    0     0    0]
> _<x> := PolynomialRing(K);
> a := Q[2,2] * Q[3,3];
> IsIrreducible(x^2+x+a);
true
```

<a id="example-ex-29b8f5"></a>
#### `Example: Revised Minus-Type Quadratic Form (ex-29b8f5)`

Compare the revised form with the standard form: the forms `Q` above and `QR` below have different entries in the central $2\times 2$ block.

```magma
> QR := StandardQuadraticForm(4,49 : Minus, Variant := "Revised");
> QR;
[   0    0     0    1]
[   0    4     0    0]
[   0    0  z^11    0]
[   0    0     0    0]
```

<a id="function-standardsymmetricform-rngintelt-fld"></a>
#### `StandardSymmetricForm(n, K): RngIntElt, Fld -> AlgMatElt`

<a id="function-standardsymmetricform-rngintelt-rngintelt"></a>
#### `StandardSymmetricForm(n, q : parameters): RngIntElt, RngIntElt -> AlgMatElt`

```magma
Minus  : BoolElt                      Default: false
Variant: MonStgElt                    Default: "Default"
```

In all cases this is $Q + Q^{\hbox{tr}}$, where $Q$ is the corresponding standard quadratic form, as defined above.

<a id="constructions"></a>
<a id="sectconstr"></a>
### Constructing Polar Spaces

If $J$ is an $n\times n$ matrix, the command `VectorSpace(K,n,J)` creates a vector space of dimension $n$ over $K$ with a bilinear form whose matrix is $J$.

The default form attached to every vector space in Magma is the symmetric form whose matrix is the identity matrix.

A vector space $V$ is recognised as a polar space if any of the following conditions apply. (There is no check to ensure that the inner product matrix is non-degenerate.)

1.There is a quadratic form attached to $V$.

2.There is a field involution attached to $V$ and the inner product matrix of $V$ is hermitian or skew-hermitian with respect to this involution.

3.The inner product matrix of $V$ is symmetric or alternating.

Thus a vector space with a symmetric inner product matrix but no quadratic form attached is a polar space. If the characteristic of the field is 2 and the form is not alternating it is a pseudo-symplectic space, otherwise we shall call it an orthogonal space to distinguish it from quadratic spaces.

<a id="function-polarspace-algmatelt-fldfin-fldaut"></a>
#### `PolarSpace(F, a): AlgMatElt[FldFin], FldAut -> ModTupFld[FldFin]`

```magma
Symbolic: BoolElt                    Default: true
```

The polar space associated to the Gram matrix $F$, hermitian with repsect to the field automorphism $a$. `Symbolic` determines the method of finding isotropic subspaces.

<a id="function-trivialpolarspace-fldfin-rngintelt"></a>
#### `TrivialPolarSpace(F, n): FldFin, RngIntElt -> ModTupFld[FldFin]`

Polar space over $F$ of dimension $n$ with the zero bilinear form.

<a id="function-ispolarspace-modtupfld"></a>
#### `IsPolarSpace(V): ModTupFld -> BoolElt`

Check if the vector space $V$ is a quadratic space or if the Gram matrix of $V$ is a reflexive form.

<a id="function-polarspacetype-modtupfld"></a>
#### `PolarSpaceType(V): ModTupFld -> MonStgElt`

The type of the polar space $V$, returned as a string.

<a id="example-ex-1d3f36"></a>
#### `Example: Testing for a Polar Space (ex-1d3f36)`

Create the standard vector space of dimension 4 over the rational field and check if it is a polar space.

```magma
> V := VectorSpace(Rationals(),4);
> IsPolarSpace(V);
true
> PolarSpaceType(V);
orthogonal space
```

<a id="subsectisotropic"></a>
<a id="id1"></a>
#### Isotropic Subspaces

<a id="function-firstisotropicsubspace-modtupfld-fldfin-rngintelt"></a>
##### `FirstIsotropicSubspace(V, k): ModTupFld[FldFin], RngIntElt -> ModTupFld[FldFin]`

Starts an enumeration process of $k$-dimensional isotropic subspaces in $V$, and returns the first non-singular one.

<a id="function-nextisotropicsubspace-modtupfld-fldfin-rngintelt"></a>
##### `NextIsotropicSubspace(V, k): ModTupFld[FldFin], RngIntElt -> ModTupFld[FldFin]`

The next $k$-dimensional isotropic subspace in $V$.

<a id="function-allisotropicsubspaces-modtupfld-fldfin-rngintelt"></a>
##### `AllIsotropicSubspaces(V, k): ModTupFld[FldFin], RngIntElt -> [ ModTupFld[FldFin] ]`

All $k$-dimensional isotropic subspaces in $V$.

<a id="function-numberofisotropicsubspaces-modtupfld-fldfin-rngintelt"></a>
##### `NumberOfIsotropicSubspaces(V, k): ModTupFld[FldFin], RngIntElt -> RngIntElt`

The number of $k$-dimensional isotropic subspaces in $V$.

<a id="sympspace"></a>
<a id="subsectsympsp"></a>
#### Symplectic Spaces

<a id="function-symplecticspace-algmatelt"></a>
##### `SymplecticSpace(J): AlgMatElt -> ModTupRng`

The symplectic space of dimension $n$ defined by the $n\times n$ matrix $J$. This function checks to ensure that $J$ is alternating.

The symplectic inner product on this space is obtained from `InnerProduct`, which evaluates the alternating form $J$ and returns a value in the base ring. This is distinct from the intrinsic `SymplecticInnerProduct` described in Chapter [Quantum Codes](https://docs.magma-maths.org/CodingTheory/QuantumCodes/index-quantum-codes.md#chap-codequantum): that intrinsic computes the coding-theory product $(a|b)*(c|d) = ad - bc$ in compact or extended format and returns its field trace down to the prime field (see that chapter for the precise source field of the trace in each format).

<a id="function-issymplecticspace-modtupfld"></a>
##### `IsSymplecticSpace(W): ModTupFld -> BoolElt`

Returns `true` if the `Involution` attribute of the generic vector space $W$ is not assigned and the space carries an alternating form, otherwise `false`.

Note that a quadratic space over a field of characteristic 2 satisfies these conditions and consequently this function will return `true` for these spaces.

<a id="function-ispseudosymplecticspace-modtupfld"></a>
##### `IsPseudoSymplecticSpace(W): ModTupFld -> BoolElt`

Given a vector space $W$ over a finite field, this intrinsic returns `true` if the base field has characteristic 2, the `Involution` attribute is not assigned to the generic space and the form is symmetric but not alternating, otherwise `false`.

<a id="function-directsum-modtuprng-modtuprng"></a>
##### `DirectSum(V, W): ModTupRng, ModTupRng -> ModTupRng, Map, Map`

If $V$ and $W$ are symplectic spaces this function returns the orthogonal direct sum $V\perp W$ and linear embeddings $V \to V\perp W$ and $W \to V\perp W$.

<a id="unitaryspace"></a>
<a id="subsectunitarysp"></a>
#### Unitary Spaces

In order to accommodate hermitian forms it is necessary to assign a field automorphism of order two to the `Involution` attribute of the vector space.

Thus a unitary space is characterised as a vector space $V$ whose ambient space, `Generic(V)`, has the attribute `Involution` and whose inner product matrix is either hermitian or skew hermitian.

<a id="function-unitaryspace-algmatelt-map"></a>
##### `UnitarySpace(J, sigma): AlgMatElt, Map -> ModTupFld`

The $n$-dimensional unitary space over the base field $K$ of $J$, where $\sigma$ is an automorphism of $K$ of order 2 and where $J$ is an $n \times n$ matrix which is hermitian or skew-hermitian with respect to $\sigma$.

<a id="function-isunitaryspace-modtupfld"></a>
##### `IsUnitarySpace(W): ModTupFld -> BoolElt, RngIntElt`

Return `true` if the `Involution` attribute of the generic space of $W$ is assigned and the form is either hermitian or skew-hermitian when restricted to $W$. The second return value is $1$ if the form is hermitian and $-1$ if the form is skew-hermitian.

<a id="example-ex-b9c1f1"></a>
##### `Example: Isotropic Vector in a Unitary Space (ex-b9c1f1)`

Create a unitary geometry with the standard hermitian form and check that the given vector is isotropic. Note that the function `DotProduct` takes both the form and the field involution into account when calculating its values. For finite fields, the function `InnerProduct` *ignores* the field involution.

```magma
> K<z> := GF(25);
> J, sigma := StandardHermitianForm(5,K);
> J;
[   0    0    0    0    1]
[   0    0    0    1    0]
[   0    0    1    0    0]
[   0    1    0    0    0]
[   1    0    0    0    0]
> sigma(z);
z^5
> V := UnitarySpace(J,sigma);
> u := V![1,z,0,z^2,-1];
> DotProduct(u,u);
0
> InnerProduct(u,u);
z^20
```

<a id="function-conjugatetranspose-mtrx-map"></a>
##### `ConjugateTranspose(M, sigma): Mtrx, Map -> Mtrx`

The transpose of the matrix $\sigma(M)$, where $\sigma$ is an automorphism of the base field of the matrix $M$.

<a id="quadspace"></a>
<a id="subsectquadsp"></a>
#### Quadratic Spaces

A vector space $V$ with an attached quadratic form is called a *quadratic space*. The polar form of a quadratic space is the inner product matrix $J$ of the space. If the characteristic of the field is not 2, the value of the quadratic form on a row vector $v$ is ${1\over 2}{v*J*v^\mathrm{tr}}$.

<a id="function-quadraticspace-algmatelt"></a>
##### `QuadraticSpace(Q): AlgMatElt -> ModTupRng`

The quadratic space of dimension $n$ defined by the quadratic form represented by an $n\times n$ matrix $Q$. The inner product matrix of the space is $Q + Q^\mathrm{tr}$.

<a id="function-quadraticspace-rngmpolelt"></a>
##### `QuadraticSpace(f): RngMPolElt -> ModTupRng`

The quadratic space of dimension $n$ whose quadratic form is given by the quadratic polynomial $f$ in $n$ variables. If the variables are $x_1$, …, $x_n$, then for $i\le j$, the $(i,j)$-th entry of the matrix of the form is the coefficient of $x_ix_j$ in $f$.

<a id="function-symmetrictoquadraticform-algmatelt"></a>
##### `SymmetricToQuadraticForm(J): AlgMatElt -> AlgMatElt`

Provided the characteristic of the field is not two, this is the upper triangular matrix which represents the quadratic form whose polar form is the symmetric matrix $J$.

<a id="function-quadraticformmatrix-modtuprng"></a>
##### `QuadraticFormMatrix(V): ModTupRng -> ModAlgElt`

The matrix which defines the quadratic form of the quadratic space $V$.

<a id="function-quadraticnorm-modtupfldelt"></a>
##### `QuadraticNorm(v): ModTupFldElt -> FldElt`

The value $Q(v)$, where $Q$ is the quadratic form attached to the generic space of the parent of the vector $v$.

<a id="function-quadraticformpolynomial-modtuprng"></a>
##### `QuadraticFormPolynomial(V): ModTupRng -> RngPolElt`

The polynomial $\sum_{i, j} q_{ij}x_ix_j$, where $Q = (q_{ij})$ is the matrix of the quadratic form of the quadratic space $V$.

<a id="function-quadraticformpolynomial-algmatelt"></a>
##### `QuadraticFormPolynomial(Q): AlgMatElt -> RngPolElt`

The polynomial $\sum_{i, j} q_{ij}x_ix_j$, where $Q = (q_{ij})$ is a matrix representing a quadratic form.

<a id="example-ex-474785"></a>
##### `Example: Quadratic Space from a Polynomial (ex-474785)`

The quadratic space defined by a polynomial.

```magma
> _<x,y,z> := PolynomialRing(Rationals(),3);
> f := x^2 + x*y +3*x*z - 2*y*z + y^2 +z^2;
> V := QuadraticSpace(f);
> PolarSpaceType(V);
quadratic space
> IsNonsingular(V);
true
> QuadraticFormMatrix(V);
[ 1  1  3]
[ 0  1 -2]
[ 0  0  1]
```

<a id="function-orthogonalsum-modtupfld-modtupfld"></a>
##### `OrthogonalSum(V, W): ModTupFld, ModTupFld -> ModTupFld, Map, Map`

The orthogonal direct sum $V$ of the quadratic spaces $V$ and $W$ together with linear embeddings $V \to V\perp W$ and $W \to V\perp W$.

<a id="function-orthogonaltensorproduct-modtupfld-modtupfld"></a>
##### `OrthogonalTensorProduct(V, W): ModTupFld, ModTupFld -> ModTupFld`

The tensor product of the quadratic spaces $V$ and $W$. If $\beta$ and $\gamma$ are the symmetric bilinear forms on $V$ and $W$, respectively, and if $\xi$ is the bilinear form on the tensor product, then $\xi(v_1\otimes w_1,v_2\otimes w_2) = \beta(v_1,v_2)\gamma(w_1,w_2)$.

<a id="function-totallysingularcomplement-modtupfld-modtupfld-modtupfld"></a>
##### `TotallySingularComplement(V, U, W): ModTupFld, ModTupFld, ModTupFld -> ModTupFld`

Given totally singular subspaces $U$ and $W$ of the quadratic space $V$ such that $U^\perp \cap W = 0$ this function returns a totally singular subspace $X$ such that $V = X \oplus U^\perp$ and $W\subseteq X$.

<a id="function-discriminant-modtupfld"></a>
##### `Discriminant(V): ModTupFld -> RngIntElt`

If $V$ is a vector space over the finite field $K$ and if $J$ is the Gram matrix of $V$, the *discriminant* of $V$ is the determinant $\Delta$ of $J$ modulo squares. That is, the discriminant is 0 if $\Delta$ is a square in $K$, 1 if it is a non-square. The form $J$ is required to be non-degenerate.

<a id="function-arfinvariant-modtupfld"></a>
##### `ArfInvariant(V): ModTupFld -> RngIntElt`

The Arf invariant of the quadratic space $V$.

Currently this is available only for quadratic spaces of even dimension $2m$ over a finite field $F$ of characteristic 2. In this case there are two possibilities: either the Witt index of the form is $m$ and the Arf invariant is 0, or the Witt index is $m-1$ and the Arf invariant is 1.

<a id="function-dicksoninvariant-modtupfld-mtrx"></a>
##### `DicksonInvariant(V, f): ModTupFld, Mtrx -> RngIntElt`

The Dickson invariant of the isometry $f$ of the quadratic space $V$ is the rank (mod 2) of $1-f$. If the polar form of $Q$ is non-degenerate, the Dickson invariant defines a homomorphism from the orthogonal group $O(V)$ onto the additive group of order 2.

<a id="function-spinornorm-modtupfld-mtrx"></a>
##### `SpinorNorm(V, f): ModTupFld, Mtrx -> RngIntElt`

The spinor norm of the isometry $f$ of the quadratic space $V$. This is the discriminant of the Wall form (Section [Wall Forms](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/wallform.md#sectwall)) of $f$.

<a id="function-spinornorm-algmatelt-fld-algmatelt-fld"></a>
##### `SpinorNorm(Q, g): AlgMatElt[Fld], AlgMatElt[Fld] -> FldElt`

Given a symmetric matrix $Q$ over a field $F$, and a matrix $g$ satisfying $gQg^\mathrm{tr}= Q$, returns an element $x \in F$ representing in $F / F^{\times 2}$ the spinor norm of the isometry $g$ with repsect to the quadratic form represented by $Q$.

<a id="example-ex-ff51ba"></a>
##### `Example: Spinor Norm over a General Field (ex-ff51ba)`

An example for a spinor norm computation over a general field.

```magma
> Q := SymmetricMatrix(Rationals(), [2,0,2,0,0,2,1,0,0,2,0,0,1,1,52]);
> g := Matrix(Rationals(), 5, 5,
>                    [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,-1,0,0,0,1,0,-1]);
> g * Q * Transpose(g) eq Q;
true
> SpinorNorm(Q,g);
2745
> FactorizationOfQuotient(SpinorNorm(Q, g));
[ <3, 2>, <5, 1>, <61, 1> ]
```

<a id="function-characterqqmodsquares-rngintelt-fldratelt"></a>
##### `CharacterQQModSquares(d, r): RngIntElt, FldRatElt -> RngIntElt`

Let $\chi_d : {\mathbb{Q}}^{\times} / {\mathbb{Q}}^{\times 2} \to {\mathbb{Z}}^{\times}$ be the multiplicative character defined by $\chi_d(p) = -1$ iff $p \mid d$. Returns $\chi_d(r)$.

<a id="function-spinornormrho-rngintelt-grpmatelt-algmatelt"></a>
##### `SpinorNormRho(d, g, Q): RngIntElt, GrpMatElt, AlgMatElt -> RngIntElt`

Let $Q$ be an integral symmetric matrix, $g$ an isometry of the quadratic space, and $d \mid {\rm Disc}(Q)$. Returns the value of $\chi_d$ (as in `CharacterQQModSquares`) at the spinor norm of $g$ with respect to ${\rm O}(Q)$.

<a id="function-hyperbolicbasis-modtupfld-seqenum-modtupfld"></a>
##### `HyperbolicBasis(U, B, W): ModTupFld, SeqEnum, ModTupFld -> SeqEnum`

Given complementary totally singular subspaces $U$ and $W$ of a quadratic space and a basis $B$ for $U$, return a sequence of pairwise orthogonal hyperbolic pairs whose second components form a basis for $W$.

<a id="function-orthogonalreflection-modtupfldelt"></a>
##### `OrthogonalReflection(a): ModTupFldElt -> AlgMatElt`

The reflection determined by a non-singular vector of a quadratic space.

<a id="function-rootsequence-modtupfld-mtrx"></a>
##### `RootSequence(V, f): ModTupFld, Mtrx -> SeqEnum`

Given a matrix $f$ representing an isometry of the quadratic space $V$, return a sequence of vectors such that the product of the corresponding orthogonal reflections is $f$. The empty sequence is returned if $f$ is the identity matrix.

<a id="function-reflectionfactors-modtupfld-mtrx"></a>
##### `ReflectionFactors(V, f): ModTupFld, Mtrx -> SeqEnum`

Given a matrix $f$ representing an isometry of the quadratic space $V$, return a sequence of reflections whose product is $f$. The empty sequence corresponds to the identity matrix.

Given a quadratic space $V$ defined by a quadratic form $Q$ with polar form $\beta$ and non-zero vectors $u,v \in V$ such that $u$ is singular and $\beta(u,v) = 0$, the *Siegel transformation* (also called an Eichler transformation) is the isometry $\rho_{u,v}$ defined by

$$
x \rho_{u,v} = x + \beta(x,v)u - \beta(x,u)v - Q(v)\beta(x,u) u.
$$

<a id="function-siegeltransformation-modtupfldelt-modtupfldelt"></a>
##### `SiegelTransformation(u, v): ModTupFldElt, ModTupFldElt -> AlgMatElt`

The Siegel transformation defined by a singular vector $u$ and a vector $v$ orthogonal to $u$. The common parent of $u$ and $v$ must be a quadratic space.

<a id="example-ex-717e94"></a>
##### `Example: Isometries from Siegel Transformations (ex-717e94)`

A group of isometries generated by Siegel transformations.

```magma
> Q := StandardQuadraticForm(4,3);
> V := QuadraticSpace(Q);
> u := V.1;
> QuadraticNorm(u);
0
> X := { v : v in V | DotProduct(u,v) eq 0 and QuadraticNorm(v) ne 0 };
> #X;
12
> H := sub< GL(V) | [SiegelTransformation(u,v) : v in X]>;
> #H;
9
```

<a id="isom-sim"></a>
<a id="sectisomsim"></a>
### Isometries and Similarities

If $\beta$ is a bilinear or sesquilinear form on the vector space $V$, a linear transformation $g$ of $V$ is an *isometry* if $g$ preserves $\beta$; it is a *similarity* if it preserves $\beta$ up to a non-zero scalar multiple.

<a id="isometry"></a>
<a id="subsectisom"></a>
#### Isometries

<a id="function-isisometry-modtupfld-modtupfld-map"></a>
##### `IsIsometry(U, V, f): ModTupFld, ModTupFld, Map -> BoolElt`

Returns `true` if the map $f$ is an isometry from $U$ to $V$ with respect to the attached forms.

<a id="function-isisometry-map"></a>
##### `IsIsometry(f): Map -> BoolElt`

Returns `true` if the map $f$ is an isometry from its domain to its codomain.

<a id="function-isisometry-modtupfld-mtrx"></a>
##### `IsIsometry(V, g): ModTupFld, Mtrx -> BoolElt`

Returns `true` if the matrix $g$ is an isometry of $V$ with respect to the attached form.

<a id="function-isisometric-modtupfld-modtupfld"></a>
##### `IsIsometric(V, W): ModTupFld, ModTupFld -> BoolElt, Map`

Determines whether the polar spaces $V$ and $W$ are isometric; if they are, an isometry is returned (as a map).

<a id="example-ex-9909e6"></a>
##### `Example: Isometric Polar Spaces (ex-9909e6)`

A vector space is always equipped with a bilinear form and the default value is the identity matrix. However the “standard” symmetric form is $Q+Q^{\hbox{tr}}$, where $Q$ is the standard quadratic form. In the following example the polar spaces defined by these forms are similar but not isometric.

```magma
> F := GF(5);
> V1 := VectorSpace(F,5);
> PolarSpaceType(V1);
orthogonal space
> WittIndex(V1);
2
> J2 := StandardSymmetricForm(5,F);
> J2;
[0 0 0 0 1]
[0 0 0 1 0]
[0 0 2 0 0]
[0 1 0 0 0]
[1 0 0 0 0]
> V2 := VectorSpace(F,5,J2);
> IsIsometric(V1,V2);
false
> V3 := VectorSpace(F,5,2*J2);
> flag, f := IsIsometric(V1,V3); flag;
true
> IsIsometry(f);
true
```

If $J$ is an $n\times n$ matrix which represents a bilinear form and if $M$ is a non-singular $n\times n$ matrix, then $J$ and $MJM^{\hbox{tr}}$ are said to be *congruent* and they define isometric polar spaces.

Conversely, given bilinear forms $J_1$ and $J_2$ the following example shows how to use the `IsIsometric` function to determine whether $J_1$ and $J_2$ are congruent and if so how to find a matrix $M$ such that $J_1 = MJ_2M^{\hbox{tr}}$.

<a id="example-ex-5a3a59"></a>
##### `Example: Isometry Between Symplectic Spaces (ex-5a3a59)`

Begin with alternating forms $J_1$ and $J_2$ over ${\bf F}_{25}$, construct the corresponding symplectic spaces and then use the isometry to define the matrix $M$.

```magma
> F<x> := GF(25);
> J1 := Matrix(F,4,4,[ 0, x^7, x^14, x^13, x^19, 0, x^8, x^5,
>   x^2, x^20, 0, x^17, x, x^17, x^5, 0 ]);
> J2 := Matrix(F,4,4,[ 0, x^17, 2, x^23, x^5, 0, x^15, x^5,
>   3, x^3, 0, 4, x^11, x^17, 1, 0 ]);
> V1 := SymplecticSpace(J1);
> V2 := SymplecticSpace(J2);
> flag, f := IsIsometric(V1,V2); assert flag;
> f;
Mapping from: ModTupFld: V1 to ModTupFld: V2 given by a rule
> M := Matrix(F,4,4,[f(V1.i) : i in [1..4]]);
> J1 eq M*J2*Transpose(M);
true
```

<a id="example-ex-6727c3"></a>
##### `Example: Transforming Forms with TransformForm (ex-6727c3)`

Another way to obtain a matrix with the same effect as $M$ is to use the function `TransformForm`.

```magma
> M1 := TransformForm(J1,"symplectic");
> M2 := TransformForm(J2,"symplectic");
> M_alt := M1*M2^-1;
> J1 eq M_alt*J2*Transpose(M_alt);
true
```

<a id="function-commoncomplement-modtupfld-modtupfld-modtupfld"></a>
##### `CommonComplement(V, U, W): ModTupFld, ModTupFld, ModTupFld -> ModTupFld`

A common complement to the subspaces $U$ and $W$ in the vector space $V$. (The subspaces must have the same dimension.) This is used by the following function, which implements Witt’s theorem.

<a id="function-extendisometry-modtupfld-modtupfld-map"></a>
##### `ExtendIsometry(V, U, f): ModTupFld, ModTupFld, Map -> Map`

An extension of the isometry $f : U \to V$ to an isometry $V \to V$, where $U$ is a subspace of the polar space $V$.

This is an implementation of Witt’s theorem on the extension of an isometry defined on a subspace of a symplectic, unitary, or quadratic space. The isometry $f$ must satisfy $f(U\cap \hbox{rad}(V)) = f(U)\cap \hbox{rad}(V)$.

If the characteristic is two and the form $J$ of $V$ is symmetric, then $J$ must be alternating.

<a id="function-isometrygroup-modtupfld"></a>
##### `IsometryGroup(V): ModTupFld -> GrpMat`

The group of isometries of the polar space $V$. This includes degenerate polar spaces as well as polar spaces defined by a quadratic form over a field of characteristic two.

Given a reflexive form $J$, the function `IsometryGroup(J)` defined in Chapter [Algebras with Involution](https://docs.magma-maths.org/Algebras/AlgebrasWithInvolution/index-algebras-with-involution.md#chapstaralgebras) returns the isometry group of $J$. More generally, if $S$ is a sequence of reflexive forms, the function `IsometryGroup(S)` returns the group of isometries of the system.

<a id="example-ex-833a77"></a>
##### `Example: Isometry Group of a Degenerate Quadratic Space (ex-833a77)`

We give an example of an isometry group of a degenerate quadratic space over a field of characteristic 2.

```magma
> F := GF(4);
> Q1 := StandardQuadraticForm(4,F : Minus);
> Q := DiagonalJoin(Q1,ZeroMatrix(F,2,2));
> V := QuadraticSpace(Q);
> G := IsometryGroup(V);
> [ IsIsometry(V,g) : g in Generators(G) ];
[ true, true, true, true, true, true, true ]
> #G;
96259276800
```

<a id="example-ex-86d774"></a>
##### `Example: Conjugating Isometry Groups (ex-86d774)`

The matrix $M$ constructed in Example [Isometry Between Symplectic Spaces](https://docs.magma-maths.org/MatricesLinearAlgebra/PolarSpaces/isom-sim.md#example-ex-5a3a59) can be used to conjugate the isometry group of $J_1$ to the isometry group of $J_2$.

```magma
> F<x> := GF(25);
> J1 := Matrix(F,4,4,[ 0, x^7, x^14, x^13, x^19, 0, x^8, x^5,
>   x^2, x^20, 0, x^17, x, x^17, x^5, 0 ]);
> J2 := Matrix(F,4,4,[ 0, x^17, 2, x^23, x^5, 0, x^15, x^5,
>   3, x^3, 0, 4, x^11, x^17, 1, 0 ]);
> V1 := SymplecticSpace(J1);
> V2 := SymplecticSpace(J2);
> flag, f := IsIsometric(V1,V2); assert flag;
> M := Matrix(F,4,4,[f(V1.i) : i in [1..4]]);
> G1 := IsometryGroup(V1);
> G2 := IsometryGroup(V2);
> M^-1*G1.1*M in G2;
true
> M^-1*G1.2*M in G2;
true
```

<a id="similarity"></a>
<a id="subsectsimil"></a>
#### Similarities

If $\beta$ is a bilinear or sesquilinear form, a linear transformation $f$ is a *similarity* with *multiplier* $\lambda$ if $\beta(uf,vf) = \lambda\beta(u,v)$ for all $u,v$.

<a id="function-issimilarity-modtupfld-modtupfld-map"></a>
##### `IsSimilarity(U, V, f): ModTupFld, ModTupFld, Map -> BoolElt, FldElt`

Returns `true` if the map $f$ is a similarity from $U$ to $V$ with respect to the attached forms. The second return value is the multiplier.

<a id="function-issimilarity-map"></a>
##### `IsSimilarity(f): Map -> BoolElt, FldElt`

Returns `true` if the map $f$ is a similarity from its domain to its codomain. The second return value is the multiplier.

<a id="function-issimilarity-modtupfld-mtrx"></a>
##### `IsSimilarity(V, g): ModTupFld, Mtrx -> BoolElt, FldElt`

Returns `true` if the matrix $g$ is a similarity of $V$ with respect to the attached form. The second return value is the multiplier.

<a id="function-issimilar-modtupfld-modtupfld"></a>
##### `IsSimilar(V, W): ModTupFld, ModTupFld -> BoolElt, Map`

Determines whether the polar spaces $V$ and $W$ are similar; if they are, a similarity is returned (as a map).

<a id="example-ex-86e68e"></a>
##### `Example: Similar Hermitian and Skew-Hermitian Spaces (ex-86e68e)`

An example of two unitary spaces, the first defined by an hermitian form, the second by a skew-hermitian form. The spaces are similar but not isometric.

```magma
> F<z> := GF(25);
> sigma := hom< F -> F | x :-> x^5 >;
> J1 := Matrix(F,4,4,[
>    0, z^3, z^14, z^9,   z^15, 2, z^21, z^5,
>    z^22, z^9, 1, z^7,   z^21, z, z^11, 4]);
> J2 := Matrix(F,4,4,[
>    z^15, z^10, z^17, z^7,  z^14, z^15, z^14, z^9,
>    z, z^10, z^3, z^20,     z^23, z^9, z^16, z^21]);
> V1 := UnitarySpace(J1,sigma);
> V2 := UnitarySpace(J2,sigma);
> IsUnitarySpace(V1);
true 1
> IsUnitarySpace(V2);
true -1
> IsIsometric(V1,V2);
false
> flag, f := IsSimilar(V1,V2);
> flag;
true
> IsSimilarity(V1,V2,f);
true z^3
```

<a id="function-similaritygroup-modtupfld"></a>
##### `SimilarityGroup(V): ModTupFld -> GrpMat`

The group of similarities of the polar space $V$. This includes degenerate polar spaces as well as polar spaces defined by a quadratic form over a field of characteristic two.

<a id="gramschmidt"></a>
<a id="subsectgs"></a>
#### Gram-Schmidt Normalisation

Suppose that $\beta$ is a bilinear or sesquilinear form on the vector space $V$ and that $e_1$, …, $e_n$ is an ordered basis for $V$. The Gram matrix $J$ of $\beta$ with respect to this basis is $(\beta(e_i,e_j))$. Changing the basis to $e_1A$, …, $e_nA$ where $A$ is an invertible matrix changes the Gram matrix to the congruent matrix $AJA^{\sigma t}$, where $\sigma$ is a field automorphism. (When the form is symmetric or alternating $\sigma$ is the identity.)

For a positive definite inner product on a real vector space it is possible to choose $A$ so that $AJA^t$ is the identity matrix. The algorithm which achieves this is the *Gram–Schmidt process*.

In general it is possible to choose $A$ so that $D = AJA^{\sigma t}$ is almost diagonal; that is, $D$ is a block diagonal matrix where each block is either a $1\times 1$ block or a $2\times 2$ block $\left(\begin{matrix}0&\alpha\\ s\alpha&0\end{matrix}\right)$, where $s$ is $-1$ if the form is alternating.

The following intrinsic uses the algorithm of Wilson [[Wil13b](https://docs.magma-maths.org/references.md#cite-wilson2013)].

<a id="function-gramschmidtpair-algmatelt"></a>
##### `GramSchmidtPair(J): AlgMatElt -> AlgMatElt, AlgMatElt`

Given the matrix $J$ of a reflexive form, apply Wilson’s Gram-Schmidt algorithm to return a pair of matrices $D$ and $A$ such that $AJA' = D$, where $D$ is almost diagonal and $A'$ is either the transposed conjugate of $A$ (when $J$ is hermitian) or the transpose of $A$.

<a id="example-ex-97668f"></a>
##### `Example: Gram-Schmidt for a Hermitian Form (ex-97668f)`

For the case of an hermitian matrix over the Gaussian rationals the algorithm is able to diagonalise the form.

```magma
> F<i> := QuadraticField(-1);
> B := Matrix(F,4,4,[1,0,3-i,2, 0,3,1+i,1+i, 3+i,1-i,0,2, 2,1-i,2,1]);
> B;
[     1      0 -i + 3      2]
[     0      3  i + 1  i + 1]
[ i + 3 -i + 1      0      2]
[     2 -i + 1      2      1]
> D, A := GramSchmidtPair(B);
> D;
[        1         0         0         0]
[        0         3         0         0]
[        0         0     -32/3         0]
[        0         0         0      -5/4]
> A;
[             1              0              0              0]
[             0              1              0              0]
[        -i - 3    1/3*(i - 1)              1              0]
[  1/8*(-i - 4)    1/8*(i - 2) 1/16*(3*i - 7)              1]
```

<a id="example-ex-7c8257"></a>
##### `Example: Gram-Schmidt for an Alternating Form (ex-7c8257)`

Alternating forms cannot be diagonalised.

```magma
> B := Matrix(Rationals(),4,4,[0,0,3,2, 0,0,1,1, -3,-1,0,2, -2,-1,-2,0]);
> B;
[ 0  0  3  2]
[ 0  0  1  1]
[-3 -1  0  2]
[-2 -1 -2  0]
> D, A := GramSchmidtPair(B);
> D;
[ 0  1  0  0]
[-1  0  0  0]
[ 0  0  0  1]
[ 0  0 -1  0]
> A;
[ 1 -2  0  0]
[ 2 -6  1  0]
[-1  3  0  0]
[ 0  0  0  1]
> A*B*Transpose(A) eq D;
true
```

<a id="classical"></a>
<a id="sectclassical"></a>
### Classical Groups

Given the matrix $F$ of a bilinear or sesquilinear form, the functions described in the previous section can be used to construct classical groups which preserve $F$ or preserve $F$ up to a scalar.

<a id="example-ex-1225d3"></a>
#### `Example: Groups Fixing an Alternating Form (ex-1225d3)`

For example the following code constructs the symplectic group $G$ and the conformal symplectic group $C$ preserving the non-degenerate alternating form $F$.

```magma
> F := Matrix(GF(5),4,4,[0,-1,-1,1, 1,0,1,-1, 1,-1,0,1, -1,1,-1,0]);
> V := SymplecticSpace(F);
> G := IsometryGroup(V);
> C := SimilarityGroup(V);
> f1, _ := IsIsomorphic(G,Sp(4,5));
> f2, _ := IsIsomorphic(C,CSp(4,5));
> f1, f2;
true true
```

If only the symplectic group is needed this can be obtained on one line

```magma
> G := IsometryGroup(SymplecticSpace(F));
```

Similar code can be used to construct the orthogonal group and the conformal orthogonal group preserving a quadratic form or the unitary group and conformal unitary group preserving an hermitian form.

However, to construct a group strictly between the isometry group and the similarity group of a form some more work is needed. The following example illustrates how this may be carried out for an hermitian form.

<a id="example-ex-e06cca"></a>
#### `Example: Special Unitary Group of a Hermitian Form (ex-e06cca)`

This example constructs the group of unitary matrices of determinant 1 which preserve an hermitian form $F$. The first step is to define a Magma function which takes the form as its only argument. The base field and dimension of $F$ can be recovered from $F$ itself and then an isometry $\varphi$ is constructed from the unitary space of the standard form to the unitary space of $F$. This is used to transform the generators of a standard copy of the special unitary group to the group preserving the form.

```magma
> specialUnitaryGrp := function(F)
>   K := BaseRing(F); n := NumberOfRows(F);
>   J, sigma := StandardHermitianForm(n,K);
>   V := UnitarySpace(F,sigma);
>   S := UnitarySpace(J,sigma);
>   flag, phi := IsIsometric(S,V);
>   assert flag;
>   T := Matrix(K,n,n,[phi(S.i) : i in [1..n]]);
>   H := SpecialUnitaryGroup(n,K);
>   return sub<IsometryGroup(V) | [T^-1*H.i*T : i in [1..NumberOfGenerators(H)]]>;
> end function;
```

To complete the example we define an hermitian form $F$ and then use the above function to find the special unitary group that preserves $F$.

```magma
> K<z> := GF(9);
> F := Matrix(K,4,4,[1,z^7,z^6,2, z^5,2,z^6,z^6,  z^2,z^2,1,z^3, 2,z^2,z,0]);
> G := specialUnitaryGrp(F);
> flag where flag is IsIsomorphic(G,SU(4,3));
true
```

<a id="liealg"></a>
<a id="sectliealg"></a>
### Lie Algebras and Bilinear Forms

If $J$ is the matrix of a bilinear form, the Lie algebra of derivations of $J$ consists of the matrices $X$ such that $XJ + JX^\mathrm{tr}= 0$.

<a id="function-derivationalgebra-algmatelt"></a>
#### `DerivationAlgebra(J): AlgMatElt -> AlgLie`

```magma
Rep  : MonStgElt                    Default: "Sparse"
Check: BoolElt                      Default: false
```

The Lie algebra of derivations of the bilinear form with matrix $J$. The possible values for `Rep` are `"Dense"`, `"Sparse"`, and `"Partial"` with the default being `"Sparse"`.

<a id="example-ex-3caa04"></a>
#### `Example: Lie Algebra of Type C3 (ex-3caa04)`

Construct the Lie algebra preserving the standard alternating form of rank 6 over the field of 7 elements and check that it is a simple algebra of type $C_3$.

```magma
> J := StandardAlternatingForm(6,7);
> L := DerivationAlgebra(J);
> IsSimple(L);
true
> SemisimpleType(L);
C3
```

<a id="example-ex-196405"></a>
#### `Example: G2 Ideal in Characteristic 2 (ex-196405)`

Over a field of characteristic 2, the Lie algebra of an alternating form is no longer simple. In this example the Lie algebra $L$ of the standard alternating form of rank 6 over ${\bf F}_{8}$ is of symplectic type $C_3$ but has an ideal $I$ of type $G_2$. The dimension of the centre of $L$ is 1 and so the ideal $I$ will appear as either the first or second composition factor.

```magma
> J := StandardAlternatingForm(6,8);
> L := DerivationAlgebra(J);
> SemisimpleType(L);
C3
> Dimension(Centre(L));
1
> CF := CompositionFactors(L);
> CF;
[
    Lie Algebra of dimension 1 with base ring GF(2^3),
    Lie Algebra of dimension 14 with base ring GF(2^3),
    Lie Algebra of dimension 1 with base ring GF(2^3),
    Lie Algebra of dimension 1 with base ring GF(2^3),
    Lie Algebra of dimension 1 with base ring GF(2^3),
    Lie Algebra of dimension 1 with base ring GF(2^3),
    Lie Algebra of dimension 1 with base ring GF(2^3),
    Lie Algebra of dimension 1 with base ring GF(2^3)
]
> exists(I){I : I in CF | Dimension(I) eq 14 };
true
> IsSimple(I);
true
> SemisimpleType(I);
G2
```

Another way to construct a Lie algebra from an alternating form $\beta$ with matrix $J$ defined on a vector space $V$ of dimension $n$ over a field $F$ is to set $L = V\oplus F$ and define the multiplication by $[e_i,e_j] = \beta(e_i,e_j)$, where $e_1$, $e_2$, …, $e_n$ is a basis for $V$. (All other structure constants are 0.) This is the (generalised) Heisenberg algebra.

<a id="function-heisenbergalgebra-algmatelt"></a>
#### `HeisenbergAlgebra(J): AlgMatElt -> AlgLie`

```magma
Rep  : MonStgElt                    Default: "Sparse"
Check: BoolElt                      Default: false
```

The nilpotent Lie algebra whose structure constants are obtained from the alternating form with matrix $J$ as described above. The possible values for `Rep` are `"Dense"`, `"Sparse"`, and `"Partial"` with the default being `"Sparse"`.

<a id="example-ex-aa6842"></a>
#### `Example: Heisenberg Algebra of a Form (ex-aa6842)`

Continuing the previous example we construct an explicit isomorphism between the quotient of $L$ by its $G_2$ ideal and the Heisenberg algebra of the form.

```magma
> Q := CS[1];
> W := L/Q;
> W;
Lie Algebra of dimension 7 with base ring GF(2^3)
> Z := Centre(W);
> z := Z.1;
> exists(u1,v1){ <u,v> : u,v in W | u*v ne 0 and u*v eq z };
true
> W1 := Centraliser(W,sub<W|u1,v1>);
true
> exists(u2,v2){ <u,v> : u,v in W1 | u*v ne 0 and u*v eq z };
true
> W2:= Centraliser(W1,sub<W1|u2,v2>);
> exists(u3,v3){ <u,v> : u,v in W2 | u*v ne 0 and u*v eq z };
> H := HeisenbergAlgebra(J);
> f := hom< H -> W | u1,u2,u3,v3,v2,v1,z >;
> forall{ <u,v> : u,v in Basis(H) | f(u*v) eq f(u)*f(v) };
true
> Kernel(f);
Lie Algebra of dimension 0 with base ring GF(2^3)
> Image(f) eq W;
true
```

<a id="wallform"></a>
<a id="sectwall"></a>
### Wall Forms

Given an isometry $f$ of a quadratic, symplectic, or unitary space $V$ with bilinear or sesquilinear form $\beta$, the Wall form of $f$ is the form $\theta$ defined on the image $I$ of $1-f$ by $\theta(u,v) = \beta(w,v)$, where $u = w(1-f)$. In general, the Wall form is not reflexive.

<a id="function-wallform-modtupfld-mtrx"></a>
#### `WallForm(V, f): ModTupFld, Mtrx -> ModTupFld, Map`

The space of the Wall form of the isometry $f$ and its embedding in $V$.

<a id="function-wallisometry-modtupfld-modtupfld-map"></a>
#### `WallIsometry(V, I, mu): ModTupFld, ModTupFld, Map -> Mtrx`

The inverse of `WallForm`. This is an isometry corresponding to the embedding $\mu : I \to V$, where $V$ is a quadratic, symplectic, or unitary space.

<a id="function-walldecomposition-modtupfld-mtrx"></a>
#### `WallDecomposition(V, f): ModTupFld, Mtrx -> Mtrx, Mtrx`

An isometry $f$ of a quadratic or symplectic space $V$ is *Wall-regular* if the restriction of $1-f$ to the image of $1-f$ is invertible. If $f$ is any isometry of $V$ this function returns a Wall-regular element $f_r$ and a unipotent element $f_u$ such that $f = f_rf_u = f_u f_r$.

<a id="function-semiorthogonalbasis-modtupfld"></a>
#### `SemiOrthogonalBasis(V): ModTupFld -> SeqEnum`

If $V$ is a vector space with a bilinear form $\beta$, a basis $e_1$, $e_2$, …, $e_n$ for $V$ is semi-orthogonal if $\beta(e_i,e_j) = 0$ for $i < j$. This function returns a semi-orthogonal basis with respect to the non-degenerate, non-alternating form attached to $V$. If the base field is ${\bf F}_{2}$, the form should be symmetric.

<a id="function-generalisedwallform-modtupfld-mtrx"></a>
#### `GeneralisedWallForm(V, f): ModTupFld, Mtrx -> ModTupFld, Map`

This function returns the space of the generalised Wall form of the similarity $f$ and its embedding in the quadratic space $V$. Suppose that the quadratic form $Q$ of $V$ is nondegenerate and let $\beta$ be its polar form. Then $Q(vf) = \eta Q(v)$ for some $\eta$. Suppose that $\eta = \zeta^2$ and let $V(f,\zeta)$ denote the $\zeta$-eigenspace of $f$. The generalised Wall form $\theta$ of $f$ is defined on the orthogonal complement of $V(f,\zeta)$ by $\theta(u,v) = \beta(w,v)$, where $u = \zeta w - wf$.

<a id="invform"></a>
<a id="sectinvform"></a>
### Invariant Forms

Given a group $G$ which acts on a vector space $V$ over a finite field $F$, the space of all $G$-invariant bilinear forms is isomorphic to ${\operatorname{Hom}}_G(V,V^*)$, where $V^*$ is the dual space of $V$. The isomorphism associates the form $\beta$ to $\theta\in{\operatorname{Hom}}_G(V,V^*)$, where $\beta(u,v) = \langle v, u\theta \rangle$ and where $\langle v, \varphi \rangle$ denotes the action of $\varphi$ on $v$. If $v_1$, $v_2$, …, $v_n$ is a basis for $V$ with dual basis $\omega_1$, $\omega_2$, …, $\omega_n$, the matrix of $\theta$ with respect to these bases is $J = (\beta(e_i,e_j))$.

A linear transformation with matrix $A$ preserves the form if and only if $AJA^{\hbox{tr}} = J$.

If the characteristic of the field is not 2, then $J = {1\over2}(J+J^{\hbox{tr}}) + {1\over2}(J-J^{\hbox{tr}})$. Therefore, in this case, every $G$-invariant form is the sum of a $G$-invariant symmetric form and a $G$-invariant alternating form. If the characteristic of the field is 2, every alternating form is symmetric. Thus in this case the space of $G$-invariant alternating forms is a subspace of the space of $G$-invariant symmetric forms. If the $G$-module is irreducible these two spaces coincide.

<a id="function-invariantbilinearforms-grpmat"></a>
#### `InvariantBilinearForms(G): GrpMat -> SeqEnum[AlgMatElt], SeqEnum[AlgMatElt]`

Given a matrix group $G$ this function returns two sequences: a basis for the space of $G$-invariant symmetric forms and a basis for the space of $G$-invariant alternating forms.

<a id="example-ex-246b09"></a>
#### `Example: Invariant Form of a Reducible Group (ex-246b09)`

In this example the group $G$ is reducible but (up to a scalar multiple) there is a unique $G$-invariant bilinear form.

```magma
> F<x> := GF(25);
> G := MatrixGroup< 4, F |
>    [ 1, 0, 0, 0,  0, 1, 0, 0,  0, x^14, 1, 0,  0, 0, 0, 1 ],
>    [ 3, x^23, x^20, x^10,  2, 3, 0, x^13,  4, x^10, x^13, x^23,
>      x^5, x^11, x, x^17 ] >;
> IsIrreducible(G);
false
> InvariantBilinearForms(G);
[]
[
    [   0    0    0    1]
    [   0    0    1    0]
    [   0    4    0    0]
    [   4    0    0    0]
]
```

If $G$ acts irreducibly on a vector space $V$ of dimension $n$ over a (finite) field $F$ and if $\theta_0 : V\to V^*$ is a $G$-invariant isomorphism, then $D \to {\operatorname{Hom}}_G(V,V^*) : \theta \mapsto \theta\theta_0$ is an isomorphism of vector spaces, where $D = {\operatorname{End}}_G(V)$. The algebra $D$ is a division ring and hence a field (since $F$ is finite). Thus $V$ becomes a vector space of dimension $m$ over $D$, where $n = m|D:F|$ and $G$ is isomorphic to a subgroup of ${\operatorname{GL}}(m,D)$.

<a id="example-ex-8559f1"></a>
#### `Example: Forms of a Non-Absolutely Irreducible Group (ex-8559f1)`

If $G$ acts irreducibly on $V$, the spaces of symmetric and alternating $G$-invariant forms are isomorphic (as vector spaces) to subfields of ${\operatorname{End}}_G(V)$ and therefore their dimensions are either 0 or divide $\dim_F(V)$.

```magma
> F<a> := GF(25);
> G := MatrixGroup< 4, F |
>   [ a^10, a^21, a^4, 4,
>     a^16, 4, a^9, a^8,
>     a^20, 4, 4, a^13,
>     0, a^2, a^11, a ] >;
> IsIrreducible(G), #G;
true 626
> sym, alt := InvariantBilinearForms(G);
> #sym,#alt;
2 2
```

If the characteristic of the field is not two and if $J$ is a symmetric bilinear form there is a unique upper triangular matrix $Q$ such that $J = Q + Q^{\hbox{tr}}$.

On the other hand, if the characteristic is two and $J$ is alternating, the upper triangular matrices $Q$ such that $J = Q + Q^{\hbox{tr}}$ form an affine space of dimension $\dim V$.

Suppose that the characteristic is two. If $G$ preserves a symmetric bilinear form which is not alternating, then $G$ is reducible. Conversely, if $G$ is irreducible and if $J$ is the matrix of a symmetric form preserved by $G$, then the form must be alternating and there is a unique $G$-invariant quadratic form $Q$ such that $J = Q + Q^{\hbox{tr}}$.

<a id="function-invariantquadraticforms-grpmat"></a>
#### `InvariantQuadraticForms(G): GrpMat -> SeqEnum[AlgMatElt]`

A basis for the space of quadratic forms preserved by the irreducible matrix group $G$.

<a id="example-ex-e24e49"></a>
#### `Example: Invariant Quadratic Forms of a Cyclic Group (ex-e24e49)`

In the following example the quadratic forms which are invariant under the action of a cyclic group $H$ of order 13 form a vector space of dimension 3 over ${\bf F}_{4}$.

```magma
> F<z> := GF(4);
> H := MatrixGroup<6,F |
>     [ z, 0, z^2, z, z, 1,
>       1, z, 0, z, z, z,
>       0, z^2, z, 1, z^2, z^2,
>       z, 1, z, 1, 1, 0,
>       1, z^2, z, z, 0, 1,
>       1, 0, 1, 0, z^2, 1 ] >;
>
> InvariantQuadraticForms(H);
[
    [  1   1   0   1   0   0]
    [  0   0   1 z^2 z^2   z]
    [  0   0   1   0 z^2   z]
    [  0   0   0   0   0   z]
    [  0   0   0   0 z^2   z]
    [  0   0   0   0   0 z^2],

    [  1   0   1 z^2   1   0]
    [  0   z   1   1   1   z]
    [  0   0   z   0   1   0]
    [  0   0   0 z^2 z^2 z^2]
    [  0   0   0   0 z^2   1]
    [  0   0   0   0   0   1],

    [  0   0   0   0   0   1]
    [  0   0   0   0   1   0]
    [  0   0   1   1   0   0]
    [  0   0   0   z   0   0]
    [  0   0   0   0   0   0]
    [  0   0   0   0   0   0]
]
```

Given a group $G$ which acts on a vector space $V$ over a finite field $F$ with an automorphism $F \to F :a \mapsto \overline{a}$ of order $2$, the space of $G$-invariant sesquilinear forms is isomorphic to the space of $G$-invariant semilinear maps from $V$ to $V^*$; equivalently it is isomorphic to ${\operatorname{Hom}}_G(V, \overline{V}^*)$, where $\overline{V}^*$ is the semilinear dual of $V$, namely the space of all semilinear maps from $V$ to $F$.

If $\theta\in {\operatorname{Hom}}_G(V,\overline{V}^*)$, the corresponding sesquilinear form $\beta$ is defined by $\beta(u,v) = \langle v,u\theta\rangle$ where, as before, $\langle v, \varphi \rangle$ denotes the action of $\varphi$ on $v$.

<a id="function-semilineardual-modgrp-map"></a>
#### `SemilinearDual(M, mu): ModGrp, Map -> ModGrp`

The semilinear dual of the $G$-module $M$ with respect to the field automorphism `mu`.

<a id="function-invariantsesquilinearforms-grpmat"></a>
#### `InvariantSesquilinearForms(G): GrpMat -> SeqEnum[AlgMatElt]`

A basis for the space of *hermitian* forms preserved by the matrix group $G$.

<a id="example-ex-17b876"></a>
#### `Example: Invariant Hermitian Forms (ex-17b876)`

Let $F_0$ be the fixed field of the involution. The set $\cal H$ of $G$-invariant hermitian forms is a vector space over $F_0$ and if the characteristic of $F$ is not 2, then ${\operatorname{Hom}}_G(V,\overline{V}^*) \simeq {\cal H}\otimes_{F_0} F$.

```magma
> F<x> := GF(5,2);
> mu := hom< F->F | x :-> x^5 >;
> H := MatrixGroup< 5, F |
>    [ 0, x^3, 0, 1, x^9, x^8, 1, 0, x^11, x^7, x^20, x^16, 1,
>     x^11, x^3, x^21, 4, 1, x^3, x^23, x^4, x^3, x, x^3, 2 ] >;
> M := GModule(H);
> D := SemilinearDual(M,mu);
> E := AHom(M,D);
> Dimension(E);
5
> herm := InvariantSesquilinearForms(H);
> #herm;
5
```

<a id="example-ex-9dd62c"></a>
#### `Example: Preserving Bilinear and Sesquilinear Forms (ex-9dd62c)`

If an irreducible group preserves both a bilinear and a sesquilinear form then it is realisable over a subfield of its base field. Conversely, this observation can be used to construct an example:

```magma
> F<x> := GF(81);
> H := MatrixGroup< 4, F | [ChangeRing(g,F) : g in Generators(Sp(4,9))]>;
> InvariantBilinearForms(H);
[]
[
    [   0    0    0    1]
    [   0    0    1    0]
    [   0    2    0    0]
    [   2    0    0    0]
]
> InvariantSesquilinearForms(H);
[
    [   0    0    0 x^45]
    [   0    0 x^45    0]
    [   0  x^5    0    0]
    [ x^5    0    0    0]
]
```

<a id="function-invariantformbases-grpmat"></a>
#### `InvariantFormBases(G): GrpMat -> SeqEnum[AlgMatElt], SeqEnum[AlgMatElt], SeqEnum[AlgMatElt], SeqEnum[AlgMatElt]`

This function returns four sequences: bases for the spaces of symmetric, alternating, hermitian, and quadratic forms preserved by the matrix group $G$.

<a id="semiinvform"></a>
<a id="subsectsemiinvform"></a>
#### Semi-invariant Forms

Given a vector space $V$ over a finite field $F$ and a group $G$ which acts on $V$, a bilinear form $\beta : V\times V \to F$ is *semi-invariant* if for all $g\in G$ there is a scalar $\lambda(g)$ such that $\beta(ug,vg) = \lambda(g)\beta(u,v)$ for all $u,v\in V$. The function $\lambda : G \to F^\times$ is a homomorphism and its kernel contains the derived group of $G$. The *twisted dual* $V^*_\lambda$ of the $G$-module $V$ is the dual space of $V$ with $G$-action given by $\langle v, \varphi g\rangle = \lambda(g)\langle vg^{-1},\varphi\rangle$; thus if $A$ is the matrix of $g$ acting on $V$ the matrix of the action on $V_\lambda^*$ with respect to the dual basis is $\lambda(g)A^{-\hbox{tr}}$.

The space of all semi-invariant bilinear forms is isomorphic to ${\operatorname{Hom}}_G(V,V_\lambda^*)$. The isomorphism associates the form $\beta$ to $\theta\in{\operatorname{Hom}}_G(V,V_\lambda^*)$, where $\beta(u,v) = \langle v, u\theta \rangle$.

If $\beta$ is a bilinear form with matrix $J$, then the linear transformation $g$ with matrix $A$ preserves the form up to multiplication by $\lambda(g)$ if and only if $AJA^{\hbox{tr}} = \lambda(g)J$.

<a id="function-twisteddual-modgrp-map"></a>
##### `TwistedDual(M, lambda): ModGrp, Map -> ModGrp`

The twisted dual of the $G$-module M with respect to the linear character `lambda`.

<a id="function-semiinvariantbilinearforms-grpmat"></a>
##### `SemiInvariantBilinearForms(G): GrpMat -> SeqEnum`

A sequence of triples $\langle L, S, A\rangle$ where $L$ is a sequence of field elements (one for each generator) which define a homomorphism from the matrix group $G$ to its base field and $S$ and $A$ are bases for the spaces of symmetric and alternating forms preserved by $G$ (up to multiplication by scalars).

<a id="function-semiinvariantquadraticforms-grpmat"></a>
##### `SemiInvariantQuadraticForms(G): GrpMat -> SeqEnum`

A sequence of pairs $\langle L, Q\rangle$ where $L$ is a sequence of field elements (one for each generator) which define a homomorphism from the matrix group $G$ to its base field and $Q$ is a basis for the space of quadratic forms preserved by $G$ (up to multiplication by scalars).

<a id="function-twistedsemilineardual-modgrp-map-map"></a>
##### `TwistedSemilinearDual(M, lambda, mu): ModGrp, Map, Map -> ModGrp`

The twisted semilinear dual of the $G$-module $M$ with respect to the linear character $\lambda$ and the field automorphism $\mu$.

<a id="function-semiinvariantsesquilinearforms-grpmat"></a>
##### `SemiInvariantSesquilinearForms(G): GrpMat -> SeqEnum`

A sequence of pairs $\langle L, H\rangle$ where $L$ is a sequence of field elements (one for each generator) which define a homomorphism from the matrix group $G$ to the field $F_0$, where the base field of $G$ is a quadratic extension of $F_0$, and $H$ is a basis for the space of hermitian forms preserved by $G$ (up to multiplication by scalars).

<a id="example-ex-f6ba6b"></a>
##### `Example: Semi-Invariant Forms of a Normal Subgroup (ex-f6ba6b)`

In this example $H$ is a normal subgroup of the absolutely irreducible group $N$ an $H$ is irreducible but not absolutely irreducible.

```magma
> F<x> := GF(3,2);
> H := MatrixGroup<3,F|
>   [x^2,x^7,x^3, x,0,1, x^3,x^6,2],
>   [x^3, 0, 0, 0, x^3, 0, 0, 0, x^3 ] >;
> N := MatrixGroup<3,F|H.1,H.2,[x^5,x^5,2, 0,x^2,x^6, x^7,x^7,2]>;
> IsNormal(N,H);
true
> IsIrreducible(H), IsAbsolutelyIrreducible(H);
true false
> IsIrreducible(N), IsAbsolutelyIrreducible(N);
true true
> SemiInvariantSesquilinearForms(H);
[
    <[ 1, 2 ],
    [
        [  1   x   x]
        [x^3   0 x^3]
        [x^3   x   1],

        [  0 x^3   x]
        [  x   0 x^5]
        [x^3 x^7   0],

        [  0   0   1]
        [  0   1   0]
        [  1   0   0]
    ]>
]
> SemiInvariantSesquilinearForms(N);
[
    <[ 1, 2, 1 ],
    [
        [  0   0   1]
        [  0   1   0]
        [  1   0   0]
    ]>
]
```

### Polar Spaces More Generally

In V2.29 (September 2025), in order to support more functionality for polar spaces, a category `SpcPlr` has been added, and one can create a polar spaces also in this category.

#### Creation of PolarSpaces

<a id="function-ambientpolarspace-algmatelt"></a>
##### `AmbientPolarSpace(J): AlgMatElt -> SpcPlr`

<a id="function-ambientpolarspace-algmatelt-fldaut"></a>
##### `AmbientPolarSpace(J, a): AlgMatElt, FldAut -> SpcPlr`

Builds a polar space with respect to the matrix $J$ and the field automorphism $a$.

<a id="function-polarspace-latnf"></a>
##### `PolarSpace(L): LatNF -> SpcPlr`

<a id="function-polarspace-lat"></a>
##### `PolarSpace(L): Lat -> SpcPlr`

<a id="function-ambientspace-latnf"></a>
##### `AmbientSpace(L): LatNF -> SpcPlr`

The polar space associated to the lattice $L$.

<a id="function-changering-spcplr-rng"></a>
##### `ChangeRing(V, R): SpcPlr, Rng -> SpcPlr`

The polar space obtained from $V$ by base change to $R$.

#### Properties of Polar Spaces

<a id="function-basefield-spcplr"></a>
##### `BaseField(V): SpcPlr -> Fld`

<a id="function-basering-spcplr"></a>
##### `BaseRing(V): SpcPlr -> Fld`

<a id="function-coefficientfield-spcplr"></a>
##### `CoefficientField(V): SpcPlr -> Fld`

<a id="function-coefficientring-spcplr"></a>
##### `CoefficientRing(V): SpcPlr -> Fld`

The field over which $V$ is defined.

<a id="function-vectorspace-spcplr"></a>
##### `VectorSpace(V): SpcPlr -> ModTupFld`

<a id="function-kspace-spcplr"></a>
##### `KSpace(V): SpcPlr -> ModTupFld`

The underlying vector space.

<a id="function-dimension-spcplr"></a>
##### `Dimension(V): SpcPlr -> RngIntElt`

The dimension of $V$.

<a id="function-innerform-spcplr"></a>
##### `InnerForm(V): SpcPlr -> AlgMatElt`

The inner form associated to $V$.

<a id="function-involution-spcplr"></a>
##### `Involution(V): SpcPlr -> FldAut`

The involution with respect to which $V$ is hermitian or skew-hermitian.

<a id="function-spacetype-spcplr"></a>
##### `SpaceType(V): SpcPlr -> MonStgElt`

The type of the polar space $V$, returned as a string.

<a id="function-diagonal-spcplr"></a>
##### `Diagonal(V): SpcPlr -> AlgMatElt`

The coefficients of the diagonalized form.

#### Predicates on Polar Spaces

<a id="function-isdefinite-spcplr"></a>
##### `IsDefinite(V): SpcPlr -> BoolElt`

Whether $V$ space is totally positive definite, or totally negative definite.
