
#include "bpol/gf2n.h"
//demo-include "bpol/gf2n.cc"

#include "bits/printbin.h"
#include "demo/nextarg.h"
#include "fxttypes.h"  // ulong
#include "jjassert.h"


//% Arithmetics over GF(2**n).

//#define TIMING // uncomment to disable printing

void
doit(ulong n)
{
    cout << "" << endl;
    cout << "------------------------------------------------------------" << endl;
    GF2n::print_info();
    cout << "" << endl;

    ulong pn = n;
    GF2n f(1);
    GF2n g;  g.v_ = GF2n::g_;

#ifndef TIMING
    cout << "      k  :    f:=g**k  Tr(f)    ord(f)     f*f    sqrt(f)" << endl;
#endif
    ulong k = 0;
    do
    {
        ulong t = f.trace();
        GF2n s = f.sqr();
        GF2n q = f.sqrt();
        ulong r = f.order();

#ifndef TIMING
        print_bin("    ", k, pn); cout << " : ";
        cout << "     " << f;
        cout << "     " << t;
        cout << "     " << setw(4) << r;
        cout << "    ";
        cout << "    " << s;
        cout << "    " << q;
#endif
        jjassert( q*q==f );
        jjassert( f*f==s );

        GF2n i = f.inv();
//        cout << "    ";
//        cout << "  i= " << i;
        jjassert( i.inv() == f );

        GF2n e = f.pow(GF2n::mm_);
        jjassert( 1==e );

#ifndef TIMING
        cout << endl;
#endif
        f *= g;
        ++k;
    }
    while ( f!=1 );
}
// -------------------------

int
main(int argc, char **argv)
{
    ulong dq = 1;  // whether default behavior
    if ( argc>1 )  dq = 0;

    ulong n = 4;
    NXARG(n, "degree of field");

    ulong c = 0;
    RESTARGS("Optionally supply nonzero coefficients of field poly c");
    for (ulong k=2;  (ulong)argc>k;  ++k)  c |= (1UL << atol(argv[k]));
    if ( 0!=c )  c |= (1UL<<n);

//    bitmat_print("NT=", p2n_tab, n);

    GF2n::init(n, c);
    doit(n);

    if ( dq )  // default
    {
        n = 4;
        c = 31;  // irreducible but not primitive
        GF2n::init(n, c);
        doit(n);
    }

    return 0;
}
// -------------------------

/*
Timing:
time ./bin 20
arg 1: 20 == n  [degree of field]  default=4
args 2,3,... : [Optionally supply nonzero coefficients of field poly c]

------------------------------------------------------------
  n = 20  GF(2^n)
  c = 1................1..1 == x^20 + x^3 + 1  (polynomial modulus)
  mm= .11111111111111111111   == 1048575  =  3 * 5^2 * 11 * 31 * 41  (maximal order)
  h = .1................... (aux. bitmask)
  g = ...................1. (element of maximal order)
  tv= ...1................. (traces of x^i)
tr1e= ...1................. (element with trace=1)
./bin 20  13.37s user 0.00s system 99% cpu 13.372 total

BENCHARGS=20

*/

/// Emacs:
/// Local Variables:
/// MyRelDir: "demo/gf2n"
/// makefile-dir: "../../"
/// make-target: "1demo DSRC=demo/gf2n/gf2n-demo.cc"
/// make-target2: "1demo DSRC=demo/gf2n/gf2n-demo.cc DEMOFLAGS=-DTIMING"
/// End:

