# 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, namely`Generic.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)
```