# Total ring of fractions

AbstractAlgebra.jl provides a module, implemented in src/generic/TotalFraction.jl, for the total ring of fractions of a ring.

The total ring of fractions of a ring R is the localisation of R at the non-zero divisors of R, the latter being a multiplicative subset of R.

There are no restrictions on the ring except the function is_zero_divisor must be defined and effective for R.

In particular, we do not assume that all elements of R which are not zero divisors are units in R. This has the effect of making exact division impossible generically in the total ring of fractions of R.

This in turn limits the usefulness of the total ring of fractions as a ring in AbstractAlgebra as a great deal of generic code relies on divexact. Should this be a limitation, the user can define their own divexact function for the total ring of fractions in question.

Note that in most cases a*inv(b) is not a sufficient definition of divexact(a, b) due to the possibility that b is not a unit in the total ring of fractions.

It is also possible to construct a total ring of fractions of R without the is_zero_divisor function existing for R, but some functions such as is_unit, inv, rand and ad hoc arithmetic operations involving rational numbers are not available for the total ring of fractions. One must also construct fractions using the option check=false and it is one's own responsibility to check that the denominator is not a zero divisor.

Note that although the total ring of fractions of an integral domain R is mathematically the same thing as the fraction field of R, these will be different objects in AbstractAlgebra and have different types.

## Generic total ring of fraction types

AbstractAlgebra.jl implements a generic type for elements of a total ring of fractions, namelyGeneric.TotFrac{T} where T is the type of elements of the base ring. See the file src/generic/GenericTypes.jl for details.

Parent objects of such elements have type Generic.TotFracRing{T}.

## Abstract types

The types for elements of a total ring of fractions belong directly to the abstract type RingElem and the type for the total ring of fractions parent object belongs directly to the abstract type Ring.

## Total ring of fractions constructors

In order to construct fractions in a total ring of fractions in AbstractAlgebra.jl, one must first construct the parent object for the total ring of fractions itself. This is accomplished with the following constructor.

total_ring_of_fractions(R::Ring; cached::Bool = true)

Given a base ring R return the parent object of the total ring of fractions of $R$. By default the parent object S will depend only on R and will be cached. Setting the optional argument cached to false will prevent the parent object S from being cached.

Here are some examples of creating a total ring of fractions and making use of the resulting parent objects to coerce various elements into the ring.

Examples

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

julia> S = total_ring_of_fractions(R)
Total ring of fractions of univariate polynomial ring

julia> f = S()
0

julia> g = S(123)
123

julia> h = S(BigInt(1234))
1234

julia> k = S(x + 1)
x + 1

## Fraction constructors

One can construct fractions using the total ring of fractions parent object, as for any ring or field.

(R::TotFracRing)() # constructs zero
(R::TotFracRing)(c::Integer)
(R::TotFracRing)(c::elem_type(R))
(R::TotFracRing{T})(a::T) where T <: RingElement

Although one cannot use the double slash operator // to construct elements of a total ring of fractions, as no parent has been specified, one can use the double slash operator to construct elements of a total ring of fractions so long as one of the arguments to the double slash operator is already in the total ring of fractions in question.

Examples

julia> R, x = polynomial_ring(QQ, "x")
(Univariate polynomial ring in x over rationals, x)

julia> S = total_ring_of_fractions(R)
Total ring of fractions of univariate polynomial ring

julia> f = S(x + 1)
x + 1

julia> f//3
(x + 1)//3

julia> 3//f
3//(x + 1)

julia> f//x
(x + 1)//x

## Functions for types and parents of total rings of fractions

Total rings of fractions in AbstractAlgebra.jl implement the Ring interface except for the divexact function which is not generically possible to implement.

base_ring(R::TotFracRing)
base_ring(a::TotFrac)

Return the base ring of which the total ring of fractions was constructed.

parent(a::TotFrac)

Return the total ring of fractions that the given fraction belongs to.

characteristic(R::TotFracRing)

Return the characteristic of the base ring of the total ring of fractions. If the characteristic is not known an exception is raised.

Examples

julia> R, x = polynomial_ring(QQ, "x")
(Univariate polynomial ring in x over rationals, x)

julia> S = total_ring_of_fractions(R)
Total ring of fractions of univariate polynomial ring

julia> f = S(x + 1)
x + 1

julia> U = base_ring(S)
Univariate polynomial ring in x over rationals

julia> V = base_ring(f)
Univariate polynomial ring in x over rationals

julia> T = parent(f)
Total ring of fractions of univariate polynomial ring

julia> m = characteristic(S)
0

## Total ring of fractions functions

### Basic functions

Total rings of fractions implement the Ring interface.

zero(R::TotFracRing)
one(R::TotFracRing)
iszero(a::TotFrac)
isone(a::TotFrac)
inv(a::T) where T <: TotFrac

They also implement some of the following functions which would usually be associated with the field and fraction field interfaces.

is_unit(f::TotFrac)
numerator(a::TotFrac)
denominator(a::TotFrac)

Examples

julia> R, x = polynomial_ring(QQ, "x")
(Univariate polynomial ring in x over rationals, x)

julia> S = total_ring_of_fractions(R)
Total ring of fractions of univariate polynomial ring

julia> f = S(x + 1)
x + 1

julia> g = f//(x^3 + 3x + 1)
(x + 1)//(x^3 + 3*x + 1)

julia> h = zero(S)
0

julia> k = one(S)
1

julia> isone(k)
true

julia> iszero(f)
false

julia> r = deepcopy(f)
x + 1

julia> n = numerator(g)
x + 1

julia> d = denominator(g)
x^3 + 3*x + 1

### Random generation

Random fractions can be generated using rand. The parameters passed after the total ring of fractions tell rand how to generate random elements of the base ring.

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

Examples

julia> R, = residue_ring(ZZ, 12);

julia> K = total_ring_of_fractions(R)
Total ring of fractions of residue ring

julia> f = rand(K, 0:11)
7//5

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

julia> S = total_ring_of_fractions(R)
Total ring of fractions of univariate polynomial ring

julia> g = rand(S, -1:3, -10:10)
(4*x + 4)//(-4*x^2 - x + 4)