///*
//given a list l[1]..l[n+1] where l[i+1] is the coeff of x^i in P,
//returns the list of coeffs of P(x+1)
//*/

//MMG( coption = "-O3" )  // I use a higher optimation level 

#define OPT1 // cut when all remaining signs are equal

#define OPT2 // stop when number of sign changes >= 3
// Remark: OPT2 seems buggy (Walter, 17.12.02)

MFUNC(X2XP1, MCnop)
{  MFnargsCheck(1);
   MFargCheck(1, DOM_LIST);

   //    I use less variables (the compiler can use the registers better) 

   MTcell  *k, l=MFcopy(MFarg(1));  MFchange(&l);  
   long     i, j, n = MFnopsList(l)-1;
   
//     (Since the quality of inlining functions depends on the compiler
//       I directly use MFopSet(l,j,value) instead of MFopList(&l,j,value).) 

//      In this version I use the undocumented routine MFopAdr which
//      returns a pointer instead of the object itself. This allows
//      me to use faster pointer arithmetic (*(k+1)) and to use the
//      MAPI routine MFaddto instead of MFadd.

   for (i=0;i<n;i++) {
     k = MFopAdr(l,n-1);
     for (j=n-1;j>=i;j--,k--) MFaddto( k, MFcopy(*(k+1)) );
   }
   MFreturn(l);
} MFEND

// does not work, better use the MAPI interface:
// #define MFsign(x) (long) (gcmp(MCA_cat_to_pari(x), MCA_cat_to_pari(MVzero)))

long MFsign(MTcell x)
{
  if (MTbool(MFlt(x, MVzero)))
    return(-1L);
  if (MTbool(MFgt(x, MVzero)))
    return(1L);

  return(0L);
}


MFUNC(VarX2XP1R, MCnop)
{
#ifdef DEBUG
   MFnargsCheck(2);
   MFargCheck(1, DOM_LIST);
#endif                                                // // Here is the corresponding lib code:
   MTcell l=MFcopy(MFarg(1)),t,u;                     // polylib::Uspensky_VarX2XP1R := proc(l,d)
   long n,i,j,n1,c=0,d,v=0,ls,par;                    // local i,j,n,v,c,ls,n1,lj;
#ifdef OPT2                                           //
// par = MFlong(MFarg(2));  // changed, Walter        //
   par = MFsign(MFarg(2));                            //
#endif                                                //
   l = MFchange(&l);                                  // n:=nops(l)-1; v:=0; c:=0;
   n=MFnopsList(l)-1;                                 // 
#ifdef OPT1                                           //
   n1=0; while ((ls=MFsign(MFop(l, n1))) == 0) n1++;  // n1:=1; 
   /* l[0]...l[n1-1] are zero */                      // while (ls:=sign(l[n1]))=0 do
#endif                                                // n1:=n1+1 end_while;
   for (i=n;i>=1;i--) {                               // for i from n+1 downto 2 do
     for (j=1;j<=i;j++) {                             //   lj:=l[1];
       t = MFcopy(MFop(l, j-1));                      //   for j from 2 to i do
       u = MFop(l, j);                                //    lj:=l[j]+lj; l[j]:=lj;
       MFsetList(&l, j, MFadd(u, t));                 //   end_for;
     }                                                //   if c=0 then c:=sign(l[i])
     d = MFsign(MFop(l, i));                          //   elif sign(l[i])*c<0 then
//   if (i==n) c=d;                                   //     v:=v+1; 
     if (c==0) c=d;
     else if (d*c < 0) {                              //  
       v++;                                           // 
#ifdef OPT2                                           //
       if (v>=3 || (v>=2 && par<0)) goto exit_var;    //     if v>=3 or (v>=2 and d<0) then 
#endif                                                //       return(v)
       c=d;                                           //     end_if;
     }                                                //     c:=sign(l[i]);
#ifdef OPT1                                           //
   while (n1<i && (MFsign(MFop(l, n1))*ls >= 0)) n1++;// while n1<i and sign(l[n1])*ls>=0 do
                                                      //  n1:=n1+1 end_while;
     if (n1==i) {                                     //  if n1=i then
       if (ls*c < 0) v++; goto exit_var;              //    if ls*c<0 then v:=v+1 end_if;
     }                                                //    return(v);
#endif                                                //  end_if
   }                                                  // end_for;
                                                      // check leading coeff
   if (c*MFsign(MFop(l, 0)) < 0) v++;                 // if c*sign(l[1])<0 then v:=v+1 end_if;
   exit_var:                                          //
   MFfree(l);                                         //
   MFreturn(MFint(v));                                // return(v);
} MFEND
