From e963cab90e335ac263e8f0fc96e62c3ebc080f80 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Sun, 29 Sep 2024 03:34:25 +0000 Subject: [PATCH] build based on 11bbd58 --- dev/.documenter-siteinfo.json | 2 +- dev/assertions/index.html | 2 +- dev/constructors/index.html | 2 +- dev/direct_sum/index.html | 2 +- dev/euclidean_interface/index.html | 2 +- dev/extending_abstractalgebra/index.html | 2 +- dev/field/index.html | 2 +- dev/field_interface/index.html | 2 +- dev/field_introduction/index.html | 2 +- dev/finfield/index.html | 2 +- dev/fraction/index.html | 2 +- dev/fraction_interface/index.html | 2 +- dev/free_associative_algebra/index.html | 2 +- dev/free_module/index.html | 2 +- dev/function_field/index.html | 2 +- dev/functional_map/index.html | 2 +- dev/ideal/index.html | 2 +- dev/index.html | 2 +- dev/integer/index.html | 2 +- dev/interface_introduction/index.html | 2 +- dev/laurent_mpolynomial/index.html | 2 +- dev/laurent_polynomial/index.html | 2 +- dev/linear_solving/index.html | 2 +- dev/map_cache/index.html | 2 +- dev/map_interface/index.html | 2 +- dev/map_introduction/index.html | 2 +- dev/map_with_inverse/index.html | 2 +- dev/matrix/index.html | 2 +- dev/matrix_algebras/index.html | 2 +- dev/matrix_interface/index.html | 2 +- dev/matrix_introduction/index.html | 2 +- dev/misc/index.html | 2 +- dev/module/index.html | 2 +- dev/module_homomorphism/index.html | 2 +- dev/module_interface/index.html | 2 +- dev/module_introduction/index.html | 2 +- dev/mpoly_interface/index.html | 2 +- dev/mpolynomial/index.html | 2 +- dev/mseries/index.html | 2 +- dev/ncpolynomial/index.html | 2 +- dev/ncring_interface/index.html | 2 +- dev/perm/index.html | 2 +- dev/poly_interface/index.html | 2 +- dev/polynomial/index.html | 2 +- dev/puiseux/index.html | 2 +- dev/quotient_module/index.html | 2 +- dev/rand/index.html | 2 +- dev/rational/index.html | 2 +- dev/real/index.html | 2 +- dev/residue/index.html | 2 +- dev/residue_interface/index.html | 2 +- dev/ring/index.html | 2 +- dev/ring_interface/index.html | 2 +- dev/ring_introduction/index.html | 2 +- dev/series/index.html | 2 +- dev/series_interface/index.html | 2 +- dev/submodule/index.html | 2 +- dev/total_fraction/index.html | 2 +- dev/types/index.html | 2 +- dev/univpolynomial/index.html | 2 +- dev/visualizing_types/index.html | 2 +- dev/ytabs/index.html | 2 +- 62 files changed, 62 insertions(+), 62 deletions(-) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index c2023ef0a..2d96f3afc 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-28T03:34:12","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-29T03:34:11","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/dev/assertions/index.html b/dev/assertions/index.html index c72153241..84cdd5f20 100644 --- a/dev/assertions/index.html +++ b/dev/assertions/index.html @@ -140,4 +140,4 @@ catch e e end 1 -source +source diff --git a/dev/constructors/index.html b/dev/constructors/index.html index 539ab9516..135ad90ad 100644 --- a/dev/constructors/index.html +++ b/dev/constructors/index.html @@ -94,4 +94,4 @@ (AbstractAlgebra.Generic.MPoly{BigInt}[a, b], AbstractAlgebra.Generic.MPoly{BigInt}[x11 x12], AbstractAlgebra.Generic.MPoly{BigInt}[y1, y2], AbstractAlgebra.Generic.MPoly{BigInt}[z]) julia> R, (a, b), x, y, z = polynomial_ring(ZZ, s...) -(Multivariate polynomial ring in 7 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[a, b], AbstractAlgebra.Generic.MPoly{BigInt}[x11 x12], AbstractAlgebra.Generic.MPoly{BigInt}[y1, y2], AbstractAlgebra.Generic.MPoly{BigInt}[z])source +(Multivariate polynomial ring in 7 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[a, b], AbstractAlgebra.Generic.MPoly{BigInt}[x11 x12], AbstractAlgebra.Generic.MPoly{BigInt}[y1, y2], AbstractAlgebra.Generic.MPoly{BigInt}[z])source diff --git a/dev/direct_sum/index.html b/dev/direct_sum/index.html index 6d9142203..c0d36fc08 100644 --- a/dev/direct_sum/index.html +++ b/dev/direct_sum/index.html @@ -96,4 +96,4 @@ julia> psi = ModuleHomomorphism(D, D, [r, r]) Module homomorphism from DirectSumModule over rationals - to DirectSumModule over rationals + to DirectSumModule over rationals diff --git a/dev/euclidean_interface/index.html b/dev/euclidean_interface/index.html index 6e1b03a58..5b0d12a1e 100644 --- a/dev/euclidean_interface/index.html +++ b/dev/euclidean_interface/index.html @@ -1,2 +1,2 @@ -Euclidean Ring Interface · AbstractAlgebra.jl

Euclidean Ring Interface

If a ring provides a meaningful Euclidean structure such that a useful Euclidean remainder can be computed practically, various additional functionality is provided by AbstractAlgebra.jl for those rings. This functionality depends on the following functions existing. An implementation must provide divrem, and the remaining are optional as generic fallbacks exist.

Base.divremMethod
divrem(f::T, g::T) where T <: RingElem

Return a pair q, r consisting of the Euclidean quotient and remainder of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

source
Base.modMethod
mod(f::T, g::T) where T <: RingElem

Return the Euclidean remainder of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

Note

For best compatibility with the internal assumptions made by AbstractAlgebra, the Euclidean remainder function should provide unique representatives for the residue classes; the mod function should satisfy

  1. mod(a_1, b) = mod(a_2, b) if and only if $b$ divides $a_1 - a_2$, and
  2. mod(0, b) = 0.
source
Base.divMethod
div(f::T, g::T) where T <: RingElem

Return the Euclidean quotient of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

source
AbstractAlgebra.mulmodMethod
mulmod(f::T, g::T, m::T) where T <: RingElem

Return mod(f*g, m) but possibly computed more efficiently.

source
Base.powermodMethod
powermod(f::T, e::Int, m::T) where T <: RingElem

Return mod(f^e, m) but possibly computed more efficiently.

source
Base.invmodMethod
invmod(f::T, m::T) where T <: RingElem

Return an inverse of $f$ modulo $m$, meaning that isone(mod(invmod(f,m)*f,m)) returns true.

If such an inverse doesn't exist, a NotInvertibleError should be thrown.

source
AbstractAlgebra.dividesMethod
divides(f::T, g::T) where T <: RingElem

Return a pair, flag, q, where flag is set to true if $g$ divides $f$, in which case q is set to the quotient, or flag is set to false and q is set to zero(f).

source
AbstractAlgebra.removeMethod
remove(f::T, p::T) where T <: RingElem

Return a pair v, q where $p^v$ is the highest power of $p$ dividing $f$ and $q$ is the cofactor after $f$ is divided by this power.

See also valuation, which only returns the valuation.

source
Base.gcdMethod
gcd(a::T, b::T) where T <: RingElem

Return a greatest common divisor of $a$ and $b$, i.e., an element $g$ which is a common divisor of $a$ and $b$, and with the property that any other common divisor of $a$ and $b$ divides $g$.

Note

For best compatibility with the internal assumptions made by AbstractAlgebra, the return is expected to be unit-normalized in such a way that if the return is a unit, that unit should be one.

source
Base.gcdMethod
gcd(f::T, g::T, hs::T...) where T <: RingElem

Return a greatest common divisor of $f$, $g$ and the elements in hs.

source
Base.gcdMethod
gcd(fs::AbstractArray{<:T}) where T <: RingElem

Return a greatest common divisor of the elements in fs. Requires that fs is not empty.

source
Base.lcmMethod
lcm(f::T, g::T) where T <: RingElem

Return a least common multiple of $f$ and $g$, i.e., an element $d$ which is a common multiple of $f$ and $g$, and with the property that any other common multiple of $f$ and $g$ is a multiple of $d$.

source
Base.lcmMethod
lcm(f::T, g::T, hs::T...) where T <: RingElem

Return a least common multiple of $f$, $g$ and the elements in hs.

source
Base.lcmMethod
lcm(fs::AbstractArray{<:T}) where T <: RingElem

Return a least common multiple of the elements in fs. Requires that fs is not empty.

source
Base.gcdxMethod
gcdx(f::T, g::T) where T <: RingElem

Return a triple d, s, t such that $d = gcd(f, g)$ and $d = sf + tg$, with $s$ loosely reduced modulo $g/d$ and $t$ loosely reduced modulo $f/d$.

source
AbstractAlgebra.gcdinvMethod
gcdinv(f::T, g::T) where T <: RingElem

Return a tuple d, s such that $d = gcd(f, g)$ and $s = (f/d)^{-1} \pmod{g/d}$. Note that $d = 1$ iff $f$ is invertible modulo $g$, in which case $s = f^{-1} \pmod{g}$.

source
AbstractAlgebra.crtMethod
crt(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement

Return an element congruent to $r_1$ modulo $m_1$ and $r_2$ modulo $m_2$. If check = true and no solution exists, an error is thrown.

If T is a fixed precision integer type (like Int), the result will be correct if abs(ri) <= abs(mi) and abs(m1 * m2) < typemax(T).

source
AbstractAlgebra.crtMethod
crt(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement

Return an element congruent to $r_i$ modulo $m_i$ for each $i$.

source
AbstractAlgebra.crt_with_lcmMethod
crt_with_lcm(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement

Return a tuple consisting of an element congruent to $r_1$ modulo $m_1$ and $r_2$ modulo $m_2$ and the least common multiple of $m_1$ and $m_2$. If check = true and no solution exists, an error is thrown.

source
AbstractAlgebra.crt_with_lcmMethod
crt_with_lcm(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement

Return a tuple consisting of an element congruent to $r_i$ modulo $m_i$ for each $i$ and the least common multiple of the $m_i$.

source
AbstractAlgebra.coprime_baseFunction
coprime_base(S::Vector{RingElement}) -> Vector{RingElement}

Returns a coprime base for $S$, i.e. the resulting array contains pairwise coprime objects that multiplicatively generate the same set as the input array.

source
AbstractAlgebra.coprime_base_push!Function
coprime_base_push!(S::Vector{RingElem}, a::RingElem) -> Vector{RingElem}

Given an array $S$ of coprime elements, insert a new element, that is, find a coprime base for push(S, a).

source
+Euclidean Ring Interface · AbstractAlgebra.jl

Euclidean Ring Interface

If a ring provides a meaningful Euclidean structure such that a useful Euclidean remainder can be computed practically, various additional functionality is provided by AbstractAlgebra.jl for those rings. This functionality depends on the following functions existing. An implementation must provide divrem, and the remaining are optional as generic fallbacks exist.

Base.divremMethod
divrem(f::T, g::T) where T <: RingElem

Return a pair q, r consisting of the Euclidean quotient and remainder of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

source
Base.modMethod
mod(f::T, g::T) where T <: RingElem

Return the Euclidean remainder of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

Note

For best compatibility with the internal assumptions made by AbstractAlgebra, the Euclidean remainder function should provide unique representatives for the residue classes; the mod function should satisfy

  1. mod(a_1, b) = mod(a_2, b) if and only if $b$ divides $a_1 - a_2$, and
  2. mod(0, b) = 0.
source
Base.divMethod
div(f::T, g::T) where T <: RingElem

Return the Euclidean quotient of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

source
AbstractAlgebra.mulmodMethod
mulmod(f::T, g::T, m::T) where T <: RingElem

Return mod(f*g, m) but possibly computed more efficiently.

source
Base.powermodMethod
powermod(f::T, e::Int, m::T) where T <: RingElem

Return mod(f^e, m) but possibly computed more efficiently.

source
Base.invmodMethod
invmod(f::T, m::T) where T <: RingElem

Return an inverse of $f$ modulo $m$, meaning that isone(mod(invmod(f,m)*f,m)) returns true.

If such an inverse doesn't exist, a NotInvertibleError should be thrown.

source
AbstractAlgebra.dividesMethod
divides(f::T, g::T) where T <: RingElem

Return a pair, flag, q, where flag is set to true if $g$ divides $f$, in which case q is set to the quotient, or flag is set to false and q is set to zero(f).

source
AbstractAlgebra.removeMethod
remove(f::T, p::T) where T <: RingElem

Return a pair v, q where $p^v$ is the highest power of $p$ dividing $f$ and $q$ is the cofactor after $f$ is divided by this power.

See also valuation, which only returns the valuation.

source
Base.gcdMethod
gcd(a::T, b::T) where T <: RingElem

Return a greatest common divisor of $a$ and $b$, i.e., an element $g$ which is a common divisor of $a$ and $b$, and with the property that any other common divisor of $a$ and $b$ divides $g$.

Note

For best compatibility with the internal assumptions made by AbstractAlgebra, the return is expected to be unit-normalized in such a way that if the return is a unit, that unit should be one.

source
Base.gcdMethod
gcd(f::T, g::T, hs::T...) where T <: RingElem

Return a greatest common divisor of $f$, $g$ and the elements in hs.

source
Base.gcdMethod
gcd(fs::AbstractArray{<:T}) where T <: RingElem

Return a greatest common divisor of the elements in fs. Requires that fs is not empty.

source
Base.lcmMethod
lcm(f::T, g::T) where T <: RingElem

Return a least common multiple of $f$ and $g$, i.e., an element $d$ which is a common multiple of $f$ and $g$, and with the property that any other common multiple of $f$ and $g$ is a multiple of $d$.

source
Base.lcmMethod
lcm(f::T, g::T, hs::T...) where T <: RingElem

Return a least common multiple of $f$, $g$ and the elements in hs.

source
Base.lcmMethod
lcm(fs::AbstractArray{<:T}) where T <: RingElem

Return a least common multiple of the elements in fs. Requires that fs is not empty.

source
Base.gcdxMethod
gcdx(f::T, g::T) where T <: RingElem

Return a triple d, s, t such that $d = gcd(f, g)$ and $d = sf + tg$, with $s$ loosely reduced modulo $g/d$ and $t$ loosely reduced modulo $f/d$.

source
AbstractAlgebra.gcdinvMethod
gcdinv(f::T, g::T) where T <: RingElem

Return a tuple d, s such that $d = gcd(f, g)$ and $s = (f/d)^{-1} \pmod{g/d}$. Note that $d = 1$ iff $f$ is invertible modulo $g$, in which case $s = f^{-1} \pmod{g}$.

source
AbstractAlgebra.crtMethod
crt(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement

Return an element congruent to $r_1$ modulo $m_1$ and $r_2$ modulo $m_2$. If check = true and no solution exists, an error is thrown.

If T is a fixed precision integer type (like Int), the result will be correct if abs(ri) <= abs(mi) and abs(m1 * m2) < typemax(T).

source
AbstractAlgebra.crtMethod
crt(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement

Return an element congruent to $r_i$ modulo $m_i$ for each $i$.

source
AbstractAlgebra.crt_with_lcmMethod
crt_with_lcm(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement

Return a tuple consisting of an element congruent to $r_1$ modulo $m_1$ and $r_2$ modulo $m_2$ and the least common multiple of $m_1$ and $m_2$. If check = true and no solution exists, an error is thrown.

source
AbstractAlgebra.crt_with_lcmMethod
crt_with_lcm(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement

Return a tuple consisting of an element congruent to $r_i$ modulo $m_i$ for each $i$ and the least common multiple of the $m_i$.

source
AbstractAlgebra.coprime_baseFunction
coprime_base(S::Vector{RingElement}) -> Vector{RingElement}

Returns a coprime base for $S$, i.e. the resulting array contains pairwise coprime objects that multiplicatively generate the same set as the input array.

source
AbstractAlgebra.coprime_base_push!Function
coprime_base_push!(S::Vector{RingElem}, a::RingElem) -> Vector{RingElem}

Given an array $S$ of coprime elements, insert a new element, that is, find a coprime base for push(S, a).

source
diff --git a/dev/extending_abstractalgebra/index.html b/dev/extending_abstractalgebra/index.html index 8693eb1dd..baa757930 100644 --- a/dev/extending_abstractalgebra/index.html +++ b/dev/extending_abstractalgebra/index.html @@ -107,4 +107,4 @@ (false, true, true) julia> is_unit(ZZ(-1)), is_unit(ZZ(4)) -(true, false)source

With the same logic as earlier, groups only need to extend one of the methods isone and iszero.

+(true, false)source

With the same logic as earlier, groups only need to extend one of the methods isone and iszero.

diff --git a/dev/field/index.html b/dev/field/index.html index 244aff649..bbcbf2160 100644 --- a/dev/field/index.html +++ b/dev/field/index.html @@ -1,4 +1,4 @@ Field functionality · AbstractAlgebra.jl

Field functionality

Abstract types for rings

All field types in AbstractAlgebra belong to the Field abstract type and field elements belong to the FieldElem abstract type.

As Julia types cannot belong to our FieldElem type hierarchy, we also provide the union type FieldElement which includes FieldElem in union with the Julia types Rational and AbstractFloat.

Note that

Field <: Ring
 FieldElem <: RingElem
-FieldElement <: RingElement

Of course all Ring functionality is available for AbstractAlgebra fields and their elements.

Functions for types and parents of fields

characteristic(R::MyParent)

Return the characteristic of the field. If the characteristic is not known, an exception is raised.

Basic functions

is_unit(f::MyElem)

Return true if the given element is invertible, i.e. nonzero in the field.

+FieldElement <: RingElement

Of course all Ring functionality is available for AbstractAlgebra fields and their elements.

Functions for types and parents of fields

characteristic(R::MyParent)

Return the characteristic of the field. If the characteristic is not known, an exception is raised.

Basic functions

is_unit(f::MyElem)

Return true if the given element is invertible, i.e. nonzero in the field.

diff --git a/dev/field_interface/index.html b/dev/field_interface/index.html index a579d30bd..091e2b889 100644 --- a/dev/field_interface/index.html +++ b/dev/field_interface/index.html @@ -1,2 +1,2 @@ -Field Interface · AbstractAlgebra.jl

Field Interface

AbstractAlgebra.jl generic code makes use of a standardised set of functions which it expects to be implemented for all fields. Here we document this interface. All libraries which want to make use of the generic capabilities of AbstractAlgebra.jl must supply all of the required functionality for their fields.

Types

Most fields must supply two types:

  • a type for the parent object (representing the field itself)
  • a type for elements of that field

For example, the generic fraction field type in AbstractAlgebra.jl provides two types in generic/GenericTypes.jl:

  • Generic.FracField{T} for the parent objects
  • Generic.FracFieldElem{T} for the actual fractions

The parent type must belong to Field and the element type must belong to FieldElem. Of course, the types may belong to these abstract types transitively.

For parameterised fields, we advise that the types of both the parent objects and element objects to be parameterised by the types of the elements of the base ring.

There can be variations on this theme: e.g. in some areas of mathematics there is a notion of a coefficient domain, in which case it may make sense to parameterise all types by the type of elements of this coefficient domain. But note that this may have implications for the ad hoc operators one might like to explicitly implement.

FieldElement type union

Because of its lack of multiple inheritance, Julia does not allow Julia Base types to belong to FieldElem. To allow us to work equally with AbstractAlgebra and Julia types that represent elements of fields we define a union type FieldElement in src/julia/JuliaTypes.

So far, in addition to FieldElem the union type FieldElement includes the Julia types Rational and AbstractFloat.

Most of the generic code in AbstractAlgebra makes use of the union type FieldElement instead of FieldElem so that the generic functions also accept the Julia Base field types.

Note

One must be careful when defining ad hoc binary operations for field element types. It is often necessary to define separate versions of the functions for FieldElem then for each of the Julia types separately in order to avoid ambiguity warnings.

Note that even though FieldElement is a union type we still have the following inclusion

FieldElement <: RingElement

Parent object caches

In many cases, it is desirable to have only one object in the system to represent each field. This means that if the same field is constructed twice, elements of the two fields will be compatible as far as arithmetic is concerned.

In order to facilitate this, global caches of fields are stored in AbstractAlgebra.jl, usually implemented using dictionaries. For example, the Generic.FracField parent objects are looked up in a dictionary FracDict to see if they have been previously defined.

Whether these global caches are provided or not, depends on both mathematical and algorithmic considerations. E.g. in the case of number fields, it isn't desirable to identify all number fields with the same defining polynomial, as they may be considered with distinct embeddings into one another. In other cases, identifying whether two fields are the same may be prohibitively expensive. Generally, it may only make sense algorithmically to identify two fields if they were constructed from identical data.

If a global cache is provided, it must be optionally possible to construct the parent objects without caching. This is done by passing a boolean value cached to the inner constructor of the parent object. See generic/GenericTypes.jl for examples of how to construct and handle such caches.

Required functions for all fields

In the following, we list all the functions that are required to be provided for fields in AbstractAlgebra.jl or by external libraries wanting to use AbstractAlgebra.jl.

We give this interface for fictitious types MyParent for the type of the field parent object R and MyElem for the type of the elements of the field.

Note

Generic functions in AbstractAlgebra.jl may not rely on the existence of functions that are not documented here. If they do, those functions will only be available for fields that implement that additional functionality, and should be documented as such.

In the first place, all fields are rings and therefore any field type must implement all of the Ring interface. The functionality below is in addition to this basic functionality.

Data type and parent object methods

characteristic(R::MyParent)

Return the characteristic of the field. If the characteristic is not known, an exception is raised.

Basic manipulation of rings and elements

is_unit(f::MyElem)

Return true if the given element is invertible, i.e. nonzero in the field.

+Field Interface · AbstractAlgebra.jl

Field Interface

AbstractAlgebra.jl generic code makes use of a standardised set of functions which it expects to be implemented for all fields. Here we document this interface. All libraries which want to make use of the generic capabilities of AbstractAlgebra.jl must supply all of the required functionality for their fields.

Types

Most fields must supply two types:

  • a type for the parent object (representing the field itself)
  • a type for elements of that field

For example, the generic fraction field type in AbstractAlgebra.jl provides two types in generic/GenericTypes.jl:

  • Generic.FracField{T} for the parent objects
  • Generic.FracFieldElem{T} for the actual fractions

The parent type must belong to Field and the element type must belong to FieldElem. Of course, the types may belong to these abstract types transitively.

For parameterised fields, we advise that the types of both the parent objects and element objects to be parameterised by the types of the elements of the base ring.

There can be variations on this theme: e.g. in some areas of mathematics there is a notion of a coefficient domain, in which case it may make sense to parameterise all types by the type of elements of this coefficient domain. But note that this may have implications for the ad hoc operators one might like to explicitly implement.

FieldElement type union

Because of its lack of multiple inheritance, Julia does not allow Julia Base types to belong to FieldElem. To allow us to work equally with AbstractAlgebra and Julia types that represent elements of fields we define a union type FieldElement in src/julia/JuliaTypes.

So far, in addition to FieldElem the union type FieldElement includes the Julia types Rational and AbstractFloat.

Most of the generic code in AbstractAlgebra makes use of the union type FieldElement instead of FieldElem so that the generic functions also accept the Julia Base field types.

Note

One must be careful when defining ad hoc binary operations for field element types. It is often necessary to define separate versions of the functions for FieldElem then for each of the Julia types separately in order to avoid ambiguity warnings.

Note that even though FieldElement is a union type we still have the following inclusion

FieldElement <: RingElement

Parent object caches

In many cases, it is desirable to have only one object in the system to represent each field. This means that if the same field is constructed twice, elements of the two fields will be compatible as far as arithmetic is concerned.

In order to facilitate this, global caches of fields are stored in AbstractAlgebra.jl, usually implemented using dictionaries. For example, the Generic.FracField parent objects are looked up in a dictionary FracDict to see if they have been previously defined.

Whether these global caches are provided or not, depends on both mathematical and algorithmic considerations. E.g. in the case of number fields, it isn't desirable to identify all number fields with the same defining polynomial, as they may be considered with distinct embeddings into one another. In other cases, identifying whether two fields are the same may be prohibitively expensive. Generally, it may only make sense algorithmically to identify two fields if they were constructed from identical data.

If a global cache is provided, it must be optionally possible to construct the parent objects without caching. This is done by passing a boolean value cached to the inner constructor of the parent object. See generic/GenericTypes.jl for examples of how to construct and handle such caches.

Required functions for all fields

In the following, we list all the functions that are required to be provided for fields in AbstractAlgebra.jl or by external libraries wanting to use AbstractAlgebra.jl.

We give this interface for fictitious types MyParent for the type of the field parent object R and MyElem for the type of the elements of the field.

Note

Generic functions in AbstractAlgebra.jl may not rely on the existence of functions that are not documented here. If they do, those functions will only be available for fields that implement that additional functionality, and should be documented as such.

In the first place, all fields are rings and therefore any field type must implement all of the Ring interface. The functionality below is in addition to this basic functionality.

Data type and parent object methods

characteristic(R::MyParent)

Return the characteristic of the field. If the characteristic is not known, an exception is raised.

Basic manipulation of rings and elements

is_unit(f::MyElem)

Return true if the given element is invertible, i.e. nonzero in the field.

diff --git a/dev/field_introduction/index.html b/dev/field_introduction/index.html index adb556a97..78c93b028 100644 --- a/dev/field_introduction/index.html +++ b/dev/field_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

A number of basic fields are provided, such as the rationals, finite fields, the real field, etc.

Various generic field constructions can then be made recursively on top of these basic fields. For example, fraction fields, residue fields, function fields, etc.

From the point of view of the system, all fields are rings and whether an object is a ring/field or an element thereof can be determined at the type level. There are abstract types for all field and for all field element types.

The field hierarchy can be extended by implementing new fields to follow one or more field interfaces, including the interface that all fields must follow. Once an interface is satisfied, all the corresponding generic functionality will work over the new field.

Implementations of new fields can either be generic or can be specialised implementations provided by, for example, a C library.

+Introduction · AbstractAlgebra.jl

Introduction

A number of basic fields are provided, such as the rationals, finite fields, the real field, etc.

Various generic field constructions can then be made recursively on top of these basic fields. For example, fraction fields, residue fields, function fields, etc.

From the point of view of the system, all fields are rings and whether an object is a ring/field or an element thereof can be determined at the type level. There are abstract types for all field and for all field element types.

The field hierarchy can be extended by implementing new fields to follow one or more field interfaces, including the interface that all fields must follow. Once an interface is satisfied, all the corresponding generic functionality will work over the new field.

Implementations of new fields can either be generic or can be specialised implementations provided by, for example, a C library.

diff --git a/dev/finfield/index.html b/dev/finfield/index.html index 4efdbe73b..3e3bcac95 100644 --- a/dev/finfield/index.html +++ b/dev/finfield/index.html @@ -52,4 +52,4 @@ julia> g = gen(F) 1 - + diff --git a/dev/fraction/index.html b/dev/fraction/index.html index 70f822812..4ea5db430 100644 --- a/dev/fraction/index.html +++ b/dev/fraction/index.html @@ -187,4 +187,4 @@ julia> collect(f) 2-element Vector{Tuple{BigInt, Int64}}: (10, 10) - (42, -8) + (42, -8) diff --git a/dev/fraction_interface/index.html b/dev/fraction_interface/index.html index 01581ed90..3dd6e6034 100644 --- a/dev/fraction_interface/index.html +++ b/dev/fraction_interface/index.html @@ -1,2 +1,2 @@ -Fraction Field Interface · AbstractAlgebra.jl

Fraction Field Interface

Fraction fields are supported in AbstractAlgebra.jl, at least for gcd domains. In addition to the standard Ring interface, some additional functions are required to be present for fraction fields.

Types and parents

AbstractAlgebra provides two abstract types for fraction fields and their elements:

  • FracField{T} is the abstract type for fraction field parent types
  • FracElem{T} is the abstract type for types of fractions

We have that FracField{T} <: Field and FracElem{T} <: FieldElem.

Note that both abstract types are parameterised. The type T should usually be the type of elements of the base ring of the fraction field.

Fraction fields should be made unique on the system by caching parent objects (unless an optional cache parameter is set to false). Fraction fields should at least be distinguished based on their base ring.

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Required functionality for fraction fields

In addition to the required functionality for the Field interface the Fraction Field interface has the following required functions.

We suppose that R is a fictitious base ring, and that S is the fraction field with parent object S of type MyFracField{T}. We also assume the fractions in the field have type MyFrac{T}, where T is the type of elements of the base ring.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElem.

Constructors

The following constructors create fractions. Note that these constructors don't require construction of the parent object first. This is easier to achieve if the fraction element type doesn't contain a reference to the parent object, but merely contains a reference to the base ring. The parent object can then be constructed on demand.

//(x::T, y::T) where T <: RingElem

Return the fraction $x/y$.

//(x::T, y::FracElem{T}) where T <: RingElem

Return $x/y$ where $x$ is in the base ring of $y$.

//(x::FracElem{T}, y::T) where T <: RingElem

Return $x/y$ where $y$ is in the base ring of $x$.

Basic manipulation of fields and elements

numerator(d::MyFrac{T}) where T <: RingElem

Given a fraction $d = a/b$ return $a$, where $a/b$ is in lowest terms with respect to the canonical_unit and gcd functions on the base ring.

denominator(d::MyFrac{T}) where T <: RingElem

Given a fraction $d = a/b$ return $b$, where $a/b$ is in lowest terms with respect to the canonical_unit and gcd functions on the base ring.

+Fraction Field Interface · AbstractAlgebra.jl

Fraction Field Interface

Fraction fields are supported in AbstractAlgebra.jl, at least for gcd domains. In addition to the standard Ring interface, some additional functions are required to be present for fraction fields.

Types and parents

AbstractAlgebra provides two abstract types for fraction fields and their elements:

  • FracField{T} is the abstract type for fraction field parent types
  • FracElem{T} is the abstract type for types of fractions

We have that FracField{T} <: Field and FracElem{T} <: FieldElem.

Note that both abstract types are parameterised. The type T should usually be the type of elements of the base ring of the fraction field.

Fraction fields should be made unique on the system by caching parent objects (unless an optional cache parameter is set to false). Fraction fields should at least be distinguished based on their base ring.

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Required functionality for fraction fields

In addition to the required functionality for the Field interface the Fraction Field interface has the following required functions.

We suppose that R is a fictitious base ring, and that S is the fraction field with parent object S of type MyFracField{T}. We also assume the fractions in the field have type MyFrac{T}, where T is the type of elements of the base ring.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElem.

Constructors

The following constructors create fractions. Note that these constructors don't require construction of the parent object first. This is easier to achieve if the fraction element type doesn't contain a reference to the parent object, but merely contains a reference to the base ring. The parent object can then be constructed on demand.

//(x::T, y::T) where T <: RingElem

Return the fraction $x/y$.

//(x::T, y::FracElem{T}) where T <: RingElem

Return $x/y$ where $x$ is in the base ring of $y$.

//(x::FracElem{T}, y::T) where T <: RingElem

Return $x/y$ where $y$ is in the base ring of $x$.

Basic manipulation of fields and elements

numerator(d::MyFrac{T}) where T <: RingElem

Given a fraction $d = a/b$ return $a$, where $a/b$ is in lowest terms with respect to the canonical_unit and gcd functions on the base ring.

denominator(d::MyFrac{T}) where T <: RingElem

Given a fraction $d = a/b$ return $b$, where $a/b$ is in lowest terms with respect to the canonical_unit and gcd functions on the base ring.

diff --git a/dev/free_associative_algebra/index.html b/dev/free_associative_algebra/index.html index d9ecbb447..ee75cfa3c 100644 --- a/dev/free_associative_algebra/index.html +++ b/dev/free_associative_algebra/index.html @@ -129,4 +129,4 @@ julia> g = Generic.groebner_basis([u*(x*y)^3 + u*(x*y)^2 + u + v, (y*x)^3*t + (y*x)^2*t + t + s]); julia> normal_form(u*(x*y)^3*s*t + u*(x*y)^2*s*t +u*s*t + v*s*t, g) -0 +0 diff --git a/dev/free_module/index.html b/dev/free_module/index.html index d39b4ab75..8cfef965a 100644 --- a/dev/free_module/index.html +++ b/dev/free_module/index.html @@ -21,4 +21,4 @@ julia> basis(V) 2-element Vector{AbstractAlgebra.Generic.FreeModuleElem{Rational{BigInt}}}: (1//1, 0//1) - (0//1, 1//1) + (0//1, 1//1) diff --git a/dev/function_field/index.html b/dev/function_field/index.html index ca511c7a9..65e1c90f4 100644 --- a/dev/function_field/index.html +++ b/dev/function_field/index.html @@ -220,4 +220,4 @@ (x^7 + 20//9*x^6 + 766//81*x^5 + 2027//81*x^4 + 110//3*x^3 + 682//9*x^2 + 1060//9*x + 725//9)//(x^3 - 2*x^2 - 4*x + 8) julia> tr(f) -(2*x^4 + 38//9*x^3 + 85//9*x^2 + 24*x + 25)//(x^2 - 4) +(2*x^4 + 38//9*x^3 + 85//9*x^2 + 24*x + 25)//(x^2 - 4) diff --git a/dev/functional_map/index.html b/dev/functional_map/index.html index 9f9edd983..ce21323c4 100644 --- a/dev/functional_map/index.html +++ b/dev/functional_map/index.html @@ -8,4 +8,4 @@ to integers julia> f(ZZ(2)) -3source +3source diff --git a/dev/ideal/index.html b/dev/ideal/index.html index bb7a6fd97..5b59fdc8a 100644 --- a/dev/ideal/index.html +++ b/dev/ideal/index.html @@ -72,4 +72,4 @@ julia> normal_form(30x^5*y + 2x + 1, I) -135*y^4 + 138*y^3 - 147*y^2 + 2*x + 1 +135*y^4 + 138*y^3 - 147*y^2 + 2*x + 1 diff --git a/dev/index.html b/dev/index.html index 38702fdc0..281c8990d 100644 --- a/dev/index.html +++ b/dev/index.html @@ -41,4 +41,4 @@ u = t + O(t^100) -@time divexact((u*exp(x*u)), (exp(u)-1)); +@time divexact((u*exp(x*u)), (exp(u)-1)); diff --git a/dev/integer/index.html b/dev/integer/index.html index e4a761801..79f70efd0 100644 --- a/dev/integer/index.html +++ b/dev/integer/index.html @@ -57,4 +57,4 @@ julia> m = AbstractAlgebra.exp(ZZ(0)) 1

Coprime bases

AbstractAlgebra.ppioMethod
ppio(a::T, b::T)

Return a pair $(c,d)$ such that $a=c*d$ and $c = gcd(a, b^\infty)$ if $a\neq 0$, and $c=b$, $d=0$ if $a=0$.

source

Examples

julia> c, n = ppio(ZZ(12), ZZ(26))
 (4, 3)
-
+ diff --git a/dev/interface_introduction/index.html b/dev/interface_introduction/index.html index 55ff10ee4..16d26489a 100644 --- a/dev/interface_introduction/index.html +++ b/dev/interface_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

AbstractAlgebra defines a series of interfaces that can be extended with new types that implement those interfaces. For example, if one were implementing a new polynomial ring type, one would implement all of the required functionality described in this chapter for the relevant AbstractAlgebra interfaces. This would include the Ring Interface and the Univariate Polynomial Ring Interface.

Once a new type implements all the required functionality, all the corresponding generic functionality would then function automatically for the new type.

One may then go on to implement some of the optional functionality for performance if the provided generic functionality is insufficient.

AbstractAlgebra tries to provide all generic constructions recursively so that one can have towers of generic constructions. This means that new interfaces should generally only be added if they cooperate with all the existing interfaces, at least so far as the theory exists to do so.

+Introduction · AbstractAlgebra.jl

Introduction

AbstractAlgebra defines a series of interfaces that can be extended with new types that implement those interfaces. For example, if one were implementing a new polynomial ring type, one would implement all of the required functionality described in this chapter for the relevant AbstractAlgebra interfaces. This would include the Ring Interface and the Univariate Polynomial Ring Interface.

Once a new type implements all the required functionality, all the corresponding generic functionality would then function automatically for the new type.

One may then go on to implement some of the optional functionality for performance if the provided generic functionality is insufficient.

AbstractAlgebra tries to provide all generic constructions recursively so that one can have towers of generic constructions. This means that new interfaces should generally only be added if they cooperate with all the existing interfaces, at least so far as the theory exists to do so.

diff --git a/dev/laurent_mpolynomial/index.html b/dev/laurent_mpolynomial/index.html index bf87a7efa..069d9f5d3 100644 --- a/dev/laurent_mpolynomial/index.html +++ b/dev/laurent_mpolynomial/index.html @@ -24,4 +24,4 @@ -x^-5*y^-4 julia> gcd(x^-3 - y^3, x^-2 - y^2) -x*y - 1 +x*y - 1 diff --git a/dev/laurent_polynomial/index.html b/dev/laurent_polynomial/index.html index a403da03f..c063fce6c 100644 --- a/dev/laurent_polynomial/index.html +++ b/dev/laurent_polynomial/index.html @@ -46,4 +46,4 @@ 5.0*x^3 + 2.0*x + x^-2 julia> leading_coefficient(f), trailing_coefficient(f) -(5, 1) +(5, 1) diff --git a/dev/linear_solving/index.html b/dev/linear_solving/index.html index bbaf5623a..9c773609a 100644 --- a/dev/linear_solving/index.html +++ b/dev/linear_solving/index.html @@ -30,4 +30,4 @@ can_solve_with_solution_and_kernel(A::MatElem{T}, b::MatElem{T}; side::Symbol = :left) where T can_solve_with_solution_and_kernel(C::SolveCtx{T}, b::Vector{T}; side::Symbol = :left) where T can_solve_with_solution_and_kernel(C::SolveCtx{T}, b::MatElem{T}; side::Symbol = :left) where T

Return true, $x$ of same type as $b$ solving the linear system $xA = b$, together with a matrix $K$ giving the kernel of $A$ (i.e. $KA = 0$), if such a solution exists. Return false, an empty vector or matrix and an empty matrix, if the system has no solution.

If side == :right, the system $Ax = b$ is solved.

If a context object C is supplied, then the above applies for A = matrix(C).

See also solve and kernel.

source
AbstractAlgebra.kernelFunction
kernel(f::ModuleHomomorphism{T}) where T <: RingElement

Return a pair K, g consisting of the kernel object $K$ of the given module homomorphism $f$ (as a submodule of its domain) and the canonical injection from the kernel into the domain of $f$.

source
kernel(A::MatElem; side::Symbol = :left)
-kernel(C::SolveCtx; side::Symbol = :left)

Return a matrix $K$ whose rows generate the left kernel of $A$, that is, $KA$ is the zero matrix.

If side == :right, the columns of $K$ generate the right kernel of $A$, that is, $AK$ is the zero matrix.

If the base ring is a principal ideal domain, the rows or columns respectively of $K$ are a basis of the respective kernel.

If a context object C is supplied, then the above applies for A = matrix(C).

source
+kernel(C::SolveCtx; side::Symbol = :left)

Return a matrix $K$ whose rows generate the left kernel of $A$, that is, $KA$ is the zero matrix.

If side == :right, the columns of $K$ generate the right kernel of $A$, that is, $AK$ is the zero matrix.

If the base ring is a principal ideal domain, the rows or columns respectively of $K$ are a basis of the respective kernel.

If a context object C is supplied, then the above applies for A = matrix(C).

source diff --git a/dev/map_cache/index.html b/dev/map_cache/index.html index 5634de9d3..a023321bb 100644 --- a/dev/map_cache/index.html +++ b/dev/map_cache/index.html @@ -27,4 +27,4 @@ 200 julia> d = f(ZZ(1)) -2 +2 diff --git a/dev/map_interface/index.html b/dev/map_interface/index.html index fb861aec3..567408884 100644 --- a/dev/map_interface/index.html +++ b/dev/map_interface/index.html @@ -23,4 +23,4 @@ which is the composite of Map: integers -> integers Map: integers -> rationalssource

As a shortcut for this function we have the following operator:

*(f::Map{D, U}, g::Map{U, C}) where {D, U, C} = compose(f, g)

Note the order of composition. If we have maps $f : X \to Y$, $g : Y \to Z$ the correct order of the maps in this operator is f*g, so that (f*g)(x) = g(f(x)).

This is chosen so that for left $R$-module morphisms represented by a matrix, the order of matrix multiplication will match the order of composition of the corresponding morphisms.

Of course, a custom map type or class of maps can implement its own composition type and compose function.

This is the case with the FunctionalMap class for example, which caches the Julia function/closure corresponding to the composition of two functional maps. As this cached function needs to be stored inside the composition, a special type is necessary for the composition of two functional maps.

By default, compose will check that the two maps are composable, i.e. the codomain of the first map matches the domain of the second map. This is implemented by the following function:

check_composable(f::Map{D, U}, g::Map{U, C})

Raise an exception if the codomain of $f$ doesn't match the domain of $g$.

Note that composite maps should keep track of the two maps they were constructed from. To access these maps, the following functions are provided:

map1(f::CompositeMap)
-map2(f::CompositeMap)

Any custom composite map type must also provide these functions for that map type, even if there exist fields with those names. This is because there is no common map class for all composite map types. Therefore the Generic system cannot provide fallbacks for all such composite map types.

+map2(f::CompositeMap)

Any custom composite map type must also provide these functions for that map type, even if there exist fields with those names. This is because there is no common map class for all composite map types. Therefore the Generic system cannot provide fallbacks for all such composite map types.

diff --git a/dev/map_introduction/index.html b/dev/map_introduction/index.html index 41963d17f..cadd80cbb 100644 --- a/dev/map_introduction/index.html +++ b/dev/map_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

Maps in AbstractAlgebra model maps on sets $f : D \to C$ for some domain $D$ and codomain $C$, which have no real limitations except that elements of the codomain and domain be represented by element objects in the system.

Maps $f : D \to C$ in AbstractAlgebra are modeled by Julia objects that are able to be called on a single element $d \in D$ of the domain to yield an element $f(d) \in C$ of the codomain. We say that the map is being applied.

Maps can be constructed from Julia functions, or they can be represented by some other kind of data, e.g. a matrix, or built up from other maps.

Maps in AbstractAlgebra have a domain and codomain, can be applied, composed with other maps. Various special kinds of map provide more functionality.

For details please refer to the Map Interface documentation.

For example, there are functional maps which wrap a Julia function, cached maps which cache values so they do not have to be recomputed each time they are applied to the same inputs and various kinds of maps with inverses, e.g. maps with sections, retractions and full inverses.

The map system uses a complex four parameter Map type, however various helper functions are provided to make it easier to work with.

+Introduction · AbstractAlgebra.jl

Introduction

Maps in AbstractAlgebra model maps on sets $f : D \to C$ for some domain $D$ and codomain $C$, which have no real limitations except that elements of the codomain and domain be represented by element objects in the system.

Maps $f : D \to C$ in AbstractAlgebra are modeled by Julia objects that are able to be called on a single element $d \in D$ of the domain to yield an element $f(d) \in C$ of the codomain. We say that the map is being applied.

Maps can be constructed from Julia functions, or they can be represented by some other kind of data, e.g. a matrix, or built up from other maps.

Maps in AbstractAlgebra have a domain and codomain, can be applied, composed with other maps. Various special kinds of map provide more functionality.

For details please refer to the Map Interface documentation.

For example, there are functional maps which wrap a Julia function, cached maps which cache values so they do not have to be recomputed each time they are applied to the same inputs and various kinds of maps with inverses, e.g. maps with sections, retractions and full inverses.

The map system uses a complex four parameter Map type, however various helper functions are provided to make it easier to work with.

diff --git a/dev/map_with_inverse/index.html b/dev/map_with_inverse/index.html index 204ef8340..b57fe1b48 100644 --- a/dev/map_with_inverse/index.html +++ b/dev/map_with_inverse/index.html @@ -31,4 +31,4 @@ julia> a = h(ZZ(1)) 1 - + diff --git a/dev/matrix/index.html b/dev/matrix/index.html index 38308ef84..25057213c 100644 --- a/dev/matrix/index.html +++ b/dev/matrix/index.html @@ -828,4 +828,4 @@ julia> U*A [ 1 2 3 x] [ 0 0 0 0] -[-x^3 -2*x^3 + x^2 - 2*x + 1 -2*x^3 + x^2 - 3*x 1] +[-x^3 -2*x^3 + x^2 - 2*x + 1 -2*x^3 + x^2 - 3*x 1] diff --git a/dev/matrix_algebras/index.html b/dev/matrix_algebras/index.html index ed3c340ec..ec4ddab8b 100644 --- a/dev/matrix_algebras/index.html +++ b/dev/matrix_algebras/index.html @@ -37,4 +37,4 @@ julia> n = degree(A) 3 - + diff --git a/dev/matrix_interface/index.html b/dev/matrix_interface/index.html index 16da7beac..bdc92e583 100644 --- a/dev/matrix_interface/index.html +++ b/dev/matrix_interface/index.html @@ -13,4 +13,4 @@ zero(x::MyMat{T}, R::Ring=base_ring(x)) where T <: RingElem

Construct the matrix with the same dimensions as the given matrix, and the same base ring unless explicitly specified.

similar(x::MyMat{T}, R::Ring, r::Int, c::Int) where T <: RingElem
 similar(x::MyMat{T}, r::Int, c::Int) where T <: RingElem
 zero(x::MyMat{T}, R::Ring, r::Int, c::Int) where T <: RingElem
-zero(x::MyMat{T}, r::Int, c::Int) where T <: RingElem

Construct the $r\times c$ matrix with R as base ring (which defaults to the base ring of the the given matrix). If $x$ belongs to a matrix algebra and $r \neq c$, an exception is raised, and it's also possible to specify only one Int as the order (e.g. similar(x, n)).

Custom matrices and rings may choose which specific matrix type is best-suited to return for the given ring and dimensionality. If they do not specialize these functions, the default is a Generic.MatSpaceElem matrix, or Generic.MatRingElem for matrix algebras. The default implementation of zero calls out to similar, so it's generally sufficient to specialize only similar. For both similar and zero, only the most general method has to be implemented (e.g. similar(x::MyMat, R::Ring, r::Int, c::Int), as all other methods (which have defaults) call out to this more general method.

Base.isassigned(M::MyMat, i, j)

Test whether the given matrix has a value associated with indices i and j. It is recommended to overload this method for custom matrices.

Optional symmetry test

is_symmetric(a::MatrixElem)

Return true if the given matrix is symmetric with respect to its main diagonal, otherwise return false.

+zero(x::MyMat{T}, r::Int, c::Int) where T <: RingElem

Construct the $r\times c$ matrix with R as base ring (which defaults to the base ring of the the given matrix). If $x$ belongs to a matrix algebra and $r \neq c$, an exception is raised, and it's also possible to specify only one Int as the order (e.g. similar(x, n)).

Custom matrices and rings may choose which specific matrix type is best-suited to return for the given ring and dimensionality. If they do not specialize these functions, the default is a Generic.MatSpaceElem matrix, or Generic.MatRingElem for matrix algebras. The default implementation of zero calls out to similar, so it's generally sufficient to specialize only similar. For both similar and zero, only the most general method has to be implemented (e.g. similar(x::MyMat, R::Ring, r::Int, c::Int), as all other methods (which have defaults) call out to this more general method.

Base.isassigned(M::MyMat, i, j)

Test whether the given matrix has a value associated with indices i and j. It is recommended to overload this method for custom matrices.

Optional symmetry test

is_symmetric(a::MatrixElem)

Return true if the given matrix is symmetric with respect to its main diagonal, otherwise return false.

diff --git a/dev/matrix_introduction/index.html b/dev/matrix_introduction/index.html index ebd7001ec..e7c1d0494 100644 --- a/dev/matrix_introduction/index.html +++ b/dev/matrix_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

AbstractAlgebra provides matrix spaces (mxn matrices) and matrix algebras (nxn matrices) over a ring. Whilst both types of matrix provide matrix multiplication for matrices whose dimensions are compatible for multiplication, only the latter kind of matrices form rings in the system.

Matrix spaces provide a large number of linear algebra operations, including linear solving, elementary row operations, various canonical forms. The system also provides characteristic and minimal polynomial computations, LU decomposition, determinant, matrix inverse, kernel computations.

There is also code for computation of the Hermite and Smith normal forms over Euclidean domains and Popov form for matrices over polynomial rings over a field.

Most of this generic functionality is provided for arbitrary matrix types that satisfy the AbstractAlgebra matrix interface.

+Introduction · AbstractAlgebra.jl

Introduction

AbstractAlgebra provides matrix spaces (mxn matrices) and matrix algebras (nxn matrices) over a ring. Whilst both types of matrix provide matrix multiplication for matrices whose dimensions are compatible for multiplication, only the latter kind of matrices form rings in the system.

Matrix spaces provide a large number of linear algebra operations, including linear solving, elementary row operations, various canonical forms. The system also provides characteristic and minimal polynomial computations, LU decomposition, determinant, matrix inverse, kernel computations.

There is also code for computation of the Hermite and Smith normal forms over Euclidean domains and Popov form for matrices over polynomial rings over a field.

Most of this generic functionality is provided for arbitrary matrix types that satisfy the AbstractAlgebra matrix interface.

diff --git a/dev/misc/index.html b/dev/misc/index.html index 0269e7db9..0a510ed0d 100644 --- a/dev/misc/index.html +++ b/dev/misc/index.html @@ -145,4 +145,4 @@ Solve._init_reduce_transpose(C::SolveCtx{T, NewTrait}) where T

These should fill the corresponding fields of the solve context C with a "reduced matrix" (that is, a matrix in normal form) of matrix(C), respectively transpose(matrix(C)), and other information necessary to solve a linear system. The fields can be accessed via reduced_matrix, reduced_matrix_of_transpose, etc. New fields may also be added via attributes.

Internal solving functionality

As above, one finally needs to implement the functions

Solve._can_solve_internal_no_check(
   ::NewTrait, C::SolveCtx{T, NewTrait}, b::MatElem{T}, task::Symbol;
   side::Symbol = :left
-  ) where T

and

kernel(::NewTrait, C::SolveCtx{T, NewTrait}; side::Symbol = :left)
+ ) where T

and

kernel(::NewTrait, C::SolveCtx{T, NewTrait}; side::Symbol = :left)
diff --git a/dev/module/index.html b/dev/module/index.html index 7b2194eb9..2c2ec7a79 100644 --- a/dev/module/index.html +++ b/dev/module/index.html @@ -91,4 +91,4 @@ julia> invs = invariant_factors(Q) 1-element Vector{BigInt}: 0 - + diff --git a/dev/module_homomorphism/index.html b/dev/module_homomorphism/index.html index b2e9b78bc..6b0985901 100644 --- a/dev/module_homomorphism/index.html +++ b/dev/module_homomorphism/index.html @@ -51,4 +51,4 @@ N = matrix(ZZ, 2, 2, BigInt[1, 0, 0, 1]) f = ModuleIsomorphism(M, M, N) -g = inv(f) +g = inv(f) diff --git a/dev/module_interface/index.html b/dev/module_interface/index.html index 4de3b79b7..7ffba9c15 100644 --- a/dev/module_interface/index.html +++ b/dev/module_interface/index.html @@ -1,2 +1,2 @@ -Module Interface · AbstractAlgebra.jl

Module Interface

Note

The module infrastructure in AbstractAlgebra should be considered experimental at this stage. This means that the interface may change in the future.

AbstractAlgebra allows the construction of finitely presented modules (i.e. with finitely many generators and relations), starting from free modules. The generic code provided by AbstractAlgebra will only work for modules over euclidean domains, however there is nothing preventing a library from implementing more general modules using the same interface.

All finitely presented module types in AbstractAlgebra follow the following interface which is a loose interface of functions, without much generic infrastructure built on top.

Free modules can be built over both commutative and noncommutative rings. Other types of module are restricted to fields and euclidean rings.

Abstract types

AbstractAlgebra provides two abstract types for finitely presented modules and their elements:

  • FPModule{T} is the abstract type for finitely presented module parent

types

  • FPModuleElem{T} is the abstract type for finitely presented module

element types

Note that the abstract types are parameterised. The type T should usually be the type of elements of the ring the module is over.

Required functionality for modules

We suppose that R is a fictitious base ring and that S is a module over R with parent object S of type MyModule{T}. We also assume the elements in the module have type MyModuleElem{T}, where T is the type of elements of the ring the module is over.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElement or NCRingElem.

We describe the functionality below for modules over commutative rings, i.e. with element type belonging to RingElement, however similar constructors should be available for element types belonging to NCRingElem instead, for free modules over a noncommutative ring.

Although not part of the module interface, implementations of modules that wish to follow our interface should use the same function names for submodules, quotient modules, direct sums and module homomorphisms if they wish to remain compatible with our module generics in the future.

Basic manipulation

iszero(m::MyModuleElem{T}) where T <: RingElement

Return true if the given module element is zero.

number_of_generators(M::MyModule{T}) where T <: RingElement

Return the number of generators of the module $M$ in its current representation.

gen(M::MyModule{T}, i::Int) where T <: RingElement

Return the $i$-th generator (indexed from $1$) of the module $M$.

gens(M::MyModule{T}) where T <: RingElement

Return a Julia array of the generators of the module $M$.

rels(M::MyModule{T}) where T <: RingElement

Return a Julia vector of all the relations between the generators of M. Each relation is given as an AbstractAlgebra row matrix.

Element constructors

We can construct elements of a module $M$ by specifying linear combinations of the generators of $M$. This is done by passing a vector of ring elements.

(M::Module{T})(v::Vector{T}) where T <: RingElement

Construct the element of the module $M$ corresponding to $\sum_i g[i]v[i]$ where $g[i]$ are the generators of the module $M$. The resulting element will lie in the module $M$.

Coercions

Given a module $M$ and an element $n$ of a module $N$, it is possible to coerce $n$ into $M$ using the notation $M(n)$ in certain circumstances.

In particular the element $n$ will be automatically coerced along any canonical injection of a submodule map and along any canonical projection of a quotient map. There must be a path from $N$ to $M$ along such maps.

Arithmetic operators

Elements of a module can be added, subtracted or multiplied by an element of the ring the module is defined over and compared for equality.

In the case of a noncommutative ring, both left and right scalar multiplication are defined.

+Module Interface · AbstractAlgebra.jl

Module Interface

Note

The module infrastructure in AbstractAlgebra should be considered experimental at this stage. This means that the interface may change in the future.

AbstractAlgebra allows the construction of finitely presented modules (i.e. with finitely many generators and relations), starting from free modules. The generic code provided by AbstractAlgebra will only work for modules over euclidean domains, however there is nothing preventing a library from implementing more general modules using the same interface.

All finitely presented module types in AbstractAlgebra follow the following interface which is a loose interface of functions, without much generic infrastructure built on top.

Free modules can be built over both commutative and noncommutative rings. Other types of module are restricted to fields and euclidean rings.

Abstract types

AbstractAlgebra provides two abstract types for finitely presented modules and their elements:

  • FPModule{T} is the abstract type for finitely presented module parent

types

  • FPModuleElem{T} is the abstract type for finitely presented module

element types

Note that the abstract types are parameterised. The type T should usually be the type of elements of the ring the module is over.

Required functionality for modules

We suppose that R is a fictitious base ring and that S is a module over R with parent object S of type MyModule{T}. We also assume the elements in the module have type MyModuleElem{T}, where T is the type of elements of the ring the module is over.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElement or NCRingElem.

We describe the functionality below for modules over commutative rings, i.e. with element type belonging to RingElement, however similar constructors should be available for element types belonging to NCRingElem instead, for free modules over a noncommutative ring.

Although not part of the module interface, implementations of modules that wish to follow our interface should use the same function names for submodules, quotient modules, direct sums and module homomorphisms if they wish to remain compatible with our module generics in the future.

Basic manipulation

iszero(m::MyModuleElem{T}) where T <: RingElement

Return true if the given module element is zero.

number_of_generators(M::MyModule{T}) where T <: RingElement

Return the number of generators of the module $M$ in its current representation.

gen(M::MyModule{T}, i::Int) where T <: RingElement

Return the $i$-th generator (indexed from $1$) of the module $M$.

gens(M::MyModule{T}) where T <: RingElement

Return a Julia array of the generators of the module $M$.

rels(M::MyModule{T}) where T <: RingElement

Return a Julia vector of all the relations between the generators of M. Each relation is given as an AbstractAlgebra row matrix.

Element constructors

We can construct elements of a module $M$ by specifying linear combinations of the generators of $M$. This is done by passing a vector of ring elements.

(M::Module{T})(v::Vector{T}) where T <: RingElement

Construct the element of the module $M$ corresponding to $\sum_i g[i]v[i]$ where $g[i]$ are the generators of the module $M$. The resulting element will lie in the module $M$.

Coercions

Given a module $M$ and an element $n$ of a module $N$, it is possible to coerce $n$ into $M$ using the notation $M(n)$ in certain circumstances.

In particular the element $n$ will be automatically coerced along any canonical injection of a submodule map and along any canonical projection of a quotient map. There must be a path from $N$ to $M$ along such maps.

Arithmetic operators

Elements of a module can be added, subtracted or multiplied by an element of the ring the module is defined over and compared for equality.

In the case of a noncommutative ring, both left and right scalar multiplication are defined.

diff --git a/dev/module_introduction/index.html b/dev/module_introduction/index.html index 48b5753a9..7ac49b7da 100644 --- a/dev/module_introduction/index.html +++ b/dev/module_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

As with many generic constructions in AbstractAlgebra, the modules that are provided in AbstractAlgebra itself work over a Euclidean domain. Moreover, they are limited to finitely presented modules.

Free modules and vector spaces are provided over Euclidean domains and fields respectively and then submodule, quotient module and direct sum module constructions are possible recursively over these.

It's also possible to compute an invariant decomposition using the Smith Normal Form.

The system also provides module homomorphisms and isomorphisms, building on top of the map interface.

As for rings and fields, modules follow an interface which other modules are expected to follow. However, very little generic functionality is provided automatically once this interface is implemented by a new module type.

The purpose of the module interface is simply to encourage uniformity in the module interfaces of systems that build on AbstractAlgebra. Of course modules are so diverse that this is a very loosely defined interface to accommodate the diversity of possible representations and implementations.

+Introduction · AbstractAlgebra.jl

Introduction

As with many generic constructions in AbstractAlgebra, the modules that are provided in AbstractAlgebra itself work over a Euclidean domain. Moreover, they are limited to finitely presented modules.

Free modules and vector spaces are provided over Euclidean domains and fields respectively and then submodule, quotient module and direct sum module constructions are possible recursively over these.

It's also possible to compute an invariant decomposition using the Smith Normal Form.

The system also provides module homomorphisms and isomorphisms, building on top of the map interface.

As for rings and fields, modules follow an interface which other modules are expected to follow. However, very little generic functionality is provided automatically once this interface is implemented by a new module type.

The purpose of the module interface is simply to encourage uniformity in the module interfaces of systems that build on AbstractAlgebra. Of course modules are so diverse that this is a very loosely defined interface to accommodate the diversity of possible representations and implementations.

diff --git a/dev/mpoly_interface/index.html b/dev/mpoly_interface/index.html index 8027805d8..f12fde417 100644 --- a/dev/mpoly_interface/index.html +++ b/dev/mpoly_interface/index.html @@ -4,4 +4,4 @@ divexact(f::MyMPoly{T}, c::Rational) where T <: RingElem divexact(f::MyMPoly{T}, c::T) where T <: RingElem

Divide the polynomial exactly by the constant $c$.

Euclidean division

Although multivariate polynomial rings are not in general Euclidean, it is possible to define a quotient with remainder function that depends on the polynomial ordering in the case that the quotient ring is a field or a Euclidean domain. In the case that a polynomial $g$ divides a polynomial $f$, the result no longer depends on the ordering and the remainder is zero, with the quotient agreeing with the exact quotient.

divrem(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return a tuple $(q, r)$ such that $f = qg + r$, where the coefficients of terms of $r$ whose monomials are divisible by the leading monomial of $g$ are reduced modulo the leading coefficient of $g$ (according to the Euclidean function on the coefficients).

Note that the result of this function depends on the ordering of the polynomial ring.

div(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

As per the divrem function, but returning the quotient only. Especially when the quotient happens to be exact, this function can be exceedingly fast.

GCD

In cases where there is a meaningful Euclidean structure on the coefficient ring, it is possible to compute the GCD of multivariate polynomials.

gcd(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return a greatest common divisor of $f$ and $g$.

Square root

Over rings for which an exact square root is available, it is possible to take the square root of a polynomial or test whether it is a square.

sqrt(f::MyMPoly{T}, check::Bool=true) where T <: RingElem

Return the square root of the polynomial $f$ and raise an exception if it is not a square. If check is set to false, the input is assumed to be a perfect square and this assumption is not fully checked. This can be significantly faster.

is_square(::MyMPoly{T}) where T <: RingElem

Return true if $f$ is a square.

Interface for sparse distributed, random access multivariates

The following additional functions should be implemented by libraries that provide a sparse distributed polynomial format, stored in a representation for which terms can be accessed in constant time (e.g. where arrays are used to store coefficients and exponent vectors).

Sparse distributed, random access constructors

In addition to the standard constructors, the following constructor, taking arrays of coefficients and exponent vectors, should be provided.

(S::MyMPolyRing{T})(A::Vector{T}, m::Vector{Vector{Int}}) where T <: RingElem

Create the polynomial in the given ring with nonzero coefficients specified by the elements of $A$ and corresponding exponent vectors given by the elements of $m$.

There is no assumption about coefficients being nonzero or terms being in order or unique. Zero terms are removed by the function, duplicate terms are combined (added) and the terms are sorted so that they are in the correct order.

Each exponent vector uses a separate integer for each exponent field, the first of which should be the exponent for the most significant variable with respect to the ordering. All exponents must be non-negative.

A library may also optionally provide an interface that makes use of BigInt (or any other big integer type) for exponents instead of Int.

Sparse distributed, random access basic manipulation

coeff(f::MyMPoly{T}, n::Int) where T <: RingElem

Return the coefficient of the $n$-th term of $f$. The first term should be the most significant term with respect to the ordering.

coeff(a::MyMPoly{T}, exps::Vector{Int}) where T <: RingElement

Return the coefficient of the term with the given exponent vector, or zero if there is no such term.

monomial(f::MyMPoly{T}, n::Int) where T <: RingElem
 monomial!(m::MyMPoly{T}, f::MyMPoly{T}, n::Int) where T <: RingElem

Return the $n$-th monomial of $f$ or set $m$ to the $n$-th monomial of $f$, respectively. The first monomial should be the most significant term with respect to the ordering. Monomials have coefficient $1$ in AbstractAlgebra. See the function term if you also require the coefficient, however, note that only monomials can be compared.

term(f::MyMPoly{T}, n::Int) where T <: RingElem

Return the $n$-th term of $f$. The first term should be the one whose monomial is most significant with respect to the ordering.

exponent(f::MyMPoly{T}, i::Int, j::Int) where T <: RingElem

Return the exponent of the $j$-th variable in the $i$-th term of the polynomial $f$. The first term is the one with whose monomial is most significant with respect to the ordering.

exponent_vector(a::MyMPoly{T}, i::Int) where T <: RingElement

Return a vector of exponents, corresponding to the exponent vector of the i-th term of the polynomial. Term numbering begins at $1$ and the exponents are given in the order of the variables for the ring, as supplied when the ring was created.

setcoeff!(a::MyMPoly, exps::Vector{Int}, c::S) where S <: RingElement

Set the coefficient of the term with the given exponent vector to the given value $c$. If no such term exists (and $c \neq 0$), one will be inserted. This function takes $O(\log n)$ operations if a term with the given exponent already exists and $c \neq 0$, or if the term is inserted at the end of the polynomial. Otherwise it can take $O(n)$ operations in the worst case. This function must return the modified polynomial.

Unsafe functions

The following functions must be provided, but are considered unsafe, as they may leave the polynomials in an inconsistent state and they mutate their inputs. As usual, such functions should only be applied on polynomials that have no references elsewhere in the system and are mainly intended to be used in carefully written library code, rather than by users.

Users should instead build polynomials using the constructors described above.

fit!(f::MyMPoly{T}, n::Int) where T <: RingElem

Ensure that the polynomial $f$ internally has space for $n$ nonzero terms. This function must mutate the function in-place if it is mutable. It does not return the mutated polynomial. Immutable types can still be supported by defining this function to do nothing.

setcoeff!(a::MyMPoly{T}, i::Int, c::T) where T <: RingElement
-setcoeff!(a::MyMPoly{T}, i::Int, c::U) where {T <: RingElement, U <: Integer}

Set the $i$-th coefficient of the polynomial $a$ to $c$. No check is performed on the index $i$ or for $c = 0$. It may be necessary to call combine_like_terms after calls to this function, to remove zero terms. The function must return the modified polynomial.

combine_like_terms!(a::MyMPoly{T}) where T <: RingElement

Remove zero terms and combine any adjacent terms with the same exponent vector (by adding them). It is assumed that all the exponent vectors are already in the correct order with respect to the ordering. The function must return the resulting polynomial.

set_exponent_vector!(a::MyMPoly{T}, i::Int, exps::Vector{Int}) where T <: RingElement

Set the $i$-th exponent vector to the given exponent vector. No check is performed on the index $i$, which is assumed to be valid (or that the polynomial has enough space allocated). No sorting of exponents is performed by this function. To sort the terms after setting any number of exponents with this function, run the sort_terms! function. The function must return the modified polynomial.

sort_terms!(a::MyMPoly{T}) where {T <: RingElement}

Sort the terms of the given polynomial according to the polynomial ring ordering. Zero terms and duplicate exponents are ignored. To deal with those call combine_like_terms. The sorted polynomial must be returned by the function.

Optional functionality for multivariate polynomials

The following functions can optionally be implemented for multivariate polynomial types.

Reduction by an ideal

divrem(f::MyMPoly{T}, G::Vector{MyMPoly{T}}) where T <: RingElem

As per the divrem function above, except that each term of $r$ starting with the most significant term, is reduced modulo the leading terms of each of the polynomials in the array $G$ for which the leading monomial is a divisor.

A tuple $(Q, r)$ is returned from the function, where $Q$ is an array of polynomials of the same length as $G$, and such that $f = r + \sum Q[i]G[i]$.

The result is again dependent on the ordering in general, but if the polynomials in $G$ are over a field and the reduced generators of a Groebner basis, then the result is unique.

Evaluation

evaluate(a::MyMPoly{T}, A::Vector{T}) where T <: RingElem

Evaluate the polynomial at the given values in the coefficient ring of the polynomial. The result should be an element of the coefficient ring.

evaluate(f::MyMPoly{T}, A::Vector{U}) where {T <: RingElem, U <: Integer}

Evaluate the polynomial $f$ at the values specified by the entries of the array $A$.

(a::MyMPoly{T})(vals::Union{NCRingElem, RingElement}...) where T <: RingElement

Evaluate the polynomial at the given arguments. This provides functional notation for polynomial evaluation, i.e. $f(a, b, c)$. It must be defined for each supported polynomial type (Julia does not allow functional notation to be defined for an abstract type).

The code for this function in MPoly.jl can be used when implementing this as it provides the most general possible evaluation, which is much more general than the case of evaluation at elements of the same ring.

The evaluation should succeed for any set of values for which a multiplication is defined with the product of a coefficient and all the values before it.

Note

The values at which a polynomial is evaluated may be in non-commutative rings. Products are performed in the order of the variables in the polynomial ring that the polynomial belongs to, preceded by a multiplication by the coefficient on the left.

Derivations

The following function allows to compute derivations of multivariate polynomials of type MPoly.

derivative(f::MyMPoly{T}, j::Int) where T <: RingElem

Compute the derivative of $f$ with respect to the $j$-th variable of the polynomial ring.

+setcoeff!(a::MyMPoly{T}, i::Int, c::U) where {T <: RingElement, U <: Integer}

Set the $i$-th coefficient of the polynomial $a$ to $c$. No check is performed on the index $i$ or for $c = 0$. It may be necessary to call combine_like_terms after calls to this function, to remove zero terms. The function must return the modified polynomial.

combine_like_terms!(a::MyMPoly{T}) where T <: RingElement

Remove zero terms and combine any adjacent terms with the same exponent vector (by adding them). It is assumed that all the exponent vectors are already in the correct order with respect to the ordering. The function must return the resulting polynomial.

set_exponent_vector!(a::MyMPoly{T}, i::Int, exps::Vector{Int}) where T <: RingElement

Set the $i$-th exponent vector to the given exponent vector. No check is performed on the index $i$, which is assumed to be valid (or that the polynomial has enough space allocated). No sorting of exponents is performed by this function. To sort the terms after setting any number of exponents with this function, run the sort_terms! function. The function must return the modified polynomial.

sort_terms!(a::MyMPoly{T}) where {T <: RingElement}

Sort the terms of the given polynomial according to the polynomial ring ordering. Zero terms and duplicate exponents are ignored. To deal with those call combine_like_terms. The sorted polynomial must be returned by the function.

Optional functionality for multivariate polynomials

The following functions can optionally be implemented for multivariate polynomial types.

Reduction by an ideal

divrem(f::MyMPoly{T}, G::Vector{MyMPoly{T}}) where T <: RingElem

As per the divrem function above, except that each term of $r$ starting with the most significant term, is reduced modulo the leading terms of each of the polynomials in the array $G$ for which the leading monomial is a divisor.

A tuple $(Q, r)$ is returned from the function, where $Q$ is an array of polynomials of the same length as $G$, and such that $f = r + \sum Q[i]G[i]$.

The result is again dependent on the ordering in general, but if the polynomials in $G$ are over a field and the reduced generators of a Groebner basis, then the result is unique.

Evaluation

evaluate(a::MyMPoly{T}, A::Vector{T}) where T <: RingElem

Evaluate the polynomial at the given values in the coefficient ring of the polynomial. The result should be an element of the coefficient ring.

evaluate(f::MyMPoly{T}, A::Vector{U}) where {T <: RingElem, U <: Integer}

Evaluate the polynomial $f$ at the values specified by the entries of the array $A$.

(a::MyMPoly{T})(vals::Union{NCRingElem, RingElement}...) where T <: RingElement

Evaluate the polynomial at the given arguments. This provides functional notation for polynomial evaluation, i.e. $f(a, b, c)$. It must be defined for each supported polynomial type (Julia does not allow functional notation to be defined for an abstract type).

The code for this function in MPoly.jl can be used when implementing this as it provides the most general possible evaluation, which is much more general than the case of evaluation at elements of the same ring.

The evaluation should succeed for any set of values for which a multiplication is defined with the product of a coefficient and all the values before it.

Note

The values at which a polynomial is evaluated may be in non-commutative rings. Products are performed in the order of the variables in the polynomial ring that the polynomial belongs to, preceded by a multiplication by the coefficient on the left.

Derivations

The following function allows to compute derivations of multivariate polynomials of type MPoly.

derivative(f::MyMPoly{T}, j::Int) where T <: RingElem

Compute the derivative of $f$ with respect to the $j$-th variable of the polynomial ring.

diff --git a/dev/mpolynomial/index.html b/dev/mpolynomial/index.html index 2ccbd1bdc..56eff7640 100644 --- a/dev/mpolynomial/index.html +++ b/dev/mpolynomial/index.html @@ -476,4 +476,4 @@ (Multivariate polynomial ring in 2 variables over finite field F_7, AbstractAlgebra.Generic.MPoly{AbstractAlgebra.GFElem{Int64}}[x, y]) julia> g = rand(S, -1:2, 3:5) -4*x^3*y^4 +4*x^3*y^4 diff --git a/dev/mseries/index.html b/dev/mseries/index.html index 44cf479f5..717fa822b 100644 --- a/dev/mseries/index.html +++ b/dev/mseries/index.html @@ -75,4 +75,4 @@ 1 + 3*y*x^2 + O(10) julia> one(R) -1 + O(10)

Power series functionality provided by AbstractAlgebra.jl

The functionality listed below is automatically provided by AbstractAlgebra.jl for absolute series over any commutative ring.

Basic functionality

The following are provided for weighted and unweighted series:

AbstractAlgebra.number_of_variablesMethod
number_of_variables(R::AbsMSeriesRing)

Return the number of variables in the series ring.

source
AbstractAlgebra.symbolsMethod
symbols(R::MSeriesRing)

Return a vector of symbols, one for each of the variables of the series ring $R$.

source
Base.precisionMethod
precision(a::AbsMSeries)

Return a vector of precisions, one for each variable in the series ring. If the ring is weighted the weighted precision is returned instead.

source
AbstractAlgebra.coeffMethod
coeff(a::AbsMSeries, n::Int)

Return the coefficient of the $n$-th nonzero term of the series (or zero if there are fewer than $n$ nonzero terms). Terms are numbered from the least significant term, i.e. the first term displayed when the series is printed.

source
AbstractAlgebra.characteristicMethod
characteristic(R::FracField{T}) where T <: RingElem

Return the characteristic of the given field.

source
AbstractAlgebra.genMethod
gen(R::AbsMSeriesRing, i::Int)

Return the $i$-th generator (variable) of the series ring $R$. Numbering starts from $1$ for the most significant variable.

source
AbstractAlgebra.gensMethod
gens(R::AbsMSeriesRing)

Return a vector of the generators (variables) of the series ring $R$, starting with the most significant.

source
AbstractAlgebra.is_genMethod
is_gen(a::AbsMSeries)

Return true if the series $a$ is a generator of its parent series ring.

source
AbstractAlgebra.is_unitMethod
is_unit(a::AbsMSeries)

Return true if the series is a unit in its series ring, i.e. if its constant term is a unit in the base ring.

source
Base.lengthMethod
length(a::AbsMSeries)

Return the number of nonzero terms in the series $a$.

source

The following are only available for unweighted series.

AbstractAlgebra.max_precisionMethod
max_precision(R::AbsMSeriesRing)

Return a vector of precision caps, one for each variable in the ring. Arithmetic operations will be performed to precisions not exceeding these values.

source
AbstractAlgebra.valuationMethod
valuation(a::AbsMSeries)

Return the valuation of $a$ as a vector of integers, one for each variable.

source

Iteration

AbstractAlgebra.coefficientsMethod
coefficients(a::AbsMSeries)

Return an array of the nonzero coefficients of the series, in the order they would be displayed, i.e. least significant term first.

source
AbstractAlgebra.exponent_vectorsMethod
exponent_vectors(a::AbsMSeries)

Return an array of the exponent vectors of the nonzero terms of the series, in the order they would be displayed, i.e. least significant term first.

source

Truncation

Base.truncateMethod
truncate(a::AbstractAlgebra.AbsMSeries, prec::Vector{Int})

Return $a$ truncated to (absolute) precisions given by the vector prec.

source
Base.truncateMethod
truncate(a::AbstractAlgebra.AbsMSeries, prec::Int)

Return $a$ truncated to precision prec. This either truncates by weight in the weighted cases or truncates each variable to precision prec in the unweighted case.

source

Exact division

AbstractAlgebra.divexactMethod
divexact(x::AbsMSeries{T}, y::AbsMSeries{T}; check::Bool=true) where T <: RingElement

Return the exact quotient of the series $x$ by the series $y$. This function currently assumes $y$ is an invertible series.

source

Evaluation

AbstractAlgebra.evaluateMethod
evaluate(a::U, vars::Vector{Int}, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the corresponding variables with indices given by the array vars. The values must be in the same ring as $a$.

source
AbstractAlgebra.evaluateMethod
evaluate(a::U, vars::Vector{U}, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the corresponding variables given by the array vars. The values must be in the same ring as $a$.

source
AbstractAlgebra.evaluateMethod
evaluate(a::U, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the variables the series ring to which $a$ belongs. The values must be in the same ring as $a$.

source

Random generation

Base.randMethod
rand(S::MSeriesRing, term_range, v...)

Return a random element of the series ring $S$ with number of terms in the range given by term_range and where coefficients of the series are randomly generated in the base ring using the data given by v. The exponents of the variable in the terms will be less than the precision caps for the Ring $S$ when it was created.

source
+1 + O(10)

Power series functionality provided by AbstractAlgebra.jl

The functionality listed below is automatically provided by AbstractAlgebra.jl for absolute series over any commutative ring.

Basic functionality

The following are provided for weighted and unweighted series:

AbstractAlgebra.number_of_variablesMethod
number_of_variables(R::AbsMSeriesRing)

Return the number of variables in the series ring.

source
AbstractAlgebra.symbolsMethod
symbols(R::MSeriesRing)

Return a vector of symbols, one for each of the variables of the series ring $R$.

source
Base.precisionMethod
precision(a::AbsMSeries)

Return a vector of precisions, one for each variable in the series ring. If the ring is weighted the weighted precision is returned instead.

source
AbstractAlgebra.coeffMethod
coeff(a::AbsMSeries, n::Int)

Return the coefficient of the $n$-th nonzero term of the series (or zero if there are fewer than $n$ nonzero terms). Terms are numbered from the least significant term, i.e. the first term displayed when the series is printed.

source
AbstractAlgebra.characteristicMethod
characteristic(R::FracField{T}) where T <: RingElem

Return the characteristic of the given field.

source
AbstractAlgebra.genMethod
gen(R::AbsMSeriesRing, i::Int)

Return the $i$-th generator (variable) of the series ring $R$. Numbering starts from $1$ for the most significant variable.

source
AbstractAlgebra.gensMethod
gens(R::AbsMSeriesRing)

Return a vector of the generators (variables) of the series ring $R$, starting with the most significant.

source
AbstractAlgebra.is_genMethod
is_gen(a::AbsMSeries)

Return true if the series $a$ is a generator of its parent series ring.

source
AbstractAlgebra.is_unitMethod
is_unit(a::AbsMSeries)

Return true if the series is a unit in its series ring, i.e. if its constant term is a unit in the base ring.

source
Base.lengthMethod
length(a::AbsMSeries)

Return the number of nonzero terms in the series $a$.

source

The following are only available for unweighted series.

AbstractAlgebra.max_precisionMethod
max_precision(R::AbsMSeriesRing)

Return a vector of precision caps, one for each variable in the ring. Arithmetic operations will be performed to precisions not exceeding these values.

source
AbstractAlgebra.valuationMethod
valuation(a::AbsMSeries)

Return the valuation of $a$ as a vector of integers, one for each variable.

source

Iteration

AbstractAlgebra.coefficientsMethod
coefficients(a::AbsMSeries)

Return an array of the nonzero coefficients of the series, in the order they would be displayed, i.e. least significant term first.

source
AbstractAlgebra.exponent_vectorsMethod
exponent_vectors(a::AbsMSeries)

Return an array of the exponent vectors of the nonzero terms of the series, in the order they would be displayed, i.e. least significant term first.

source

Truncation

Base.truncateMethod
truncate(a::AbstractAlgebra.AbsMSeries, prec::Vector{Int})

Return $a$ truncated to (absolute) precisions given by the vector prec.

source
Base.truncateMethod
truncate(a::AbstractAlgebra.AbsMSeries, prec::Int)

Return $a$ truncated to precision prec. This either truncates by weight in the weighted cases or truncates each variable to precision prec in the unweighted case.

source

Exact division

AbstractAlgebra.divexactMethod
divexact(x::AbsMSeries{T}, y::AbsMSeries{T}; check::Bool=true) where T <: RingElement

Return the exact quotient of the series $x$ by the series $y$. This function currently assumes $y$ is an invertible series.

source

Evaluation

AbstractAlgebra.evaluateMethod
evaluate(a::U, vars::Vector{Int}, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the corresponding variables with indices given by the array vars. The values must be in the same ring as $a$.

source
AbstractAlgebra.evaluateMethod
evaluate(a::U, vars::Vector{U}, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the corresponding variables given by the array vars. The values must be in the same ring as $a$.

source
AbstractAlgebra.evaluateMethod
evaluate(a::U, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the variables the series ring to which $a$ belongs. The values must be in the same ring as $a$.

source

Random generation

Base.randMethod
rand(S::MSeriesRing, term_range, v...)

Return a random element of the series ring $S$ with number of terms in the range given by term_range and where coefficients of the series are randomly generated in the base ring using the data given by v. The exponents of the variable in the terms will be less than the precision caps for the Ring $S$ when it was created.

source
diff --git a/dev/ncpolynomial/index.html b/dev/ncpolynomial/index.html index ccff27bd6..b1b5beb1f 100644 --- a/dev/ncpolynomial/index.html +++ b/dev/ncpolynomial/index.html @@ -210,4 +210,4 @@ julia> h = derivative(f) [2 0; 0 2]*x*y + x + 1 - + diff --git a/dev/ncring_interface/index.html b/dev/ncring_interface/index.html index 92c316d16..7a365d2b3 100644 --- a/dev/ncring_interface/index.html +++ b/dev/ncring_interface/index.html @@ -1,3 +1,3 @@ Noncommutative ring Interface · AbstractAlgebra.jl

Noncommutative ring Interface

AbstractAlgebra.jl supports commutative rings through its Ring interface. In this section we describe the corresponding interface for noncommutative rings. The two interfaces are very similar in terms of required functionality, and so we mainly document the differences here.

Noncommutative rings can be supported through the abstract types NCRing and NCRingElem. Note that we have Ring <: NCRing, etc., so the interface here should more correctly be called the Not-necessarily-Commutative-ring interface.

However, the fact remains that if one wishes to implement a noncommutative ring, one should make its type belong to NCRing but not to Ring. Therefore it is not too much of a mistake to think of the NCRing interface as being for noncommutative rings.

Types

As for the Ring interface, most noncommutative rings must supply two types:

  • a type for the parent object (representing the ring itself)
  • a type for elements of that ring

The parent type must belong to NCRing and the element type must belong to NCRingElem. Of course, the types may belong to these abstract types transitively via an intermediate abstract type.

Also as for the Ring interface, it is advised to make the types of generic parameterised rings that belong to NCRing and NCRingElem depend on the type of the elements of that parameter ring.

NCRingElement type union

As for the Ring interface, the NCRing interface provides a union type NCRingElement in src/julia/JuliaTypes.jl which is a union of NCRingElem and the Julia types Integer, Rational and AbstractFloat.

Most of the generic code in AbstractAlgebra for general rings makes use of the union type NCRingElement instead of NCRingElem so that the generic functions also accept the Julia Base ring types.

As per usual, one may need to implement one ad hoc binary operation for each concrete type belonging to NCRingElement to avoid ambiguity warnings.

Parent object caches

Parent object caches for the NCRing interface operate as per the Ring interface.

Required functions for all rings

Generic functions may only rely on required functionality for the NCRing interface, which must be implemented by all noncommutative rings.

Most of this required functionality is the same as for the Ring interface, so we refer the reader there for details, with the following modifications.

We give this interface for fictitious types MyParent for the type of the ring parent object R and MyElem for the type of the elements of the ring.

Exact division

divexact_left(f::MyElem, g::MyElem)
-divexact_right(f::MyElem, g::MyElem)

If $f = ga$ for some $a$ in the ring, the function divexact_left(f, g) returns a. If $f = ag$ then divexact_right(f, g) returns a. A DivideError() should be thrown if division is by zero. If no exact quotient exists or an impossible inverse is unavoidably encountered, an error should be thrown.

+divexact_right(f::MyElem, g::MyElem)

If $f = ga$ for some $a$ in the ring, the function divexact_left(f, g) returns a. If $f = ag$ then divexact_right(f, g) returns a. A DivideError() should be thrown if division is by zero. If no exact quotient exists or an impossible inverse is unavoidably encountered, an error should be thrown.

diff --git a/dev/perm/index.html b/dev/perm/index.html index 3c2f3ea94..6cd36e27d 100644 --- a/dev/perm/index.html +++ b/dev/perm/index.html @@ -185,4 +185,4 @@ (1,2)(3,4) julia> Generic.emb!(Perm(collect(1:5)), p, [3,1,4,5]) -(1,3)(4,5)source +(1,3)(4,5)source diff --git a/dev/poly_interface/index.html b/dev/poly_interface/index.html index 2ba5de61e..bd7a3d5f8 100644 --- a/dev/poly_interface/index.html +++ b/dev/poly_interface/index.html @@ -1,4 +1,4 @@ Univariate Polynomial Ring Interface · AbstractAlgebra.jl

Univariate Polynomial Ring Interface

Univariate polynomial rings are supported in AbstractAlgebra, and in addition to the standard Ring interface, numerous additional functions are required to be present for univariate polynomial rings.

Univariate polynomial rings can be built over both commutative and noncommutative rings.

Univariate polynomial rings over a field are also Euclidean and therefore such rings must implement the Euclidean interface.

Since a sparse distributed multivariate format can generally also handle sparse univariate polynomials, the univariate polynomial interface is designed around the assumption that they are dense. This is not a requirement, but it may be easier to use the multivariate interface for sparse univariate types.

Types and parents

AbstractAlgebra provides two abstract types for polynomial rings and their elements over a commutative ring:

  • PolyRing{T} is the abstract type for univariate polynomial ring parent types
  • PolyRingElem{T} is the abstract type for univariate polynomial types

Similarly there are two abstract types for polynomial rings and their elements over a noncommutative ring:

  • NCPolyRing{T} is the abstract type for univariate polynomial ring parent types
  • NCPolyRingElem{T} is the abstract type for univariate polynomial types

We have that PolyRing{T} <: Ring and PolyRingElem{T} <: RingElem. Similarly we have that NCPolyRing{T} <: NCRing and NCPolyRingElem{T} <: NCRingElem.

Note that the abstract types are parameterised. The type T should usually be the type of elements of the coefficient ring of the polynomial ring. For example, in the case of $\mathbb{Z}[x]$ the type T would be the type of an integer, e.g. BigInt.

If the parent object for such a ring has type MyZX and polynomials in that ring have type MyZXPoly then one would have:

  • MyZX <: PolyRing{BigInt}
  • MyZXPoly <: PolyRingElem{BigInt}

Polynomial rings should be made unique on the system by caching parent objects (unless an optional cache parameter is set to false). Polynomial rings should at least be distinguished based on their base (coefficient) ring. But if they have the same base ring and symbol (for their variable/generator), they should certainly have the same parent object.

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Required functionality for univariate polynomials

In addition to the required functionality for the Ring/NCRing interface (and in the case of polynomials over a field, the Euclidean Ring interface), the Polynomial Ring interface has the following required functions.

We suppose that R is a fictitious base ring (coefficient ring) and that S is a univariate polynomial ring over R (i.e. $S = R[x]$) with parent object S of type MyPolyRing{T}. We also assume the polynomials in the ring have type MyPoly{T}, where T is the type of elements of the base (coefficient) ring.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElem or NCRingElem.

We describe the functionality below for polynomials over commutative rings, i.e. with element type belonging to RingElem, however similar constructors should be available for element types belonging to NCRingElem instead, if the coefficient ring is noncommutative.

Constructors

In addition to the standard constructors, the following constructors, taking an array of coefficients, must be available.

(S::MyPolyRing{T})(A::Vector{T}) where T <: RingElem
 (S::MyPolyRing{T})(A::Vector{U}) where T <: RingElem, U <: RingElem
-(S::MyPolyRing{T})(A::Vector{U}) where T <: RingElem, U <: Integer

Create the polynomial in the given ring whose degree $i$ coefficient is given by A[1 + i]. The elements of the array are assumed to be able to be coerced into the base ring R. If the argument is an empty vector, the zero polynomial shall be returned.

It may be desirable to have a additional version of the function that accepts an array of Julia Int values if this can be done more efficiently.

It is also possible to create polynomials directly without first creating the corresponding polynomial ring.

polynomial(R::Ring, arr::Vector{T}, var::VarName=:x; cached::Bool=true)

Given an array of coefficients construct the polynomial with those coefficients over the given ring and with the given variable.

Note

If cached is set to false then the parent ring of the created polynomial is not cached. However, this means that subsequent polynomials created in the same way will not be compatible. Instead, one should use the parent object of the first polynomial to create subsequent polynomials instead of calling this function repeatedly with cached=false.

Data type and parent object methods

var(S::MyPolyRing{T}) where T <: RingElem

Return a Symbol representing the variable (generator) of the polynomial ring. Note that this is a Symbol not a String, though its string value will usually be used when printing polynomials.

symbols(S::MyPolyRing{T}) where T <: RingElem

Return the array [s] where s is a Symbol representing the variable of the given polynomial ring. This is provided for uniformity with the multivariate interface, where there is more than one variable and hence an array of symbols.

dense_poly_type(::Type{T}) where T <: RingElement

Return the type of a polynomial whose coefficients have the given type. In our example MyPoly{T}.

This function is defined for generic polynomials and only needs to be defined for custom polynomial rings, e.g. ones defined by a C implementation.

The default implementation figures out the appropriate polynomial ring type via dense_poly_type and calls its constructor with R, s, cached as arguments. In our example, this would be

MyPolyRing{T}(R, s, cached)

Accordingly, polynomial_ring_only only needs to be defined, if such a constructor does not exist or other behaviour is wanted.

Basic manipulation of rings and elements

length(f::MyPoly{T}) where T <: RingElem

Return the length of the given polynomial. The length of the zero polynomial is defined to be $0$, otherwise the length is the degree plus $1$. The return value should be of type Int.

set_length!(f::MyPoly{T}, n::Int) where T <: RingElem

This function must zero any coefficients beyond the requested length $n$ and then set the length of the polynomial to $n$. This function does not need to normalise the polynomial and is not useful to the user, but is used extensively by the AbstractAlgebra generic functionality.

This function returns the resulting polynomial.

coeff(f::MyPoly{T}, n::Int) where T <: RingElem

Return the coefficient of the polynomial f of degree n. If n is larger than the degree of the polynomial, it should return zero in the coefficient ring.

setcoeff!(f::MyPoly{T}, n::Int, a::T) where T <: RingElem

Set the degree $n$ coefficient of $f$ to $a$. This mutates the polynomial in-place if possible and returns the mutated polynomial (so that immutable types can also be supported). The function must not assume that the polynomial already has space for $n + 1$ coefficients. The polynomial must be resized if this is not the case.

Note that this function is not required to normalise the polynomial and is not necessarily useful to the user, but is used extensively by the generic functionality in AbstractAlgebra.jl. It is for setting raw coefficients in the representation.

normalise(f::MyPoly{T}, n::Int) where T <: RingElem

Given a polynomial whose length is currently $n$, including any leading zero coefficients, return the length of the normalised polynomial (either zero or the length of the polynomial with nonzero leading coefficient). Note that the function does not actually perform the normalisation.

fit!(f::MyPoly{T}, n::Int) where T <: RingElem

Ensure that the polynomial $f$ internally has space for $n$ coefficients. This function must mutate the function in-place if it is mutable. It does not return the mutated polynomial. Immutable types can still be supported by defining this function to do nothing.

Some interfaces for C polynomial types automatically manage the internal allocation of polynomials in every function that can be called on them. Explicit adjustment by the generic code in AbstractAlgebra.jl is not required. In such cases, this function can also be defined to do nothing.

Optional functionality for polynomial rings

Sometimes parts of the Euclidean Ring interface can and should be implemented for polynomials over a ring that is not necessarily a field.

When divisibility testing can be implemented for a polynomial ring over a field, it should be possible to implement the following functions from the Euclidean Ring interface:

  • divides
  • remove
  • valuation

When the given polynomial ring is a GCD domain, with an effective GCD algorithm, it may be possible to implement the following functions:

  • gcd
  • lcm

Polynomial rings can optionally implement any part of the generic univariate polynomial functionality provided by AbstractAlgebra.jl, using the same interface.

Obviously additional functionality can also be added to that provided by AbstractAlgebra.jl on an ad hoc basis.

Similar

The similar function is available for all univariate polynomial types, but new polynomial rings can define a specialised version of it if required.

similar(x::MyPoly{T}, R::Ring=base_ring(x), var::VarName=var(parent(x))) where T <: RingElem

Construct the zero polynomial with the given variable and coefficients in the given ring, if specified, and with the defaults shown if not.

Custom polynomial rings may choose which polynomial type is best-suited to return for any given arguments. If they don't specialise the function the default polynomial type returned is a Generic.Poly.

+(S::MyPolyRing{T})(A::Vector{U}) where T <: RingElem, U <: Integer

Create the polynomial in the given ring whose degree $i$ coefficient is given by A[1 + i]. The elements of the array are assumed to be able to be coerced into the base ring R. If the argument is an empty vector, the zero polynomial shall be returned.

It may be desirable to have a additional version of the function that accepts an array of Julia Int values if this can be done more efficiently.

It is also possible to create polynomials directly without first creating the corresponding polynomial ring.

polynomial(R::Ring, arr::Vector{T}, var::VarName=:x; cached::Bool=true)

Given an array of coefficients construct the polynomial with those coefficients over the given ring and with the given variable.

Note

If cached is set to false then the parent ring of the created polynomial is not cached. However, this means that subsequent polynomials created in the same way will not be compatible. Instead, one should use the parent object of the first polynomial to create subsequent polynomials instead of calling this function repeatedly with cached=false.

Data type and parent object methods

var(S::MyPolyRing{T}) where T <: RingElem

Return a Symbol representing the variable (generator) of the polynomial ring. Note that this is a Symbol not a String, though its string value will usually be used when printing polynomials.

symbols(S::MyPolyRing{T}) where T <: RingElem

Return the array [s] where s is a Symbol representing the variable of the given polynomial ring. This is provided for uniformity with the multivariate interface, where there is more than one variable and hence an array of symbols.

dense_poly_type(::Type{T}) where T <: RingElement

Return the type of a polynomial whose coefficients have the given type. In our example MyPoly{T}.

This function is defined for generic polynomials and only needs to be defined for custom polynomial rings, e.g. ones defined by a C implementation.

AbstractAlgebra.polynomial_ring_onlyMethod
polynomial_ring_only(R::NCRing, s::Symbol; cached::Bool=true)

Like polynomial_ring(R::NCRing, s::Symbol) but return only the polynomial ring.

source

The default implementation figures out the appropriate polynomial ring type via dense_poly_type and calls its constructor with R, s, cached as arguments. In our example, this would be

MyPolyRing{T}(R, s, cached)

Accordingly, polynomial_ring_only only needs to be defined, if such a constructor does not exist or other behaviour is wanted.

Basic manipulation of rings and elements

length(f::MyPoly{T}) where T <: RingElem

Return the length of the given polynomial. The length of the zero polynomial is defined to be $0$, otherwise the length is the degree plus $1$. The return value should be of type Int.

set_length!(f::MyPoly{T}, n::Int) where T <: RingElem

This function must zero any coefficients beyond the requested length $n$ and then set the length of the polynomial to $n$. This function does not need to normalise the polynomial and is not useful to the user, but is used extensively by the AbstractAlgebra generic functionality.

This function returns the resulting polynomial.

coeff(f::MyPoly{T}, n::Int) where T <: RingElem

Return the coefficient of the polynomial f of degree n. If n is larger than the degree of the polynomial, it should return zero in the coefficient ring.

setcoeff!(f::MyPoly{T}, n::Int, a::T) where T <: RingElem

Set the degree $n$ coefficient of $f$ to $a$. This mutates the polynomial in-place if possible and returns the mutated polynomial (so that immutable types can also be supported). The function must not assume that the polynomial already has space for $n + 1$ coefficients. The polynomial must be resized if this is not the case.

Note that this function is not required to normalise the polynomial and is not necessarily useful to the user, but is used extensively by the generic functionality in AbstractAlgebra.jl. It is for setting raw coefficients in the representation.

normalise(f::MyPoly{T}, n::Int) where T <: RingElem

Given a polynomial whose length is currently $n$, including any leading zero coefficients, return the length of the normalised polynomial (either zero or the length of the polynomial with nonzero leading coefficient). Note that the function does not actually perform the normalisation.

fit!(f::MyPoly{T}, n::Int) where T <: RingElem

Ensure that the polynomial $f$ internally has space for $n$ coefficients. This function must mutate the function in-place if it is mutable. It does not return the mutated polynomial. Immutable types can still be supported by defining this function to do nothing.

Some interfaces for C polynomial types automatically manage the internal allocation of polynomials in every function that can be called on them. Explicit adjustment by the generic code in AbstractAlgebra.jl is not required. In such cases, this function can also be defined to do nothing.

Optional functionality for polynomial rings

Sometimes parts of the Euclidean Ring interface can and should be implemented for polynomials over a ring that is not necessarily a field.

When divisibility testing can be implemented for a polynomial ring over a field, it should be possible to implement the following functions from the Euclidean Ring interface:

When the given polynomial ring is a GCD domain, with an effective GCD algorithm, it may be possible to implement the following functions:

Polynomial rings can optionally implement any part of the generic univariate polynomial functionality provided by AbstractAlgebra.jl, using the same interface.

Obviously additional functionality can also be added to that provided by AbstractAlgebra.jl on an ad hoc basis.

Similar

The similar function is available for all univariate polynomial types, but new polynomial rings can define a specialised version of it if required.

similar(x::MyPoly{T}, R::Ring=base_ring(x), var::VarName=var(parent(x))) where T <: RingElem

Construct the zero polynomial with the given variable and coefficients in the given ring, if specified, and with the defaults shown if not.

Custom polynomial rings may choose which polynomial type is best-suited to return for any given arguments. If they don't specialise the function the default polynomial type returned is a Generic.Poly.

diff --git a/dev/polynomial/index.html b/dev/polynomial/index.html index 5d5ebc23a..14430532a 100644 --- a/dev/polynomial/index.html +++ b/dev/polynomial/index.html @@ -514,4 +514,4 @@ julia> G = hom(Zx, Fpy, c -> Fp(c), y^3); julia> G(5*x + 1) -2*y^3 + 1source +2*y^3 + 1source diff --git a/dev/puiseux/index.html b/dev/puiseux/index.html index 0f80020c6..a3dd711a3 100644 --- a/dev/puiseux/index.html +++ b/dev/puiseux/index.html @@ -154,4 +154,4 @@ julia> h = sqrt(a) 1 + 1//2*z + 11//8*z^2 - 11//16*z^3 - 77//128*z^4 + O(z^5) - + diff --git a/dev/quotient_module/index.html b/dev/quotient_module/index.html index e3057f222..7ef31368c 100644 --- a/dev/quotient_module/index.html +++ b/dev/quotient_module/index.html @@ -62,4 +62,4 @@ julia> dim(Q) 1 - + diff --git a/dev/rand/index.html b/dev/rand/index.html index c9888d9ac..2be439ad9 100644 --- a/dev/rand/index.html +++ b/dev/rand/index.html @@ -50,4 +50,4 @@ R, x = polynomial_ring(ZZ, :x) -test_rand(R, -1:10, -10:10)

In general, we try to use UnitRange's to specify how 'big' we want the random instance to be, e.g. the range of degrees a polynomial could take, the range random integers could lie in, etc. The objective is to make it easy for the user to control the 'size' of random values in test code.

+test_rand(R, -1:10, -10:10)

In general, we try to use UnitRange's to specify how 'big' we want the random instance to be, e.g. the range of degrees a polynomial could take, the range random integers could lie in, etc. The objective is to make it easy for the user to control the 'size' of random values in test code.

diff --git a/dev/rational/index.html b/dev/rational/index.html index 138618b46..b0173a14d 100644 --- a/dev/rational/index.html +++ b/dev/rational/index.html @@ -55,4 +55,4 @@ true julia> root(ZZ(27)//64, 3) -3//4 +3//4 diff --git a/dev/real/index.html b/dev/real/index.html index b6632835f..2191e9030 100644 --- a/dev/real/index.html +++ b/dev/real/index.html @@ -48,4 +48,4 @@ julia> m = inv(g) 0.07291666666666666666666666666666666666666666666666666666666666666666666666666631 - + diff --git a/dev/residue/index.html b/dev/residue/index.html index 4ea334b75..f444d3c13 100644 --- a/dev/residue/index.html +++ b/dev/residue/index.html @@ -113,4 +113,4 @@ (Univariate polynomial ring in x over rationals, x) julia> g = rand(S, 2:2, -10:10) --1//4*x^2 - 2//7*x + 1 +-1//4*x^2 - 2//7*x + 1 diff --git a/dev/residue_interface/index.html b/dev/residue_interface/index.html index 9b16bdcc8..ff1b49398 100644 --- a/dev/residue_interface/index.html +++ b/dev/residue_interface/index.html @@ -1,3 +1,3 @@ Residue Ring Interface · AbstractAlgebra.jl

Residue Ring Interface

Residue rings (currently a quotient ring modulo a principal ideal) are supported in AbstractAlgebra.jl, at least for Euclidean base rings. There is also partial support for residue rings of polynomial rings where the modulus has invertible leading coefficient.

In addition to the standard Ring interface, some additional functions are required to be present for residue rings.

Types and parents

AbstractAlgebra provides four abstract types for residue rings and their elements:

  • ResidueRing{T} is the abstract type for residue ring parent types
  • ResidueField{T} is the abstract type for residue rings known to be fields
  • ResElem{T} is the abstract type for types of elements of residue rings (residues)
  • ResFieldElem{T} is the abstract type for types of elements of residue fields

We have that ResidueRing{T} <: AbstractAlgebra.Ring and ResElem{T} <: AbstractAlgebra.RingElem.

Note that these abstract types are parameterised. The type T should usually be the type of elements of the base ring of the residue ring/field.

If the parent object for a residue ring has type MyResRing and residues in that ring have type MyRes then one would have:

  • MyResRing <: ResidueRing{BigInt}
  • MyRes <: ResElem{BigInt}

Residue rings should be made unique on the system by caching parent objects (unless an optional cache parameter is set to false). Residue rings should at least be distinguished based on their base ring and modulus (the principal ideal one is taking a quotient of the base ring by).

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Required functionality for residue rings

In addition to the required functionality for the Ring interface the Residue Ring interface has the following required functions.

We suppose that R is a fictitious base ring, $m$ is an element of that ring, and that S is the residue ring (quotient ring) $R/(m)$ with parent object S of type MyResRing{T}. We also assume the residues $r \pmod{m}$ in the residue ring have type MyRes{T}, where T is the type of elements of the base ring.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElem.

Data type and parent object methods

modulus(S::MyResRing{T}) where T <: AbstractAlgebra.RingElem

Return the modulus of the given residue ring, i.e. if the residue ring $S$ was specified to be $R/(m)$, return $m$.

Basic manipulation of rings and elements

data(f::MyRes{T}) where T <: RingElem
-lift(f::MyRes{T}) where T <: RingElem

Given a residue $r \pmod{m}$, represented as such, return $r$. In the special case where machine integers are used to represent the residue, data will return the machine integer, whereas lift will return a multiprecision integer. Otherwise lift falls back to data by default.

+lift(f::MyRes{T}) where T <: RingElem

Given a residue $r \pmod{m}$, represented as such, return $r$. In the special case where machine integers are used to represent the residue, data will return the machine integer, whereas lift will return a multiprecision integer. Otherwise lift falls back to data by default.

diff --git a/dev/ring/index.html b/dev/ring/index.html index bcc21cf7a..c9a976f42 100644 --- a/dev/ring/index.html +++ b/dev/ring/index.html @@ -32,4 +32,4 @@ mod!(a, b)

Return mod(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for mod(a, a, b).

source
AbstractAlgebra.gcd!Function
gcd!(z, a, b)
 gcd!(a, b)

Return gcd(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for gcd(a, a, b).

source
AbstractAlgebra.lcm!Function
lcm!(z, a, b)
 lcm!(a, b)

Return lcm(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for lcm(a, a, b).

source

Random generation

The Julia random interface is implemented for all ring parents (instead of for types). The exact interface differs depending on the ring, but the parameters supplied are usually ranges, e.g. -1:10 for the range of allowed degrees for a univariate polynomial.

rand(R::NCRing, v...)

Factorization

For commutative rings supporting factorization and irreducibility testing, the following optional functions may be implemented.

AbstractAlgebra.is_irreducibleMethod
is_irreducible(a::RingElement)

Return true if $a$ is irreducible, else return false. Zero and units are by definition never irreducible.

source
AbstractAlgebra.is_squarefreeMethod
is_squarefree(a::RingElement)

Return true if $a$ is squarefree, else return false. An element is squarefree if it it is not divisible by any squares except the squares of units.

source
factor(a::T) where T <: RingElement
-factor_squarefree(a::T) where T <: RingElement

Return a factorization into irreducible or squarefree elements, respectively. The return is an object of type Fac{T}.

AbstractAlgebra.FacType
Fac{T <: RingElement}

Type for factored ring elements. The structure holds a unit of type T and is an iterable collection of T => Int pairs for the factors and exponents.

See unit(a::Fac), evaluate(a::Fac).

source
AbstractAlgebra.unitMethod
unit(a::Fac{T}) -> T

Return the unit of the factorization.

source
AbstractAlgebra.evaluateMethod
evaluate(a::Fac{T}) -> T

Multiply out the factorization into a single element.

source
Base.getindexMethod
getindex(a::Fac, b) -> Int

If $b$ is a factor of $a$, the corresponding exponent is returned. Otherwise an error is thrown.

source
Base.setindex!Method
setindex!(a::Fac{T}, c::Int, b::T)

If $b$ is a factor of $a$, the corresponding entry is set to $c$.

source
+factor_squarefree(a::T) where T <: RingElement

Return a factorization into irreducible or squarefree elements, respectively. The return is an object of type Fac{T}.

AbstractAlgebra.FacType
Fac{T <: RingElement}

Type for factored ring elements. The structure holds a unit of type T and is an iterable collection of T => Int pairs for the factors and exponents.

See unit(a::Fac), evaluate(a::Fac).

source
AbstractAlgebra.unitMethod
unit(a::Fac{T}) -> T

Return the unit of the factorization.

source
AbstractAlgebra.evaluateMethod
evaluate(a::Fac{T}) -> T

Multiply out the factorization into a single element.

source
Base.getindexMethod
getindex(a::Fac, b) -> Int

If $b$ is a factor of $a$, the corresponding exponent is returned. Otherwise an error is thrown.

source
Base.setindex!Method
setindex!(a::Fac{T}, c::Int, b::T)

If $b$ is a factor of $a$, the corresponding entry is set to $c$.

source
diff --git a/dev/ring_interface/index.html b/dev/ring_interface/index.html index b6452c85c..45042760d 100644 --- a/dev/ring_interface/index.html +++ b/dev/ring_interface/index.html @@ -269,4 +269,4 @@ return R(rand(base_ring(R), 1:6, -999:999)) end -test_Ring_interface(constant_polynomial_ring(S)) +test_Ring_interface(constant_polynomial_ring(S)) diff --git a/dev/ring_introduction/index.html b/dev/ring_introduction/index.html index 1039bea29..4022460ed 100644 --- a/dev/ring_introduction/index.html +++ b/dev/ring_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

A rich ring hierarchy is provided, supporting both commutative and noncommutative rings.

A number of basic rings are provided, such as the integers, integers mod n and numerous fields.

A recursive rings implementation is then built on top of the basic rings via a number of generic ring constructions. These include univariate and multivariate polynomials and power series, univariate Laurent and Puiseux series, residue rings, matrix algebras, etc.

Where possible, these constructions can be built on top of one another in generic towers.

The ring hierarchy can be extended by implementing new rings to follow one or more ring interfaces. Generic functionality provided by the system is then automatically available for the new rings. These implementations can either be generic or can be specialised implementations provided by, for example, a C library.

In most cases, the interfaces consist of a set of constructors and functions that must be implemented to satisfy the interface. These are the functions that the generic code relies on being available.

+Introduction · AbstractAlgebra.jl

Introduction

A rich ring hierarchy is provided, supporting both commutative and noncommutative rings.

A number of basic rings are provided, such as the integers, integers mod n and numerous fields.

A recursive rings implementation is then built on top of the basic rings via a number of generic ring constructions. These include univariate and multivariate polynomials and power series, univariate Laurent and Puiseux series, residue rings, matrix algebras, etc.

Where possible, these constructions can be built on top of one another in generic towers.

The ring hierarchy can be extended by implementing new rings to follow one or more ring interfaces. Generic functionality provided by the system is then automatically available for the new rings. These implementations can either be generic or can be specialised implementations provided by, for example, a C library.

In most cases, the interfaces consist of a set of constructors and functions that must be implemented to satisfy the interface. These are the functions that the generic code relies on being available.

diff --git a/dev/series/index.html b/dev/series/index.html index 38e346e9a..89b8fc637 100644 --- a/dev/series/index.html +++ b/dev/series/index.html @@ -299,4 +299,4 @@ (Univariate power series ring over integers, x + O(x^11)) julia> f = rand(R, 3:5, -10:10) -3*x^4 - x^5 + 4*x^7 + 4*x^8 - 7*x^9 + 2*x^10 + 4*x^11 - x^12 - 4*x^13 + O(x^14) +3*x^4 - x^5 + 4*x^7 + 4*x^8 - 7*x^9 + 2*x^10 + 4*x^11 - x^12 - 4*x^13 + O(x^14) diff --git a/dev/series_interface/index.html b/dev/series_interface/index.html index 45dbfe88d..56f0b1f72 100644 --- a/dev/series_interface/index.html +++ b/dev/series_interface/index.html @@ -15,4 +15,4 @@ zero(x::MySeries, R::Ring, max_prec::Int, var::VarName; cached::Bool=true) zero(x::MySeries, R::Ring, var::VarName; cached::Bool=true) zero(x::MySeries, max_prec::Int, var::VarName; cached::Bool=true) -zero(x::MySeries, var::VarName; cached::Bool=true)

As above, but use the precision cap of the parent ring of x and the base_ring of x if these are not specified.

Custom series rings may choose which series type is best-suited to return for the given coefficient ring, precision cap and variable, however they should return a series with the same model as x, i.e. relative or series.

If custom implementations don't specialise these function the default return type is a Generic.AbsSeries or Generic.RelSeries.

The default implementation of zero calls out to similar, so it's generally sufficient to specialise only similar. For both similar and zero only the most general method has to be implemented as all other methods call out to this more general method.

+zero(x::MySeries, var::VarName; cached::Bool=true)

As above, but use the precision cap of the parent ring of x and the base_ring of x if these are not specified.

Custom series rings may choose which series type is best-suited to return for the given coefficient ring, precision cap and variable, however they should return a series with the same model as x, i.e. relative or series.

If custom implementations don't specialise these function the default return type is a Generic.AbsSeries or Generic.RelSeries.

The default implementation of zero calls out to similar, so it's generally sufficient to specialise only similar. For both similar and zero only the most general method has to be implemented as all other methods call out to this more general method.

diff --git a/dev/submodule/index.html b/dev/submodule/index.html index 4c052cb91..48c3ff5c3 100644 --- a/dev/submodule/index.html +++ b/dev/submodule/index.html @@ -83,4 +83,4 @@ (Submodule over integers with 1 generator and no relations, Hom: submodule over integers with 1 generator and no relations -> free module of rank 2 over integers) julia> I = intersect(N1, N2) -Any[] +Any[] diff --git a/dev/total_fraction/index.html b/dev/total_fraction/index.html index 9299f7eb7..805a81189 100644 --- a/dev/total_fraction/index.html +++ b/dev/total_fraction/index.html @@ -104,4 +104,4 @@ Total ring of fractions of univariate polynomial ring julia> g = rand(S, -1:3, -10:10) -(4*x + 4)//(-4*x^2 - x + 4) +(4*x + 4)//(-4*x^2 - x + 4) diff --git a/dev/types/index.html b/dev/types/index.html index 436b8f55f..d8a12a3fd 100644 --- a/dev/types/index.html +++ b/dev/types/index.html @@ -15,4 +15,4 @@ true julia> parent(f) == R -true +true diff --git a/dev/univpolynomial/index.html b/dev/univpolynomial/index.html index d30723290..4cea16b1e 100644 --- a/dev/univpolynomial/index.html +++ b/dev/univpolynomial/index.html @@ -14,4 +14,4 @@ (y, z) julia> number_of_generators(S) -3

Universal polynomial functionality

The universal polynomial ring behaves exactly like a multivariate polynomial ring with the few differences noted above.

The only functionality not implemented is the ability to do divrem by an ideal of polynomials.

The universal polynomial ring is very useful for doing symbolic manipulation. However, it is important to understand that AbstractAlgebra is not a symbolic system and the performance of the universal polynomial ring will closely match that of a multivariate polynomial ring with the same number of variables.

The disadvantage of this approach to symbolic manipulation is that some manipulations that would be offered by a symbolic system are not available, as variables are not identified by their names alone in AbstractAlgebra, as would be the case symbolically, but by objects.

The most powerful symbolic tools we offer are the generalised evaluation functions, the multivariate coefficient functionality, the ability to change coefficient ring and to map coefficients according to a supplied function and the ability to convert a multivariate which happens to have just one variable into a dense univariate polynomial.

Further facilities may be added in future to ease symbolic manipulations.

+3

Universal polynomial functionality

The universal polynomial ring behaves exactly like a multivariate polynomial ring with the few differences noted above.

The only functionality not implemented is the ability to do divrem by an ideal of polynomials.

The universal polynomial ring is very useful for doing symbolic manipulation. However, it is important to understand that AbstractAlgebra is not a symbolic system and the performance of the universal polynomial ring will closely match that of a multivariate polynomial ring with the same number of variables.

The disadvantage of this approach to symbolic manipulation is that some manipulations that would be offered by a symbolic system are not available, as variables are not identified by their names alone in AbstractAlgebra, as would be the case symbolically, but by objects.

The most powerful symbolic tools we offer are the generalised evaluation functions, the multivariate coefficient functionality, the ability to change coefficient ring and to map coefficients according to a supplied function and the ability to convert a multivariate which happens to have just one variable into a dense univariate polynomial.

Further facilities may be added in future to ease symbolic manipulations.

diff --git a/dev/visualizing_types/index.html b/dev/visualizing_types/index.html index 43a4cac6d..0fef10b05 100644 --- a/dev/visualizing_types/index.html +++ b/dev/visualizing_types/index.html @@ -1,2 +1,2 @@ -Visualization of the types of AbstractAlgebra.jl · AbstractAlgebra.jl

Visualization of the types of AbstractAlgebra.jl

AbstractAlgebra.jl implements a couple of abstract types which can be extended.

Abstract parents

The following diagram shows a complete list of all abstract types in AbstractAlgebra.jl.

Diagram of parent types

Abstract elements

Similarly the following diagram shows a complete list of all abstract types in AbstractAlgebra.jl.

Diagram of element types

Concrete types in AbstractAlgebra.jl

Until now we have discussed the abstract types of AbstractAlgebra.jl. Under this subsection we will instead give some examples of concrete types in AbstractAlgebra.jl.

In parentheses we put the types of the corresponding parent objects.

  • Perm{<:Integer} (SymmetricGroup{<:Integer})
  • GFElem{<:Integer} (GFField{<:Integer})

We also think of various Julia types as though they were AbstractAlgebra.jl types:

  • BigInt (Integers{BigInt})
  • Rational{BigInt} (Rationals{BigInt})

Then there are various types for generic constructions over a base ring. They are all parameterised by a type T which is the type of the elements of the base ring they are defined over.

  • Generic.Poly{T} (Generic.PolyRing{T})
  • Generic.MPoly{T} (Generic.MPolyRing{T})
  • Generic.RelSeries{T} (Generic.RelPowerSeriesRing{T})
  • Generic.AbsSeries{T} (Generic.AbsPowerSeriesRing{T})
  • Generic.LaurentSeriesRingElem{T} (Generic.LaurentSeriesRing{T})
  • Generic.LaurentSeriesFieldElem{T} (Generic.LaurentSeriesField{T})
  • Generic.ResidueRingElem{T} (Generic.ResidueRing{T})
  • Generic.FracFieldElem{T} (Generic.FracField{T})
  • Generic.Mat{T} (Generic.MatSpace{T})
+Visualization of the types of AbstractAlgebra.jl · AbstractAlgebra.jl

Visualization of the types of AbstractAlgebra.jl

AbstractAlgebra.jl implements a couple of abstract types which can be extended.

Abstract parents

The following diagram shows a complete list of all abstract types in AbstractAlgebra.jl.

Diagram of parent types

Abstract elements

Similarly the following diagram shows a complete list of all abstract types in AbstractAlgebra.jl.

Diagram of element types

Concrete types in AbstractAlgebra.jl

Until now we have discussed the abstract types of AbstractAlgebra.jl. Under this subsection we will instead give some examples of concrete types in AbstractAlgebra.jl.

In parentheses we put the types of the corresponding parent objects.

  • Perm{<:Integer} (SymmetricGroup{<:Integer})
  • GFElem{<:Integer} (GFField{<:Integer})

We also think of various Julia types as though they were AbstractAlgebra.jl types:

  • BigInt (Integers{BigInt})
  • Rational{BigInt} (Rationals{BigInt})

Then there are various types for generic constructions over a base ring. They are all parameterised by a type T which is the type of the elements of the base ring they are defined over.

  • Generic.Poly{T} (Generic.PolyRing{T})
  • Generic.MPoly{T} (Generic.MPolyRing{T})
  • Generic.RelSeries{T} (Generic.RelPowerSeriesRing{T})
  • Generic.AbsSeries{T} (Generic.AbsPowerSeriesRing{T})
  • Generic.LaurentSeriesRingElem{T} (Generic.LaurentSeriesRing{T})
  • Generic.LaurentSeriesFieldElem{T} (Generic.LaurentSeriesField{T})
  • Generic.ResidueRingElem{T} (Generic.ResidueRing{T})
  • Generic.FracFieldElem{T} (Generic.FracField{T})
  • Generic.Mat{T} (Generic.MatSpace{T})
diff --git a/dev/ytabs/index.html b/dev/ytabs/index.html index d5f436033..5462cc94d 100644 --- a/dev/ytabs/index.html +++ b/dev/ytabs/index.html @@ -257,4 +257,4 @@ ⋅ ⋅ ⋅ 1 ⋅ 1 1 ⋅ 1 -source

SkewDiagram implements array interface with the following functions:

Base.sizeMethod
size(xi::SkewDiagram)

Return the size of array where xi is minimally contained. See size(Y::YoungTableau) for more details.

source
Base.inMethod
in(t::Tuple{Integer,Integer}, xi::SkewDiagram)

Check if box at position (i,j) belongs to the skew diagram xi.

source
Base.getindexMethod
getindex(xi::SkewDiagram, n::Integer)

Return 1 if linear index n corresponds to (column-major) entry in xi.lam which is not contained in xi.mu. Otherwise return 0.

source

The support for skew diagrams is very rudimentary. The following functions are available:

AbstractAlgebra.Generic.is_rimhookMethod
is_rimhook(xi::SkewDiagram)

Check if xi represents a rim-hook diagram, i.e. its diagram is edge-connected and contains no $2\times 2$ squares.

source
AbstractAlgebra.Generic.leglengthFunction
leglength(xi::SkewDiagram[, check::Bool=true])

Compute the leglength of a rim-hook xi, i.e. the number of rows with non-zero entries minus one. If check is false function will not check whether xi is actually a rim-hook.

source
AbstractAlgebra.Generic.matrix_reprMethod
matrix_repr(xi::SkewDiagram)

Return a sparse representation of the diagram xi, i.e. a sparse array A where A[i,j] == 1 if and only if (i,j) is in xi.lam but not in xi.mu.

source
+source

SkewDiagram implements array interface with the following functions:

Base.sizeMethod
size(xi::SkewDiagram)

Return the size of array where xi is minimally contained. See size(Y::YoungTableau) for more details.

source
Base.inMethod
in(t::Tuple{Integer,Integer}, xi::SkewDiagram)

Check if box at position (i,j) belongs to the skew diagram xi.

source
Base.getindexMethod
getindex(xi::SkewDiagram, n::Integer)

Return 1 if linear index n corresponds to (column-major) entry in xi.lam which is not contained in xi.mu. Otherwise return 0.

source

The support for skew diagrams is very rudimentary. The following functions are available:

AbstractAlgebra.Generic.is_rimhookMethod
is_rimhook(xi::SkewDiagram)

Check if xi represents a rim-hook diagram, i.e. its diagram is edge-connected and contains no $2\times 2$ squares.

source
AbstractAlgebra.Generic.leglengthFunction
leglength(xi::SkewDiagram[, check::Bool=true])

Compute the leglength of a rim-hook xi, i.e. the number of rows with non-zero entries minus one. If check is false function will not check whether xi is actually a rim-hook.

source
AbstractAlgebra.Generic.matrix_reprMethod
matrix_repr(xi::SkewDiagram)

Return a sparse representation of the diagram xi, i.e. a sparse array A where A[i,j] == 1 if and only if (i,j) is in xi.lam but not in xi.mu.

source