Skip to content

Commit

Permalink
Make FqField the default finite field
Browse files Browse the repository at this point in the history
  • Loading branch information
thofma committed Dec 31, 2023
1 parent 97fab3e commit 6695643
Show file tree
Hide file tree
Showing 50 changed files with 1,129 additions and 1,324 deletions.
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[deps]
AbstractAlgebra = "c3fe647b-3220-5bb0-a1ea-a7954cac585d"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a"

[compat]
Documenter = "1.0"
221 changes: 15 additions & 206 deletions docs/src/finitefield.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,15 @@ end

# Finite fields

Finite fields are provided in Nemo by Flint. This allows construction of finite
fields of any characteristic and degree for which there are Conway polynomials.
It is also possible for the user to specify their own irreducible polynomial
generating a finite field.
A finite field $K$ is represented as simple extension $K = k(\alpha) = k[x]/(f)$, where $k$ can
be
- a prime field $\mathbf{F}_p$ ($K$ is then an *absolute finite field*), or
- an arbitrary finite field $k$ ($K$ is then a *relative finite field*).

Finite fields are constructed using the `FlintFiniteField` function. However,
for convenience we define
In both cases, we call $k$ the *base field* of $K$, $\alpha$ a *generator* and $f$ the *defining polynomial* of $K$.

```
finite_field = FlintFiniteField
```

so that finite fields can be constructed using `finite_field` rather than
`FlintFiniteField`. Note that this is the name of the constructor, but not of
finite field type.

The types of finite field elements in Nemo are given in the following table,
along with the libraries that provide them and the associated types of the
parent objects.

Library | Field | Element type | Parent type
---------|--------------------------------|---------------|---------------------
Flint | $\mathbb{F}_{p^n}$ (small $p$) | `fqPolyRepFieldElem` | `fqPolyRepField`
Flint | $\mathbb{F}_{p^n}$ (large $p$) | `FqPolyRepFieldElem` | `FqPolyRepField`

The only difference between the `FqPolyRepFieldElem` and `fqPolyRepFieldElem` types is the representation.
The former is for finite fields with multiprecision characteristic and the
latter is for characteristics that fit into a single unsigned machine word. The
`FlintFiniteField` constructor automatically picks the correct representation
for the user, and so the average user doesn't need to know about the actual
types.

All the finite field types belong to the `FinField` abstract type and the
finite field element types belong to the `FinFieldElem` abstract type.

Since all the functionality for the `FqPolyRepFieldElem` finite field type is identical to that
provided for the `fqPolyRepFieldElem` finite field type, we simply document the former.
Note that all field theoretic properties (like basis, degree or trace) are defined with respect to the base field.
Methods with prefix `absolute_` return

## Finite field functionality

Expand All @@ -53,180 +25,14 @@ Finite fields in Nemo provide all the field functionality described in AbstractA

Below we describe the functionality that is provided in addition to this.

### Constructors

In order to construct finite field elements in Nemo, one must first construct
the finite field itself. This is accomplished with one of the following
constructors.

```@docs
FlintFiniteField
```

Here are some examples of creating finite fields and making use of the
resulting parent objects to coerce various elements into those fields.

**Examples**

```jldoctest
julia> R, x = finite_field(7, 3, "x")
(Finite field of degree 3 over GF(7), x)
julia> S, y = finite_field(ZZ(12431351431561), 2, "y")
(Finite field of degree 2 over GF(12431351431561), y)
julia> T, t = polynomial_ring(residue_ring(ZZ, 12431351431561), "t")
(Univariate polynomial ring in t over ZZ/(12431351431561), t)
julia> U, z = finite_field(t^2 + 7, "z")
(Finite field of degree 2 over GF(12431351431561), z)
julia> a = R(5)
5
julia> b = R(x)
x
julia> c = S(ZZ(11))
11
julia> d = U(7)
7
```

### Basic manipulation

```@docs
gen(::FqPolyRepField)
```

```@docs
is_gen(::FqPolyRepFieldElem)
```

```@docs
coeff(::FqPolyRepFieldElem, ::Int)
```

```@docs
degree(::FqPolyRepField)
```

```@docs
modulus(::FqPolyRepField)
```

**Examples**

```jldoctest
julia> R, x = finite_field(ZZ(7), 5, "x")
(Finite field of degree 5 over GF(7), x)
julia> c = gen(R)
x
julia> d = characteristic(R)
7
julia> f = order(R)
16807
julia> g = degree(R)
5
julia> n = is_gen(x)
true
```

### Special functions

Various special functions with finite field specific behaviour are defined.

```@docs
tr(::FqPolyRepFieldElem)
```

```@docs
norm(::FqPolyRepFieldElem)
```

```@docs
frobenius(::FqPolyRepFieldElem, ::Int)
```

```@docs
pth_root(::FqPolyRepFieldElem)
```

**Examples**

```jldoctest
julia> R, x = finite_field(ZZ(7), 5, "x")
(Finite field of degree 5 over GF(7), x)
julia> a = x^4 + 3x^2 + 6x + 1
x^4 + 3*x^2 + 6*x + 1
julia> b = tr(a)
1
julia> c = norm(a)
4
julia> d = frobenius(a)
x^4 + 2*x^3 + 3*x^2 + 5*x + 1
julia> f = frobenius(a, 3)
3*x^4 + 3*x^3 + 3*x^2 + x + 4
julia> g = pth_root(a)
4*x^4 + 3*x^3 + 4*x^2 + 5*x + 2
```

### Lift

```@docs
lift(::FpPolyRing, ::FqPolyRepFieldElem)
```

**Examples**

```jldoctest
julia> R, x = finite_field(23, 2, "x")
(Finite field of degree 2 over GF(23), x)
julia> S, y = polynomial_ring(GF(23), "y")
(Univariate polynomial ring in y over GF(23), y)
julia> f = 8x + 9
8*x + 9
julia> lift(S, f)
8*y + 9
```

# Uniform finite fields

An (experimental) uniform finite field interface is provided by the type `FqField`.
Such a finite field can be constructed as an extension of a prime field
$\mathbf{F}_p$ (an absolute extension) or of another finite field (a relative
extension). The field over which the extension is constructed is referred to as the *base field*
and field theoretic properties like the degree of an extension or the trace of an element are understood with respect to the base field.
The corresponding functionality for the implicit absolute extension over the prime field is available
by methods with the prefix `absolute_`.

Note that all finite fields are simple extension $k[t]/(f)$ of their base field $k$.
The irreducible polynomial $f \in k[t]$ is the *defining polynomial* and the class of $t$ is referred
to as the *generator* of the extension.

## Construction of finite fields
## Constructors

```@docs
Nemo._FiniteField
Nemo._GF
finite_field
GF
```

## Field properties
## Field functionality

```@docs
base_field(::FqField)
Expand All @@ -237,12 +43,15 @@ is_absolute(::FqField)
defining_polynomial(::FqPolyRing, ::FqField)
```

## Element properties
## Element functionality

```@docs
gen(::FqField)
is_gen(::FqFieldElem)
tr(::FqFieldElem)
absolute_tr(::FqFieldElem)
norm(::FqFieldElem)
absolute_norm(::FqFieldElem)
lift(::FqPolyRing, ::FqFieldElem)
lift(::ZZRing, ::FqFieldElem)
```
2 changes: 1 addition & 1 deletion docs/src/gfp.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Below we describe the functionality that is provided in addition to these.

```jldoctest
julia> F = GF(3)
Finite field of characteristic 3
Finite field of degree 1 over GF(3)
julia> a = characteristic(F)
3
Expand Down
18 changes: 0 additions & 18 deletions src/HeckeMiscFiniteField.jl
Original file line number Diff line number Diff line change
@@ -1,21 +1,3 @@
# additional constructors

function FlintFiniteField(p::Integer; cached::Bool=true)
@assert is_prime(p)
k = GF(p, cached=cached)
return k, k(1)
end

function FlintFiniteField(p::ZZRingElem; cached::Bool=true)
@assert is_prime(p)
k = GF(p, cached=cached)
return k, k(1)
end

GF(p::Integer, k::Int, s::VarName=:o; cached::Bool=true) = FlintFiniteField(p, k, s, cached=cached)[1]
GF(p::ZZRingElem, k::Int, s::VarName=:o; cached::Bool=true) = FlintFiniteField(p, k, s, cached=cached)[1]


##
## rand for Flint-Finite fields
##
Expand Down
4 changes: 4 additions & 0 deletions src/Native.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ function finite_field(F::FqPolyRepField, deg::Int, s::VarName = :o; cached = tru
return FqPolyRepField(characteristic(F), deg, Symbol(s), cached)
end

similar(F::FqPolyRepField, deg::Int, s::VarName = :o; cached = true) = finite_field(F, deg, s, cached = cached)

function finite_field(char::Int, deg::Int, s::VarName = :o; cached = true)
parent_obj = fqPolyRepField(ZZRingElem(char), deg, Symbol(s), cached)
return parent_obj, gen(parent_obj)
Expand All @@ -62,6 +64,8 @@ function finite_field(F::fqPolyRepField, deg::Int, s::VarName = :o; cached = tru
return fqPolyRepField(characteristic(F), deg, Symbol(s), cached)
end

similar(F::fqPolyRepField, deg::Int, s::VarName = :o; cached = true) = FiniteField(F, deg, s, cached = cached)

# Additional from Hecke
function finite_field(p::Integer; cached::Bool = true)
@assert is_prime(p)
Expand Down
19 changes: 18 additions & 1 deletion src/Nemo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ for i in names(AbstractAlgebra)
@eval export $i
end

<<<<<<< HEAD
import AbstractAlgebra: _absolute_basis
import AbstractAlgebra: @attributes
import AbstractAlgebra: @show_name
Expand Down Expand Up @@ -198,6 +199,22 @@ import AbstractAlgebra: promote_rule
import AbstractAlgebra: Ring
import AbstractAlgebra: Set
import AbstractAlgebra: set_attribute!
=======
export GF

import AbstractAlgebra: Set, Module, Ring, Group, Field, promote_rule

import AbstractAlgebra: pretty, Lowercase, LowercaseOff, Indent, Dedent, ErrorConstrDimMismatch

export flint_cleanup, flint_set_num_threads

export PadicField, QadicField

export QQBar

# Things/constants which are also defined in AbstractAlgebra:
export ZZ, QQ, finite_field, number_field
>>>>>>> 7e5b9356a (Make FqField the default finite field)

include("Exports.jl")

Expand Down Expand Up @@ -598,7 +615,7 @@ const ZZ = FlintZZ
const QQ = FlintQQ
const PadicField = FlintPadicField
const QadicField = FlintQadicField
const finite_field = FlintFiniteField
#const FiniteField = FlintFiniteField

###############################################################################
#
Expand Down
2 changes: 1 addition & 1 deletion src/embedding/embedding.jl
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ function intersections(k::T, K::T) where T <: FinField
# and we embed it in k and S
else
# kc of same type as k but degree c
kc = finite_field(k, c, string("x", c))
kc = similar(k, c, string("x", c))
embed(kc, k)
for g in subK[l]
embed(kc, domain(g))
Expand Down
4 changes: 2 additions & 2 deletions src/flint/FlintTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6893,13 +6893,13 @@ const _fq_default_mpoly_union = Union{AbstractAlgebra.Generic.MPoly{FqPolyRepFie
m = modulus(R)
p = characteristic(R)
if fits(UInt, p)
Fq = GF(UInt(p))
Fq = Native.GF(UInt(p))
if isone(degree(m))
Fqx = polynomial_ring(Fq, s, cached = cached, ordering = ordering)[1]
return new(Fqx, R, 3)
end
mm = polynomial_ring(Fq, "x")[1](lift(polynomial_ring(ZZ, "x")[1], m))
Fq = FlintFiniteField(mm, R.var, cached = cached, check = false)[1]
Fq = Native.FiniteField(mm, R.var, cached = cached, check = false)[1]
Fqx = polynomial_ring(Fq, s, cached = cached, ordering = ordering)[1]
return new(Fqx, R, 2)
end
Expand Down
Loading

0 comments on commit 6695643

Please sign in to comment.