

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

#include "bits/bitsperlong.h"
#include "bpol/bitpol-irred.h"
#include "bpol/bitpol-primitive.h"
#include "bits/printbin.h"
#include "demo/nextarg.h"
#include "fxttypes.h"  // ulong
#include "fxtiomanip.h"
#include "jjassert.h"


//% Minimal polynomials in GF(2**n).


//#define TIMING // uncomment to disable printing

int
main(int argc, char **argv)
{
    ulong n = 6;
    NXARG(n, "The n in GF(2**n).");

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

    GF2n::init(n, c);

    GF2n::print_info();
    cout << endl;

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

#ifdef TIMING

    ulong p, d;  // minpoly, degree(minpoly)
    do
    {
        d = gf2n_minpoly(f, p);
        f *= g;
    }
    while ( f!=1 );
    cout << "dummy val:" << (d&p) << endl;


#else
    cout << "   k          :";
    cout << "    f:=g**k  ord(f) Tr(f)  p:=minpoly(f)  deg(p) " << endl;
    ulong k = 0;
    do
    {
        cout << setw(4) << k;
        print_bin(" = ",k,pn); cout << " : ";
        cout << "    " << f;

        cout << "  " << setw(4) << f.order();
        cout << "    " << f.trace();

        ulong p, d;  // minpoly, degree(minpoly)
        d = gf2n_minpoly(f, p);

        print_bin("      ",p, pn+2);
        cout << "      " << setw(2) << d;

        ulong h = 1UL << (d-1); // == highest_one(p)>>1;
        if ( d < BITS_PER_LONG )
        {
            jjassert( bitpol_irreducible_q(p, h) );
            GF2n v = gf2n_eval_poly(f, p);
            jjassert( 0==v );
        }

        if ( d==n )
        {
            ulong q = test_bitpol_primitive(p, h, GF2n::mfact_);
            if ( 0!=q )  cout << " N"; // Non-primitive
        }
        f *= g;
        ++k;

        cout << endl;
    }
    while ( f!=1 );
#endif

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

/*
Timing:

time ./bin 20
arg 1: 20 == n  [The n in GF(2**n).]  default=6
  c = 1................1..1 == x^20 + x^3 + 1  (polynomial modulus)
dummy val:0
./bin 20  12.25s user 0.00s system 99% cpu 12.260 total
 ==> 2^20/12.25 == 85,598 per second

BENCHARGS=20

*/


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

