//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995 by the LiDIA Group
//
// File        : gf_appl.c
// Author      : Thomas Pfahler (TPf)
// Last change : TPf, Aug 8 1995, initial version
//

#include <LiDIA/gf_p_element.h>

main()
{
    cout<<"gf_appl   -   test application for finite field arithmetic\n\n";

    bigint p, q;
    lidia_size_t k;
    
    cout<<"Enter the characteristic of the field (a prime number): "; cin>>p;
    cout<<"Enter the degree of the field (over its prime field)  : "; cin>>k;

    galois_field ff(p, k);
    cout<<"\nThe field "<<ff<<" has";
    cout<<"\ncharacteristic "<<ff.characteristic();
    cout<<", degree "<<ff.degree();
    cout<<"\nand "<<ff.number_of_elements()<<" elements\n\n";

    cout<<"Creating a polynomial base representation ... ";
    gf_p_base pb(ff);
    cout<<"done.\n\n";
    Fp_polynomial irred = pb.irred_polynomial();
    cout<<"This is a representation of the form (Z/pZ[X])/(f(X) Z/pZ[X]),\n";
    cout<<"where f is an irreducible polynomial in Z/pZ[X].\n";
    cout<<"Here, f = ";
    irred.pretty_print();
    cout<<"\n\n";

    cout<<"Arithmetic in "<<ff<<"\n";
    cout<<"Generating random elements ...\n";
    gf_p_element a(pb), b(pb);
    a.randomize();
    b.randomize();
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    cout<<"a has order "<<a.compute_order()<<endl;
    cout<<"a is ";
    if (!a.is_primitive_element()) cout<<"not ";
    cout<<"a primitive element\n";
    cout<<"a + b = "<<a+b<<endl;
    cout<<"a - b = "<<a-b<<endl;
    cout<<"a * b = "<<a*b<<endl;
    cout<<"a / b = "<<a/b<<endl;
    cout<<"a^(-1)= "<<inverse(a)<<endl;
    cout<<"Tr(a) = "<<compute_trace(a)<<endl;
    cout<<"N(a)  = "<<compute_norm(a)<<endl;

    cout<<"\nGenerating a primitive element :\n";
    cout<<pb.gen_primitive_elem();
    cout<<"\nGenerating a free element :\n";
    cout<<pb.gen_free_elem();
    cout<<"\nGenerating a free primitive element :\n";
    cout<<pb.gen_free_primitive_elem();
    cout<<"\n";
}
