Extending the interface of AbstractAlgebra.jl

In this section we will discuss on how to extend the interface of AbstractAlgebra.jl.

Elements and parents

Any implementation with elements and parents should implement the following interface:

Base.parentFunction
parent(a)

Return parent object of given element $a$.

Examples

julia> G = SymmetricGroup(5); g = Perm([3,4,5,2,1])
(1,3,5)(2,4)

julia> parent(g) == G
true

julia> S, x = laurent_series_ring(ZZ, 3, :x)
(Laurent series ring in x over integers, x + O(x^4))

julia> parent(x) == S
true
source
AbstractAlgebra.elem_typeFunction
elem_type(parent)
elem_type(parent_type)

Given a parent object (or its type), return the type of its elements.

Examples

julia> S, x = power_series_ring(QQ, 2, :x)
(Univariate power series ring over rationals, x + O(x^3))

julia> elem_type(S) == typeof(x)
true
source
AbstractAlgebra.parent_typeFunction
parent_type(element)
parent_type(element_type)

Given an element (or its type), return the type of its parent object.

Examples

julia> R, x = polynomial_ring(ZZ, :x)
(Univariate polynomial ring in x over integers, x)

julia> S = matrix_space(R, 2, 2)
Matrix space of 2 rows and 2 columns
  over univariate polynomial ring in x over integers

julia> a = rand(S, 0:1, 0:1);

julia> parent_type(a) == typeof(S)
true
source

Acquiring associated elements and parents

Further, if one has a base ring, like polynomials over the integers $\mathbb{Z}[x]$, then one should implement

AbstractAlgebra.base_ringFunction
base_ring(a)

Return base ring $R$ of given element or parent $a$.

Examples

julia> S, x = polynomial_ring(QQ, :x)
(Univariate polynomial ring in x over rationals, x)

julia> base_ring(S) == QQ
true

julia> R = GF(7)
Finite field F_7

julia> base_ring(R)
Union{}
source
AbstractAlgebra.base_ring_typeFunction
base_ring_type(a)

Return the type of the base ring of the given element, element type, parent or parent type $a$.

Examples

julia> R, x = polynomial_ring(ZZ, :x)
(Univariate polynomial ring in x over integers, x)

julia> base_ring_type(R) == typeof(base_ring(R))
true

julia> base_ring_type(zero(R)) == typeof(base_ring(zero(R)))
true

julia> base_ring_type(typeof(R)) == typeof(base_ring(R))
true

julia> base_ring_type(typeof(zero(R))) == typeof(base_ring(zero(R)))
true
source

Special elements

For rings, one has to extend the following methods:

Base.oneFunction
one(a)

Return the multiplicative identity in the algebraic structure of $a$, which can be either an element or parent.

Examples

julia> S = matrix_space(ZZ, 2, 2)
Matrix space of 2 rows and 2 columns
  over integers

julia> one(S)
[1   0]
[0   1]

julia> R, x = puiseux_series_field(QQ, 4, :x)
(Puiseux series field in x over rationals, x + O(x^5))

julia> one(x)
1 + O(x^4)

julia> G = GF(5)
Finite field F_5

julia> one(G)
1
source
Base.zeroFunction
zero(a)

Return the additive identity in the algebraic structure of $a$, which can be either an element or parent.

Examples

julia> S = matrix_ring(QQ, 2)
Matrix ring of degree 2
  over rationals

julia> zero(S)
[0//1   0//1]
[0//1   0//1]

julia> R, x = polynomial_ring(ZZ, :x)
(Univariate polynomial ring in x over integers, x)

julia> zero(x^3 + 2)
0
source

Groups should only extend at least one of these. The one that is required depends on if the group is additive (commutative) or multiplicative.

Basic manipulation

If one would like to implement a ring, these are the basic manipulation methods that all rings should extend:

Base.isoneFunction
isone(a)

Return true if $a$ is the multiplicative identity, else return false.

Examples

julia> S = matrix_space(ZZ, 2, 2); T = matrix_space(ZZ, 2, 3); U = matrix_space(ZZ, 3, 2);

julia> isone(S([1 0; 0 1]))
true

julia> isone(T([1 0 0; 0 1 0]))
false

julia> isone(U([1 0; 0 1; 0 0]))
false

julia> T, x = puiseux_series_field(QQ, 10, :x)
(Puiseux series field in x over rationals, x + O(x^11))

julia> isone(x), isone(T(1))
(false, true)
source
Base.iszeroFunction
iszero(a)

Return true if $a$ is the additative identity, else return false.

Examples

julia> T, x = puiseux_series_field(QQ, 10, :x)
(Puiseux series field in x over rationals, x + O(x^11))

julia> a = T(0)
O(x^10)

julia> iszero(a)
true
source
AbstractAlgebra.is_unitFunction
is_unit(a::T) where {T <: NCRingElem}

Return true if $a$ is invertible, else return false.

Examples

julia> S, x = polynomial_ring(QQ, :x)
(Univariate polynomial ring in x over rationals, x)

julia> is_unit(x), is_unit(S(1)), is_unit(S(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.