In this section we will show you some basic computations with fields. GAP supports at present the following fields. The rationals, cyclotomic extensions of rationals and their subfields (which we will refer to as number fields in the following), and finite fields.

Let us first take a look at the infinite fields mentioned above. While the set of rational numbers is a predefined domain in GAP to which you may refer by its identifier `Rationals`, cyclotomic fields are constructed by using the function `CyclotomicField`, which may be abbreviated as `CF`.

```    gap> IsField( Rationals );
true
gap> Size( Rationals );
"infinity"
gap> f := CyclotomicField( 8 );
CF(8)
gap> IsSubset( f, Rationals );
true```

The integer argument `n` of the function call to `CF` specifies that the cyclotomic field containing all n-th roots of unity should be returned.

Cyclotomic fields are constructed as extensions of the Rationals by primitive roots of unity. Thus a primitive n-th root of unity is always an element of CF(n), where n is a natural number. In GAP, one may construct a primitive n-th root of unity by calling `E(n)`.

```    gap> (E(8) + E(8)^3)^2;
-2
gap> E(8) in f;
true```

For every field extension you can compute the Galois group, i.e., the group of automorphisms that leave the subfield fixed. For an example, cyclotomic fields are an extension of the rationals, so you can compute their Galois group over the rationals.

```    gap> Galf := GaloisGroup( f );
Group( NFAutomorphism( CF(8) , 7 ), NFAutomorphism( CF(8) , 5 ) )
gap> Size( Galf );
4```

The above cyclotomic field is a small example where the Galois group is not cyclic.

```    gap> IsCyclic( Galf );
false
gap> IsAbelian( Galf );
true
gap> AbelianInvariants( Galf );
[ 2, 2 ]```

This shows us that the 8th cyclotomic field has a Galois group which is isomorphic to group V_4.

The elements of the Galois group are GAP automorphisms, so they may be applied to the elements of the field in the same way as all mappings are usually applied to objects in GAP.

```    gap> g := Galf.generators[1];
NFAutomorphism( CF(8) , 7 )
gap> E(8) ^ g;
-E(8)^3```

There are two functions, `Norm` and `Trace`, which compute the norm and the trace of elements of the field, respectively. The norm and the trace of an element a are defined to be the product and the sum of the images of a under the Galois group. You should usually specify the field as a first argument. This argument is however optional. If you omit a default field will be used. For a cyclotomic a this is the smallest cyclotomic field that contains a (note that this is not the smallest field that contains a, which may be a number field that is not a cyclotomic field).

```    gap> orb := List( Elements( Galf ), x -> E(8) ^ x );
[ E(8), E(8)^3, -E(8), -E(8)^3 ]
gap> Sum( orb ) = Trace( f, E(8) );
true
gap> Product( orb ) = Norm( f, E(8) );
true
gap> Trace( f, 1 );
4```

The basic way to construct a finite field is to use the function `GaloisField` which may be abbreviated, as usual in algebra, as `GF`. Thus

```    gap> k := GF( 3, 4 );
GF(3^4)```

or

```    gap> k := GaloisField( 81 );
GF(3^4)```

will assign the finite field of order 3^4 to the variable `k`.

In fact, what `GF` does is to set up a record which contains all necessary information, telling that it represents a finite field of degree 4 over its prime field with 3 elements. Of course, all arguments to `GF` others than those which represent a prime power are rejected -- for obvious reasons.

Some of the more important entries of the field record are `zero`, `one` and `root`, which hold the corresponding elements of the field. All elements of a finite field are represented as a certain power of an appropriate primitive root, which is written as `Z(q)`. As can be seen below the smallest possible primitive root is used.

```    gap> k.one + k.root + k.root^10 - k.zero;
Z(3^4)^52
gap> k.root;
Z(3^4)
gap> k.root ^ 20;
Z(3^2)^2
gap> k.one;
Z(3)^0```

Note that of course elements from fields of different characteristic cannot be combined in operations.

```    gap> Z(3^2) * k.root + k.zero + Z(3^8);
Z(3^8)^6534
gap> Z(2) * k.one;
Error, Finite field *: operands must have the same characteristic```

In this example we tried to multiply a primitive root of the field with two elements with the identity element of the field `k`. As the characteristic of `k` equals 3, there is no way to perform the multiplication. The first statement of the example shows, that if all the elements of the expression belong to fields of the same characteristic, the result will be computed.

As soon as a primitive root is demanded, GAP internally sets up all relevant data structures that are necessary to compute in the corresponding finite field. Each finite field is constructed as a splitting field of a Conway polynomial. These polynomials, as a set, have special properties that make it easy to embed smaller fields in larger ones and to convert the representation of the elements when doing so. All Conway polynomials for fields up to an order of 65536 have been computed and installed in the GAP kernel.

But now look at the following example.

```    gap> Z(3^3) * Z(3^4);
Error, Finite field *: smallest common superfield to large```

Although both factors are elements of fields of characteristic 3, the product can not be evaluated by GAP. The reason for this is very easy to explain: In order to compute the product, GAP has to find a field in which both of the factors lie. Here in our example the smallest field containing Z(3^3) and Z(3^4) is GF(3^{12}), the field with 531441 elements. As we have mentioned above that the size of finite fields in GAP is limited at present by 65536 we now see that there is no chance to set up the internal data structures for the common field to perform the computation.

As before with cyclotomic fields, the Galois group of a finite field and the norm and trace of its elements may be computed. The calling conventions are the same as for cyclotomic fields.

```    gap> Galk := GaloisGroup( k );
Group( FrobeniusAutomorphism( GF(3^4) ) )
gap> Size( Galk );
4
gap> IsCyclic( Galk );
true
gap> Norm( k, k.root ^ 20 );
Z(3)^0
gap> Trace( k, k.root ^ 20 );
0*Z(3)```

So far, in our examples, we were always interested in the Galois group of a field extension k over its prime field. In fact it often will occur that, given a subfield l of k the Galois group of k over l is desired. In GAP it is possible to change the structure of a field by using the `/` operator. So typing

```    gap> l := GF(3^2);
GF(3^2)
gap> IsSubset( k, l );
true
gap> k / l;
GF(3^4)/GF(3^2)```

changes the representation of k from a field extension of degree 4 over GF(3) to a field given as an extension of degree 2 over GF(3^2). The actual elements of the fields are still the same, only the structure of the field has changed.

```    gap> k = k / l;
true
gap> Galkl := GaloisGroup( k / l );
Group( FrobeniusAutomorphism( GF(3^4)/GF(3^2) )^2 )
gap> Size( Galkl );
2```

Of course, all the relevant functions behave in a different way when they refer to `k / l` instead of `k`

```    gap> Norm( k / l, k.root ^ 20 );
Z(3)
gap> Trace( k / l, k.root ^ 20 );
Z(3^2)^6```

This feature, to change the structure of the field without changing the underlying set of elements, is also available for cyclotomic fields, which we have seen at the beginning of this chapter.

```    gap> g := CyclotomicField( 4 );
GaussianRationals
gap> IsSubset( f, g );
true
gap> f / g;
CF(8)/GaussianRationals
gap> Galfg := GaloisGroup( f / g );
Group( NFAutomorphism( CF(8)/GaussianRationals , 5 ) )
gap> Size( Galfg );
2```

The examples should have shown that, although the structure of finite fields and cyclotomic fields is rather different, there is a similar interface to them in GAP, which makes it easy to write programs that deal with both types of fields in the same way.

GAP 3.4.4
April 1997