/* changed boolean to mboolean in mmg/include/kernel/xxx.h
   and min to mmin in generic.H */

#include <magnum/Prime.H>
#include <magnum/FpPolynom.H>
#include <magnum/FpPolynom_Set.H>

long nbFactors(const FpPolynom_List &list)
{
  long n=0;
  for (FpPolynom_List_Iterator l_iter (list); l_iter (); ++l_iter) 
    n+=l_iter ()->set().size ();
  return n;
}

MTcell polynomToMuPAD(const FpPolynom &x)
{
    MTcell p,q; long i=0;

    p = MFnewList(x.length());
    for (FpPolynom_Iterator x_iter (x); x_iter (); ++x_iter)
      {
	q = MFnewList(2);
	MFopSet(q,0,MFlong((long)x_iter ()->factor));
	MFopSet(q,1,MFlong((long)x_iter ()->power));
	MFopSet(p,i++,q);
      }
    return p;
}

MTcell toMuPAD(const FpPolynom_List &l)
{
    MTcell  ll; long i=0;

        ll=MFnewList(2*nbFactors(l)+1);
        MFopSet(ll,i,MFlong((long)l.factor));
        FpPolynom_List_Iterator l_iter (l);
        if (l_iter ())
        {
	  do {
                FpPolynom_Set_Iterator s_iter (l_iter ()->set ());
                if (s_iter ())
                    do
                    {
		        MFopSet(ll,++i,polynomToMuPAD(s_iter ()->polynom ()));
                        MFopSet(ll,++i,MFlong((long)l_iter ()->power));
                    }
                    while ((++s_iter) ());
	      } while ((++l_iter) ());
        }
    return(ll);
}

//
// MuPAD dynamic module for 'magnum' interface
//
MFUNC( initmod,     // Reserved name -> called from 'loadmod'
       MCremember,  // use remember table -> exec only once
{
    MFreturn( MFcopy(MVnull) );
} )

MFUNC( factor,      // Function name, as visible in MuPAD
       MCnop,     // No OPtion is set for this function
{
    MTcell  l; MTcell v;
    long n; long i; long p; long q;
    char    buf[256];

    if( MVnargs != 2 ) MFerror("wrong number of arguments");
    l = MFarg(1);
    if( !MFisList(l) ) MFerror("list expected");
    p = MFlong(MFarg(2));
    FpPolynom x ((Prime) p);
    n = MFnops(l);
    for( i = 0; i < n ; i++ ) {
      v = MFop(l,i);
      q = MFlong(MFop(v,0));
      if (q<0) q+=p;
      x+=FpPolynom (x.descriptor,(Fp) q,MFlong(MFop(v,1)));
    }
    FpPolynom_List ll;
    factorize (ll, x);
    MFreturn(toMuPAD(ll));
} )

