Index: Singular/LIB/poly.lib
===================================================================
--- Singular/LIB/poly.lib	(revision 2b4e7066de6a1ca22687a95c7411269e78fe38d8)
+++ Singular/LIB/poly.lib	(revision ff8d25468b2f699e6c418ba14d9c0e1019b263e5)
@@ -1,4 +1,4 @@
 ///////////////////////////////////////////////////////////////////////////////
-version="$Id: poly.lib,v 1.29 2000-12-22 14:22:23 greuel Exp $";
+version="$Id: poly.lib,v 1.30 2000-12-31 01:55:11 greuel Exp $";
 category="General purpose";
 info="
@@ -133,8 +133,9 @@
 proc freerank
 "USAGE:   freerank(M[,any]);  M=poly/ideal/vector/module/matrix
-COMPUTE: rank of module presented by M in case it is free. By definition this
-         is vdim(coker(M)/m*coker(M)) if coker(M) is free, where m = maximal
-         ideal of basering and M is considered as matrix (the 0-module is
-         free of rank 0)
+COMPUTE: rank of module presented by M in case it is free. 
+         By definition this is vdim(coker(M)/m*coker(M)) if coker(M)
+         is free, where m = maximal ideal of the variables of the
+         basering and M is considered as matrix. 
+         (the 0-module is free of rank 0)
 RETURN:  rank of coker(M) if coker(M) is free and -1 else;
          in case of a second argument return a list:
@@ -159,9 +160,10 @@
   ideal i=x;
   module M=[x,0,1],[-x,0,-1];
-  freerank(M);           // should be 2, coker(M) is not free
-  freerank(syz (M),"");  // [1] should be 1, coker(syz(M))=M is free of rank 1
-                         // [2] should be gen(2)+gen(1) (minimal relation of M)
+  freerank(M);          // should be 2, coker(M) is not free
+  freerank(syz (M),""); 
+  // [1] should be 1, coker(syz(M))=M is free of rank 1
+  // [2] should be gen(2)+gen(1) (minimal relation of M)
   freerank(i);
-  freerank(syz(i));      // should be 1, coker(syz(i))=i is free of rank 1
+  freerank(syz(i));     // should be 1, coker(syz(i))=i is free of rank 1
 }
 ///////////////////////////////////////////////////////////////////////////////
@@ -208,7 +210,7 @@
 proc is_zero
 "USAGE:   is_zero(M[,any]); M=poly/ideal/vector/module/matrix
-RETURN:  integer, 1 if coker(M)=0 resp. 0 if coker(M)!=0, where M is considered
-         as matrix
-         if a second argument is given, return a list:
+RETURN:  integer, 1 if coker(M)=0 resp. 0 if coker(M)!=0, where M is 
+         considered as matrix.
+         If a second argument is given, return a list:
                 L[1] = 1 if coker(M)=0 resp. 0 if coker(M)!=0
                 L[2] = dim(M)
@@ -230,5 +232,5 @@
   is_zero(j);
 }
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 
 proc maxcoef (f)
@@ -273,6 +275,6 @@
 RETURN:  int/intmat, each component equals maximal degree of monomials in the
          corresponding component of id, independent of ring ordering
-         (maxdeg of each var is 1)
-         of type int if id is of type poly, of type intmat else
+         (maxdeg of each var is 1).
+         Of type int if id is of type poly, of type intmat else
 NOTE:    proc maxdeg1 returns 1 integer, the absolut maximum; moreover, it has
          an option for computing weighted degrees
@@ -316,5 +318,5 @@
    ring r = 0,(x,y,z),wp(-1,-2,-3);
    poly f = x+y2+z3;
-   deg(f);               //deg; returns weighted degree (in case of 1 block)!
+   deg(f);             //deg; returns weighted degree (in case of 1 block)!
    maxdeg(f);
    matrix m[2][2]=f+x10,1,0,f^2;
@@ -396,10 +398,10 @@
    ring r = 0,(x,y,z),wp(-1,-2,-3);
    poly f = x+y2+z3;
-   deg(f);                  //deg returns weighted degree (in case of 1 block)!
+   deg(f);            //deg returns weighted degree (in case of 1 block)!
    maxdeg1(f);
    intvec v = ringweights(r);
-   maxdeg1(f,v);                             //weighted maximal degree
+   maxdeg1(f,v);                        //weighted maximal degree
    matrix m[2][2]=f+x10,1,0,f^2;
-   maxdeg1(m,v);                             //absolut weighted maximal degree
+   maxdeg1(m,v);                        //absolut weighted maximal degree
 }
 ///////////////////////////////////////////////////////////////////////////////
@@ -452,8 +454,8 @@
    ring r = 0,(x,y,z),ls;
    poly f = x5+y2+z3;
-   ord(f);                      // ord returns weighted order of leading term!
-   mindeg(f);                   // computes minimal degree
+   ord(f);                  // ord returns weighted order of leading term!
+   mindeg(f);               // computes minimal degree
    matrix m[2][2]=x10,1,0,f^2;
-   mindeg(m);                   // computes matrix of minimum degrees
+   mindeg(m);               // computes matrix of minimum degrees
 }
 ///////////////////////////////////////////////////////////////////////////////
@@ -532,9 +534,9 @@
    ring r = 0,(x,y,z),ls;
    poly f = x5+y2+z3;
-   ord(f);                      // ord returns weighted order of leading term!
+   ord(f);                  // ord returns weighted order of leading term!
    intvec v = 1,-3,2;
-   mindeg1(f,v);                // computes minimal weighted degree
+   mindeg1(f,v);            // computes minimal weighted degree
    matrix m[2][2]=x10,1,0,f^2;
-   mindeg1(m,1..3);             // computes absolut minimum of weighted degrees
+   mindeg1(m,1..3);         // computes absolut minimum of weighted degrees
 }
 ///////////////////////////////////////////////////////////////////////////////
@@ -550,5 +552,5 @@
 //-------------------------------- examples -----------------------------------
 example
-{  "EXAMPLE:"; echo = 2;
+{ "EXAMPLE:"; echo = 2;
    ring r = 0,(x,y,z),ls;
    poly f = 2x5+3y2+4z3;
@@ -559,20 +561,19 @@
    module m=[9xy,0,3z3],[4z,6y,2x];
    normalize(m);
-   normalize(matrix(m));             // by automatic type conversion to module!
-}
-///////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
 // Input: <ideal>=<f1,f2,...,fm> and <polynomial> g
 // Question: Does g lie in the radical of <ideal>?
-// Solution: Compute a standard basis G for <f1,f2,...,fm,gz-1> where z is a new
-//           variable. Then g is contained in the radical of <ideal> <=> 1 is
-//           generator in G.
-////////////////////////////////////////////////////////////////////////////////
+// Solution: Compute a standard basis G for <f1,f2,...,fm,gz-1> where z is a 
+//           new variable. Then g is contained in the radical of <ideal> <=> 
+//           1 is generator in G.
+///////////////////////////////////////////////////////////////////////////////
 proc rad_con (poly g,ideal I)
-"  USAGE:   rad_con(<poly>,<ideal>);
-  RETURNS: 1 (TRUE) (type <int>) if <poly> is contained in the radical of
-           <ideal>, 0 (FALSE) (type <int>) otherwise
-  EXAMPLE: example rad_con; shows an example
+"USAGE:   rad_con(g,I); g polynomial, I ideal
+RETURN:  1 (TRUE) (type int) if g is contained in the radical of I
+@*       0 (FALSE) (type int) otherwise
+EXAMPLE: example rad_con; shows an example
 "
 { def br=basering;
@@ -597,56 +598,117 @@
 }
 example
-{ "  EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7.";
-  echo=2;
-           ring R=0,(x,y,z),dp;
-           ideal I=x2+y2,z2;
-           poly f=x4+y4;
-           rad_con(f,I);
-           ideal J=x2+y2,z2,x4+y4;
-           poly g=z;
-           rad_con(g,I);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-proc lcm (ideal i)
-"USAGE:   lcm(i); i ideal
-RETURN:  poly = lcm(i[1],...,i[size(i)])
-NOTE:
+{ "EXAMPLE:"; echo=2;
+   ring R=0,(x,y,z),dp;
+   ideal I=x2+y2,z2;
+   poly f=x4+y4;
+   rad_con(f,I);
+   ideal J=x2+y2,z2,x4+y4;
+   poly g=z;
+   rad_con(g,I);
+}
+///////////////////////////////////////////////////////////////////////////////
+
+proc lcm (id, list #)
+"USAGE:   lcm(p[,q]); p int/intve q a list of integers or
+          p poly/ideal q a list of polynomials
+RETURN:  the least common multiple of the common entries of p and q:
+@*         - of type int if p is an int/intvec
+@*         - of type poly if p is a poly/ideal
 EXAMPLE: example lcm; shows an example
 "
 {
   int k,j;
-   poly p,q;
-  i=simplify(i,10);
-  for(j=1;j<=size(i);j++)
-  {
-    if(deg(i[j])>0)
-    {
-      p=i[j];
-      break;
-    }
-  }
-  if(deg(p)==-1)
-  {
-    return(1);
-  }
-  for (k=j+1;k<=size(i);k++)
-  {
-     if(deg(i[k])!=0)
+//------------------------------ integer case --------------------------------
+  if( typeof(id) == "int" or typeof(id) == "intvec" )
+  {
+     intvec i = id;
+     if (size(#)!=0)
      {
-        q=gcd(p,i[k]);
-        if(deg(q)==0)
+        for (j = 1; j<=size(#); j++)
         {
-           p=p*i[k];
+           if (typeof(#[j]) !="int" and typeof(#[j]) !="intvec")
+           { ERROR("// ** list element must be an integer");}
+           else
+           { i = i,#[j]; }
         }
-        else
+     }
+     int p,q;
+     if( i == 0 ) 
+     { 
+        return(0); 
+     }
+     for(j=1;j<=size(i);j++)
+     {
+       if( i[j] != 0 )
+       {
+         p=i[j];
+         break;
+       }
+     }
+     for (k=j+1;k<=size(i);k++)
+     {
+        if( i[k] !=0)
         {
+           q=gcd(p,i[k]);
            p=p/q;
            p=p*i[k];
         }
      }
-   }
-  return(p);
+     if(p <0 ) 
+     {return(-p);}
+     return(p);
+   }    
+
+//----------------------------- polynomial case ------------------------------
+  if( typeof(id) == "poly" or typeof(id) == "ideal" )
+  {
+     ideal i = id;
+     if (size(#)!=0)
+     {
+        for (j = 1; j<=size(#); j++)
+        {
+           if (typeof(#[j]) !="poly" and typeof(#[j]) !="ideal"
+              and typeof(#[j]) !="int" and typeof(#[j]) !="intvec")
+           { ERROR("// ** list element must be a polynomial");}
+           else
+           { i = i,#[j]; }
+        }
+     }
+     poly p,q;
+     i=simplify(i,10);
+     if(size(i) == 0) 
+     { 
+        return(0); 
+     }
+     for(j=1;j<=size(i);j++)
+     {
+       if(maxdeg(i[j])!= 0)
+       {
+         p=i[j];
+         break;
+       }
+     }
+     if(deg(p)==-1)
+     {
+       return(1);
+     }
+     for (k=j+1;k<=size(i);k++)
+     {
+        if(maxdeg(i[k])!=0)
+        {
+           q=gcd(p,i[k]);
+           if(maxdeg(q)==0)
+           {
+                 p=p*i[k];
+           }
+           else
+           {
+              p=p/q;
+              p=p*i[k];
+           }
+        }
+     }
+     return(p);
+   }
 }
 example
@@ -655,10 +717,9 @@
    poly  p = (x+y)*(y+z);
    poly  q = (z4+2)*(y+z);
-   ideal l=p,q;
-   poly  pr= lcm(l);
-   pr;
-   l=1,-1,p,1,-1,q,1;
-   pr=lcm(l);
-   pr;
+   lcm(p,q);
+   ideal i=p,q,y+z;
+   lcm(i,p);
+   lcm(2,3,6);
+   lcm(2..6);
 }
 
@@ -683,5 +744,4 @@
 ///////////////////////////////////////////////////////////////////////////////
 
-
 proc numerator(number n)
 "USAGE:    numerator(n); n number
@@ -701,4 +761,5 @@
   numerator(n);
 }
+///////////////////////////////////////////////////////////////////////////////
 
 proc denominator(number n)
@@ -721,19 +782,26 @@
 ////////////////////////////////////////////////////////////////////////
 
+////////////////////////////////////////////////////////////////////////
+// The idea of the procedures mod2id, id2mod and subrInterred is, to
+// perform standard basis computation or interreduction of a submodule
+// of a free module with generators gen(1),...,gen(n) over a ring R
+// in a ring R[t1,...,tn]/<ti*tj> with gen(i) maped to ti
+////////////////////////////////////////////////////////////////////////
+
 proc mod2id(matrix M,intvec vpos)
-"USAGE:     mod2id(M,vpos); M matrix, vpos intvec
-ASSUME:    vpos is an integer vector such that gen(i) corresponds
-           to var(vpos[i])
-           the basering contains variables var(vpos[i]) which do not occur
-           in M
-NOTE:      this procedure should be used in the following situation:
-           one wants to pass to a ring with new variables, say e(1),..,e(s),
-           which correspond to the components gen(1),..,gen(s) of the
-           module M such that e(i)*e(j)=0 for all i,j
-           the new ring should already exist and be the current ring
-RETURN:    ideal i in which each gen(i) from the module is replaced by
-           var(vpos[i]) and all monomials var(vpos[i])*var(vpos[j]) have
-           been added to the generating set of i
-EXAMPLE:   example mod2id; shows an example"
+"USAGE:   mod2id(M,vpos); M matrix, vpos intvec
+ASSUME:  vpos is an integer vector such that gen(i) corresponds
+         to var(vpos[i]).
+         The basering contains variables var(vpos[i]) which do not occur
+         in M.
+RETURN:  ideal I in which each gen(i) from the module is replaced by
+         var(vpos[i]) and all monomials var(vpos[i])*var(vpos[j]) have
+         been added to the generating set of I.
+NOTE:    This procedure should be used in the following situation:
+         one wants to pass to a ring with new variables, say e(1),..,e(s),
+         which correspond to the components gen(1),..,gen(s) of the
+         module M such that e(i)*e(j)=0 for all i,j.
+         The new ring should already exist and be the current ring
+EXAMPLE: example mod2id; shows an example"
 {
   int p = printlevel-voice+3;  // p=printlevel+1 (default: p=1)
@@ -771,15 +839,15 @@
 
 proc id2mod(ideal i,intvec vpos)
-"USAGE:     id2mod(I,vpos); I ideal, vpos intvec
-NOTE:      * use this procedure only makes sense if the ideal contains
-             all var(vpos[i])*var(vpos[j]) as monomial generators and
-             all other generators are linear combinations of the
-             var(vpos[i]) over the ring in the other variables
-           * this is the inverse procedure to mod2id and should be applied
-             only to ideals created by mod2id using the same intvec vpos
-             (possibly after a standard basis computation)
-RETURN:    module corresponding to the ideal by replacing var(vpos[i]) by
-           gen(i) and omitting all generators var(vpos[i])*var(vpos[j])
-EXAMPLE:   example id2mod; shows an example"
+"USAGE:   id2mod(I,vpos); I ideal, vpos intvec
+RETURN:  module corresponding to the ideal by replacing var(vpos[i]) by
+         gen(i) and omitting all generators var(vpos[i])*var(vpos[j])
+NOTE:    * This procedure only makes sense if the ideal contains
+           all var(vpos[i])*var(vpos[j]) as monomial generators and
+           all other generators of I are linear combinations of the
+           var(vpos[i]) over the ring in the other variables.
+         * This is the inverse procedure to mod2id and should be applied
+           only to ideals created by mod2id using the same intvec vpos
+           (possibly after a standard basis computation)
+EXAMPLE: example id2mod; shows an example"
 {
   int p = printlevel-voice+3;  // p=printlevel+1 (default: p=1)
@@ -820,5 +888,5 @@
                e.g. x_1,..,x_n and t_1,..,t_s
          mon:  ideal with monomial generators (not divisible by
-               one of the t_i) such that sm is contained in the module
+               any of the t_i) such that sm is contained in the module
                k[t_1,..,t_s]*mon[1]+..+k[t_1,..,t_s]*mon[size(mon)]
          iv:   intvec listing the variables which are supposed to be used
@@ -828,7 +896,10 @@
           l[2]=their coefficients after interreduction
           l[3]=l[1]*l[2]
-          (interreduced system of generators of sm seen as a submodule
-          of k[t_1,..,t_s]*mon[1]+..+k[t_1,..,t_s]*mon[size(mon)])
-EXAMPLE: example subrInterred; shows an example"
+PUPOSE:  Do interred only w.r.t. a subset of variables.  
+         The procedure returns an interreduced system of generators of 
+         sm considered as a k[t_1,..,t_s]-submodule of the free module
+         k[t_1,..,t_s]*mon[1]+..+k[t_1,..,t_s]*mon[size(mon)]).
+EXAMPLE: example subrInterred; shows an example
+"
 {
   int p = printlevel-voice+3;  // p=printlevel+1 (default: p=1)
