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

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{}

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

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)
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
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)

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