Changeset a9431c in git


Ignore:
Timestamp:
Mar 26, 2009, 5:37:19 PM (14 years ago)
Author:
Hans Schönemann <hannes@…>
Branches:
(u'jengelh-datetime', 'ceac47cbc86fe4a15902392bdbb9bd2ae0ea02c6')(u'spielwiese', 'a800fe4b3e9d37a38c5a10cc0ae9dfa0c15a4ee6')
Children:
53e33d93f45a825808d84cade536120482dc46c3
Parents:
54248e343a5d77bfd7f19c65855707d3950619e8
Message:
*hannes: new normal


git-svn-id: file:///usr/local/Singular/svn/trunk@11594 2c84dea3-7e68-4137-9b89-c4e89433aadc
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Singular/LIB/normal.lib

    r54248e ra9431c  
    11///////////////////////////////////////////////////////////////////////////////
    2 version="$Id: normal.lib,v 1.49 2006-07-25 17:54:28 Singular Exp $";
     2version="$Id: normal.lib,v 1.50 2009-03-26 16:37:19 Singular Exp $";
    33category="Commutative Algebra";
    44info="
    55LIBRARY:  normal.lib     Normalization of Affine Rings
    66AUTHORS:  G.-M. Greuel,  greuel@mathematik.uni-kl.de,
     7@*        S. Laplagne,   slaplagn@dm.uba.ar,
    78@*        G. Pfister,    pfister@mathematik.uni-kl.de
    89
     10
    911MAIN PROCEDURES:
    10  normal(I[,wd]);     computes the normalization of basering/I,
    11                      resp. computes the normalization of basering/I and
    12                      the delta invariant
    13  HomJJ(L);           presentation of End_R(J) as affine ring, L a list
    14  genus(I);           computes genus of the projective curve defined by I
    15  primeClosure(L);    integral closure of R/p (p prime), L a list
    16  closureFrac(L)      write poly in integral closure as element of Quot(R/p)
    17 
    18 AUXILIARY PROCEDURE:
    19  deltaLoc(f,S);      (sum of) delta invariant(s) at conjugated singular points
     12 normal(I[...]);     normalization of an affine ring
     13 normalP(I,[...];    normalization of an affine ring in positive characteristic
     14 normalC(I,[...];    normalization of an affine ring through a chain of rings
     15 HomJJ(L);           presentation of the End_R(J) as affine ring, J an ideal
     16 genus(I);           computes the geometric genus of a projective curve
     17 primeClosure(L);    integral closure of R/p, p a prime ideal
     18 closureFrac(L);     write a poly in integral closure as element of Quot(R/p)
     19 iMult(L);           intersection multiplicity of the ideals of the list L
     20
     21AUXILIARY PROCEDURES:
     22 deltaLoc(f,S);      sum of delta invariants at conjugated singular points
     23 locAtZero(I);       checks whether the zero set of I is located at 0
     24 norTest(i,nor;)     checks whether result of normal or mormal_p was correct
    2025";
    2126
     
    3035LIB "hnoether.lib";
    3136LIB "reesclos.lib";
     37LIB "algebra.lib";
     38
     39
     40///////////////////////////////////////////////////////////////////////////////
     41
     42proc normal(ideal id, list #)
     43"USAGE:  normal(id [,choose]); id = radical ideal, choose = optional string. @*
     44         Optional parameters in list choose (can be entered in any order):@*
     45         Decomposition:@*
     46         - \"prim\" -> computes first the minimal associated primes, and then
     47         the normalization of each prime. (default)@*
     48         - \"equidim\" -> computes first an equidimensional decomposition,
     49         and then the normalization of each component. @*
     50         - \"noDeco\" -> no preliminary decomposition is done. If the ideal is
     51         not equidimensional radical, output might be wrong.@*
     52         - \"isPrim\" -> assumes that the ideal is prime. If assumption does
     53         not hold, output might be wrong.@*
     54         - \"noFac\" -> factorization is avoided in the computation of the
     55         minimal associated primes;
     56         Other:@*
     57         - \"useRing\" -> uses the original ring ordering.@*
     58         If the ring ordering is not global, it will change to a global
     59         ordering only for computing radicals and prime or equidimensional
     60         decompositions.@*
     61         If this option is not set, changes to dp ordering and perform all
     62         computation with respect to this ordering.@*
     63         - \"withDelta\" (or \"wd\") -> returns also the delta invariants.
     64         If choose is not given or empty, the default options are used.@*
     65ASSUME:  The ideal must be radical, for non-radical ideals the output may
     66         be wrong (id=radical(id); makes id radical). However, when using
     67         \"prim\" option the minimal associated primes of id are computed first
     68         and hence normal computes the normalization of the radical of id.
     69         \"isPrim\" should only be used if id is known to be prime.
     70RETURN:  a list, say nor, of size 1 (resp. 2 with option \"withDelta\").
     71@format
     72         The first element nor[1] is a list of r elements, where r is the
     73         number of associated primes P_i with option \"prim\" (resp. >= no
     74         of equidimenensional components P_i with option \"equidim\").@*
     75         Each element of nor[1] is a list with the information on the
     76         normalization of the i-th component, i.e. the integral closure
     77         in its field of fractions (as affine ring).@*
     78         Each list nor[1][i] contains 3 elements (resp. 4 with option
     79         \"withDelta\"). @*
     80         The first two element of nor[1][i] give the normalization by
     81         module generators. The normalization is of the form
     82         1/c * U, with U = nor[1][i][1] an ideal of R / P_i and
     83         c = nor[1][i][2] a polynomial in R / P_i.@*
     84         The third element is a ring Ri=nor[1][i][3], i=1..r,
     85         which contains two ideals with given
     86         names @code{norid} and @code{normap} such that @*
     87         - Ri/norid is the normalization of the i-th component.
     88         - the direct sum of the rings Ri/norid is the normalization
     89           of basering/id; @*
     90         - @code{normap} gives the normalization map from basering/id to
     91           Ri/norid for each j.@*
     92         When option \"withDelta\" is set, the forth element nor[1][i][4] is
     93         the delta invariant of the i-th component. (-1 means infinite, and 0
     94         that basering/P_i is normal)@*
     95         @*
     96         Also, When option \"withDelta\" is set the second element of the list
     97         nor, nor[2], is an integer, the total delta invariant of basering/id
     98         (-1 means infinite, and 0 that basering/id is normal).
     99@end format
     100THEORY:  We use a general algorithm described in [G.-M. Greuel, S. Laplagne,
     101         F. Seelisch: Normalization of Rings (2009)].
     102         The delta invariant of a reduced ring K[x1,...,xn]/id is
     103             dim_K(normalization(K[x1,...,xn]/id) / K[x1,...,xn]/id)
     104         We call this number also the delta invariant of id.
     105NOTE:    To use the i-th ring type: @code{def R=nor[1][i][3]; setring R;}.
     106@*       Increasing/decreasing printlevel displays more/less comments
     107         (default: printlevel=0).
     108@*       Implementation works also for local rings.         
     109@*       Not implemented for quotient rings.
     110@*       If the input ideal id is weighted homogeneous a weighted ordering may
     111         be used (qhweight(id); computes weights).
     112KEYWORDS: normalization; integral closure; delta invariant.
     113EXAMPLE: example normal; shows an example
     114"
     115
     116   intvec opt = option(get);     // Save current options
     117
     118   int i,j;
     119   int decomp;  // Preliminar decomposition:
     120                // 0 -> no decomposition (id is assumed to be prime)
     121                // 1 -> no decomposition
     122                //      (id is assumed to be equidimensional radical)
     123                // 2 -> equidimensional decomposition
     124                // 3 -> minimal associated primes
     125   int noFac, useRing, withDelta;
     126   int dbg = printlevel - voice + 2;
     127   int nvar = nvars(basering);
     128   int chara  = char(basering);
     129   list result;
     130   list keepresult;
     131   list ringStruc;
     132   ideal U;
     133   poly c;
     134   
     135   // Default methods:
     136   noFac = 0;         // Use facSTD when computing minimal associated primes
     137   decomp = 3;        // Minimal associated primes
     138   useRing = 0;       // Change first to dp ordering, and perform all
     139                      // computations there.
     140   withDelta = 0;     // Do not compute the delta invariant.
     141 
     142
     143  //--------------------------- define the method ---------------------------
     144  string method;                //make all options one string in order to use
     145                               //all combinations of options simultaneously
     146  for ( i=1; i <= size(#); i++ )
     147  {
     148    if ( typeof(#[i]) == "string" )
     149    {
     150      method = method + #[i];
     151    }
     152  }
     153
     154  //--------------------------- choosen methods -----------------------
     155  if ( find(method,"isprim") or find(method,"isPrim") )
     156  {decomp = 0;}
     157 
     158  if ( find(method,"nodeco") or find(method,"noDeco") )
     159  {decomp = 1;}
     160 
     161  if ( find(method,"equidim") )
     162  {decomp = 2;}
     163 
     164  if ( find(method,"prim") )
     165  {decomp = 3;}
     166 
     167  if ( find(method,"nofac") or find(method,"noFac") )
     168  {noFac=1;}
     169 
     170  if ( (find(method,"useRing") or find(method,"usering")) and (ordstr(basering) != "dp("+string(nvars(basering))+"),C"))
     171  {useRing = 1;}
     172 
     173  if ( find(method,"withDelta") or find(method,"wd") or find(method,"withdelta"))
     174  {
     175    if((decomp == 0) or (decomp == 3)){
     176      withDelta = 1;
     177    } else {
     178      "WARNING: the delta invariants cannot be computed with an equidimensional";
     179      "         decomposition.";
     180      "         Use option \"prim\" to compute first the minimal associated primes.";
     181      "";
     182    }
     183  }
     184
     185  kill #;
     186  list #;
     187
     188  //------------------------ change ring if required ------------------------
     189  // If the ordering is not global, we change to dp ordering for computing the
     190  // min ass primes.
     191  // If the ordering is global, but not dp, and useRing = 0, we also change to
     192  // dp ordering.
     193 
     194  int isGlobal = ord_test(basering);      // Checks if the original ring has
     195                                          // global ordering.
     196 
     197  def origR = basering;   // origR is the original ring
     198                          // R is the ring where computations will be done
     199   
     200  if((useRing  == 1) and (isGlobal == 1)){
     201    def globR = basering;
     202  } else {
     203    // We change to dp ordering.
     204    list rl = ringlist(origR);
     205    list origOrd = rl[3];
     206    list newOrd = list("dp", intvec(1:nvars(origR))), list("C", 0);
     207    rl[3] = newOrd;
     208    def globR = ring(rl);
     209    setring globR;
     210    ideal id = fetch(origR, id); 
     211  }
     212
     213  //------------------------ preliminary decomposition-----------------------
     214  list prim;
     215  if(decomp == 2){
     216    dbprint(dbg, "// Computing the equidimensional decomposition...");
     217    prim = equidim(id);
     218  }
     219  if((decomp == 0) or (decomp == 1)){
     220    prim = id;
     221  }
     222  if(decomp == 3){
     223    dbprint(dbg, "// Computing the minimal associated primes...");
     224    if( noFac )
     225    { prim = minAssGTZ(id,1); }
     226    else
     227    { prim = minAssGTZ(id); }
     228  }
     229
     230  // if ring was not global and useRing is on, we go back to the original ring
     231  if((useRing == 1) and (isGlobal != 1)){
     232    setring origR;
     233    def R = basering;
     234    list prim = fetch(globR, prim);
     235  } else {
     236    def R = basering;
     237    if(useRing == 0){
     238      ideal U;
     239      poly c;
     240    }
     241  }
     242   
     243  if(dbg>=1)
     244  { 
     245    prim; "";
     246    "// number of components is", size(prim);
     247    "";
     248  }
     249   
     250  // ---------------- normalization of the components-------------------------
     251  // calls normalM to compute the normalization of each component.
     252
     253  list norComp;       // The normalization of each component.
     254  int delt;
     255  int deltI = 0;
     256  int totalComps = 0;
     257
     258  setring origR;
     259  def newROrigOrd;
     260  list newRListO;
     261  setring R;
     262  def newR;
     263  list newRList;
     264   
     265  for(i=1; i<=size(prim); i++)
     266  {
     267    if(dbg>=2){pause();}
     268    if(dbg>=1){
     269      "// start computation of component",i;
     270      "   --------------------------------";
     271    }
     272    if(groebner(prim[i])[1] != 1){
     273      if(dbg>=2){
     274        "We compute the normalization in the ring"; basering;
     275      }
     276      printlevel = printlevel + 1;
     277      norComp = normalM(prim[i], decomp, withDelta);
     278      printlevel = printlevel - 1;     
     279      for(j = 1; j <= size(norComp); j++){
     280        newR = norComp[j][3];
     281        newRList = ringlist(newR);
     282        U = norComp[j][1];
     283        c = norComp[j][2];
     284        if(withDelta){
     285          delt = norComp[j][4];
     286          if((delt >= 0) and (deltI >= 0)){
     287            deltI = deltI + delt;
     288          } else {
     289            deltI = -1;
     290          }
     291        }
     292        if(useRing == 0){
     293        // We go back to the original ring.
     294        setring origR;
     295        U = fetch(R, U);
     296        c = fetch(R, c);
     297        newRListO = imap(R, newRList);
     298        // We change the ordering in the new ring.
     299        if(nvars(newR) > nvars(origR)){
     300          newRListO[3]=insert(origOrd, newRListO[3][1]);
     301        } else {
     302          newRListO[3] = origOrd;
     303        }
     304        newROrigOrd = ring(newRListO);
     305        setring newROrigOrd;
     306        ideal norid = imap(newR, norid);
     307        ideal normap = imap(newR, normap);
     308        export norid;
     309        export normap;
     310        setring origR;
     311        totalComps++;
     312        result[totalComps] = list(U, c, newROrigOrd);
     313        if(withDelta){
     314          result[totalComps] = insert(result[totalComps], delt, 3);
     315        }
     316        setring R;
     317        } else {
     318          setring R;
     319          totalComps++;
     320          result[totalComps] = norComp[j];
     321        }
     322      }
     323    }
     324  }
     325 
     326  // -------------------------- delta computation ---------------------------- 
     327  if(withDelta == 1){
     328    // Intersection multiplicities of list prim, sp=size(prim).
     329    if ( dbg >= 1 )
     330    {
     331      "// Sum of delta for all components: ", deltI;
     332    }   
     333    if(size(prim) > 1){
     334      dbprint(dbg, "// Computing the sum of the intersection multiplicities of the components...");
     335      int mul = iMult(prim);
     336      if ( mul < 0 )
     337      {
     338        deltI = -1;
     339      } else {
     340        deltI = deltI + mul;
     341      }
     342      if ( dbg >= 1 )
     343      {
     344        "// Intersection multiplicity is : ", mul;
     345      }         
     346    }
     347  }
     348 
     349  // -------------------------- prepare output ------------------------------   
     350  setring origR;
     351  if(withDelta){
     352    result = result, deltI;
     353  } else {
     354    result = list(result);
     355  }
     356 
     357  option(set, opt);
     358  return(result);
     359}
     360
     361
     362example
     363{ "EXAMPLE:";
     364  printlevel = printlevel+1;
     365  echo = 2;
     366  ring s = 0,(x,y),dp;
     367  ideal i = (x2-y3)*(x2+y2)*x;
     368  list nor = normal(i, "withDelta");
     369  nor;
     370
     371  // 2 branches have delta = 1, and 1 branch has delta = 0
     372  // the total delta invariant is 13
     373
     374  def R2 = nor[1][2][3];  setring R2;
     375  norid; normap;
     376   
     377  echo = 0;
     378  printlevel = printlevel-1;
     379  pause("   hit return to continue"); echo=2;
     380
     381  ring r = 2,(x,y,z),dp;
     382  ideal i = z3-xy4;
     383  list nor = normal(i, "withDelta");  nor; 
     384  // the delta invariant is infinite
     385  // xy2z/z2 and xy3/z2 generate the integral closure of r/i as r/i-module
     386  // in its quotient field Quot(r/i)
     387
     388  // the normalization as affine algebra over the ground field:             
     389  def R = nor[1][1][3]; setring R;
     390  norid; normap;
     391}
     392
    32393///////////////////////////////////////////////////////////////////////////////
    33394
     
    39400@*       p    = nonzero divisor of R
    40401COMPUTE: Endomorphism ring End_R(J)=Hom_R(J,J) with its ring structure as
    41          affine ring, together with the canonical map R --> Hom_R(J,J),
     402         affine ring, together with the map R --> Hom_R(J,J) of affine rings,
    42403         where R is the quotient ring of P modulo the standard basis SBid.
    43 RETURN:  a list l of two objects
     404RETURN:  a list l of three objects
    44405@format
    45406         l[1] : a polynomial ring, containing two ideals, 'endid' and 'endphi'
     
    47408               endphi describes the canonical map R -> Hom_R(J,J)
    48409         l[2] : an integer which is 1 if phi is an isomorphism, 0 if not
    49          l[3] : an integer, the contribution to delta
     410         l[3] : an integer, = dim_K(Hom_R(J,J)/R) (the contribution to delta)
     411                if the dimension is finite, -1 otherwise
    50412@end format
    51413NOTE:    printlevel >=1: display comments (default: printlevel=0)
     
    54416{
    55417//---------- initialisation ---------------------------------------------------
    56    int isIso,isPr,isCo,isRe,isEq,oSAZ,ii,jj,q,y;
     418   int isIso,isPr,isHy,isCo,isRe,isEq,oSAZ,ii,jj,q,y;
    57419   intvec rw,rw1;
    58420   list L;
     
    103465   if ( y>=1 )
    104466   {
    105      "// compute p*Hom(J,J) = p*J:J, p a non-zerodivisor";
    106      "//   p is equal to:"; "";
    107      p;
    108      "";
     467     "// compute p*Hom(J,J) = p*J:J";
     468     "//   the ideal J:";J;
    109469   }
    110470   f  = quotient(p*J,J);
    111471
     472   //### (neu GMG 4.10.08) divide by the greatest common divisor:
     473   poly gg = gcd( f[1],p );
     474   for(ii=2; ii <=ncols(f); ii++)
     475   {
     476      gg=gcd(gg,f[ii]);
     477   }
     478   for(ii=1; ii<=ncols(f); ii++)
     479   {
     480      f[ii]=f[ii]/gg;
     481   }
     482   p = p/gg;
     483
    112484   if ( y>=1 )
    113    { "// the module p*Hom(J,J) = p*J:J, p a non-zerodivisor";
    114       "// p"; p;
    115       "// f=p*J:J";f;
     485   { 
     486      "//   the non-zerodivisor p:"; p;
     487      "//   the module p*Hom(J,J) = p*J:J :"; f;
     488      "";
    116489   }
    117490   f2 = std(p);
     
    119492//---------- Test: Hom(J,J) == R ?, if yes, go home ---------------------------
    120493
    121    rf = interred(reduce(f,f2));       // represents p*Hom(J,J)/p*R = Hom(J,J)/R
     494   //rf = interred(reduce(f,f2));
     495   //### interred hier weggelassen, unten zugefŸgt
     496   rf = reduce(f,f2);       //represents p*Hom(J,J)/p*R = Hom(J,J)/R
    122497   if ( size(rf) == 0 )
    123498   {
     
    132507      ideal endphi = maxideal(1);
    133508      ideal endid = fetch(P,id);
    134       L=substpart(endid,endphi,homo,rw);
    135       def lastRing=L[1];
     509      endid = simplify(endid,2);
     510      L = substpart(endid,endphi,homo,rw);   //## hier substpart
     511      def lastRing = L[1];
    136512      setring lastRing;
    137513
     
    142518      attrib(endid,"isRegInCodim2",isRe);
    143519      attrib(endid,"isEqudimensional",isEq);
     520      attrib(endid,"isHypersurface",0);
    144521      attrib(endid,"isCompleteIntersection",0);
    145       attrib(endid,"isRad",0);
     522      attrib(endid,"isRadical",0);
    146523      L=lastRing;
    147524      L = insert(L,1,1);
     
    150527      {
    151528         "//   R=Hom(J,J)";
    152          "   ";
    153529         lastRing;
    154          "   ";
    155530         "//   the new ideal";
    156531         endid;
    157532         "   ";
    158533         "//   the old ring";
    159          "   ";
    160534         P;
    161          "   ";
    162535         "//   the old ideal";
    163          "   ";
    164536         setring P;
    165537         id;
    166538         "   ";
    167539         setring lastRing;
    168          "//   the map";
    169          "   ";
     540         "//   the map to the new ring";
    170541         endphi;
    171542         "   ";
    172543         pause();
    173          newline;
     544         "";
    174545      }
    175546      setring P;
     
    181552      "// R is not equal to Hom(J,J), we have to try again";
    182553      pause();
    183       newline;
     554      "";
    184555   }
    185556//---------- Hom(J,J) != R: create new ring and map from old ring -------------
    186557// the ring newR1/SBid+syzf will be isomorphic to Hom(J,J) as R-module
    187 
    188    f=mstd(f)[2];
    189    ideal ann=quotient(f2,f);
    190    int delt;
    191    if(isIso&&isEq){delt=vdim(std(modulo(f,ideal(p))));}
     558// f2=p (i.e. ideal generated by p)
     559
     560   //f = mstd(f)[2];              //### geŠndert GMG 04.10.08
     561   //ideal ann = quotient(f2,f);  //### f durch rf ersetzt 
     562   rf = mstd(rf)[2];              //rf = NF(f,p), hence <p,rf> = <p,f>
     563   ideal ann = quotient(f2,rf);   //p:f = p:rf
     564 
     565   //------------- compute the contribution to delta ----------
     566   //delt=dim_K(Hom(JJ)/R (or -1 if infinite)
     567 
     568   int delt=vdim(std(modulo(f,ideal(p))));   
    192569
    193570   f = p,rf;          // generates pJ:J mod(p), i.e. p*Hom(J,J)/p*R as R-module
    194571   q = size(f);
    195 
    196572   syzf = syz(f);
    197573
     
    211587   }
    212588
    213    map psi1 = P,maxideal(1);
    214    ideal SBid = psi1(SBid);
     589   //map psi1 = P,maxideal(1);          //### psi1 durch fetch ersetzt
     590   //ideal SBid = psi1(SBid);       
     591   ideal SBid = fetch(P,SBid);
    215592   attrib(SBid,"isSB",1);
    216593
    217594   qring newR = std(SBid);
    218595
    219    map psi = R,ideal(X(1..nvars(R)));
    220    ideal id = psi(id);
    221    ideal f = psi(f);
    222    module syzf = psi(syzf);
     596   //map psi = R,ideal(X(1..nvars(R)));  //### psi durch fetch ersetzt
     597   //ideal id = psi(id);
     598   //ideal f = psi(f);
     599   //module syzf = psi(syzf);
     600   ideal id = fetch(R,id);
     601   ideal f = fetch(R,f);
     602   module syzf = fetch(R,syzf);
    223603   ideal pf,Lin,Quad,Q;
    224604   matrix T,A;
     
    231611// It is a fact, that the kernel is generated by the linear and the quadratic
    232612// relations
     613// f=p,rf, rf=reduce(f,p), generates pJ:J mod(p),
     614// i.e. p*Hom(J,J)/p*R as R-module
    233615
    234616   pf = f[1]*f;
     
    238620   {
    239621      "// the ring structure of Hom(J,J) as R-algebra";
    240       " ";
    241       "//   the linear relations";
    242       " ";
     622      "//   the linear relations:";
    243623      Lin;
    244       "   ";
    245    }
    246 
     624   }
     625
     626   poly ff;
    247627   for (ii=2; ii<=q; ii++ )
    248628   {
    249629      for ( jj=2; jj<=ii; jj++ )
    250630      {
    251          A = lift(pf,f[ii]*f[jj]);
    252          Quad = Quad, ideal(T(jj)*T(ii) - T*A);          // quadratic relations
     631         ff = NF(f[ii]*f[jj],std(0));       //this makes lift much faster
     632         A = lift(pf,ff);                   //ff lin. comb. of elts of pf mod I
     633         Quad = Quad, ideal(T(jj)*T(ii) - T*A);  //quadratic relations
    253634      }
    254635   }
     
    257638   {
    258639      "//   the quadratic relations";
    259       "   ";
    260       interred(Quad);
     640      Quad;
    261641      pause();
    262642      newline;
     
    264644   Q = Lin,Quad;
    265645   Q = subst(Q,T(1),1);
    266    Q=mstd(Q)[2];
     646   //Q = mstd(Q)[2];            //### sehr aufwendig, daher weggelassen (GMG)
     647   //### ev das neue interred
     648   //mstd dient nur zum verkleinern, die SB-Eigenschaft geht spaeter verloren
     649   //da in neuen Ring abgebildet und mit id vereinigt
     650                       
    267651//---------- reduce number of variables by substitution, if possible ----------
    268652   if (homo==1)
     
    275659   }
    276660
    277    ideal endid  = imap(newR,id),imap(newR,Q);
     661   ideal endid  = imap(newR,id),imap(newR,Q); 
     662   //hier wird Q weiterverwendet, die SB-Eigenschaft wird nicht verwendet.
     663   endid = simplify(endid,2);
    278664   ideal endphi = ideal(X(1..nvars(R)));
    279665
    280    L=substpart(endid,endphi,homo,rw);
     666   L = substpart(endid,endphi,homo,rw);
    281667
    282668   def lastRing=L[1];
     
    287673   ideal an=sigma(ann);
    288674   export(an);  //noetig?
    289    ideal te=an,endid;
    290    if(isIso&&(size(reduce(te,std(maxideal(1))))==0))
    291    {
    292       attrib(endid,"onlySingularAtZero",oSAZ);
    293    }
    294    kill te;
    295    attrib(endid,"isCohenMacaulay",isCo);
     675   //ideal te=an,endid;
     676   //if(isIso && (size(reduce(te,std(maxideal(1))))==0))   //#### ok???
     677   // {
     678   //    attrib(endid,"onlySingularAtZero",oSAZ);
     679   // }
     680   //kill te;
     681   attrib(endid,"isCohenMacaulay",isCo);                //#### ok???
    296682   attrib(endid,"isPrim",isPr);
    297683   attrib(endid,"isIsolatedSingularity",isIso);
    298684   attrib(endid,"isRegInCodim2",isRe);
    299685   attrib(endid,"isEquidimensional",isEq);
     686   attrib(endid,"isHypersurface",0);
    300687   attrib(endid,"isCompleteIntersection",0);
    301    attrib(endid,"isRad",0);
     688   attrib(endid,"isRadical",0);
    302689   if(y>=1)
    303690   {
    304       "//   the new ring after reduction of the number of variables";
    305       "   ";
     691      "// the new ring after reduction of the number of variables";
    306692      lastRing;
    307       "   ";
    308693      "//   the new ideal";
    309       "   ";
    310       endid;
    311       "   ";
    312       "//   the old ring";
    313       "   ";
     694      endid;  "";
     695      "// the old ring";
    314696      P;
    315       "   ";
    316697      "//   the old ideal";
    317       "   ";
    318698      setring P;
    319699      id;
    320700      "   ";
    321701      setring lastRing;
    322       "//   the map";
    323       "   ";
     702      "//   the map to the new ring";
    324703      endphi;
    325704      "   ";
    326705      pause();
    327       newline;
     706      "";
    328707   }
    329708   L = lastRing;
    330709   L = insert(L,0,1);
    331    L[3]=delt;
     710   L[3] = delt;
    332711   return(L);
    333712}
     
    338717  ideal J  = x,y;
    339718  poly p   = x;
    340   list Li = std(id),id,J,p;
     719  list Li  = std(id),id,J,p;
    341720  list L   = HomJJ(Li);
    342721  def end = L[1];    // defines ring L[1], containing ideals endid, endphi
     
    346725  map psi = r,endphi;// defines the canonical map r/id -> End(r/id)
    347726  psi;
     727  L[3];              // contribution to delta
    348728}
    349729
     730
    350731///////////////////////////////////////////////////////////////////////////////
    351 
    352 proc normal(ideal id, list #)
    353 "USAGE:   normal(i [,choose]);  i a radical ideal, choose empty, 1 ,\"g\" \"wd\"
    354          if choose=1 the normalization of the associated primes is computed
    355          (which is sometimes more efficient);
    356          if @code{choose=\"wd\"} the delta invariant is computed
    357          simultaneously; this may take much more time in the reducible case,
    358          since the factorizing standard basis algorithm cannot be used.@*
    359          if @code{choose=\"g\"} the generators of the integral closure
    360          are computed.
    361 ASSUME:  The ideal must be radical, for non-radical ideals the output may
    362          be wrong (i=radical(i); makes i radical)
    363 RETURN:  a list of rings, say nor and in case of @code{choose=\"wd\"} an
    364          integer at the end of the list.
    365          In case of @code{choose=\"g\"} it returns a list of polynomials
    366          g_1,...,g_k+1 at the end of the list such that g_1/g_k+1,...
    367          g_k/g_k+1 generate the integral closure.
    368          Each ring @code{nor[i]} contains two ideals with given names
    369          @code{norid} and @code{normap} such that@*
    370          - the direct sum of the rings @code{nor[i]/norid} is the
    371          normalization of basering/id;@*
    372          - @code{normap} gives the normalization map from basering/id to
    373          @code{nor[i]/norid} (for each i).
    374 NOTE:    to use the i-th ring type: @code{def R=nor[i]; setring R;}.
    375 @*       Increasing printlevel displays more comments (default: printlevel=0).
    376 @*       Not implemented for local or mixed orderings.
    377 @*       If the input ideal i is weighted homogeneous a weighted ordering may
    378          be used (qhweight(i); computes weights).
    379 KEYWORDS: normalization; delta invariant.
    380 EXAMPLE: example normal; shows an example
     732//compute intersection multiplicities as needed for delta(I) in
     733//normalizationPrimes and normalP:
     734
     735proc iMult (list prim)
     736"USAGE:   iMult(L);  L a list of ideals
     737RETURN:  int, the intersection multiplicity of the ideals of L;
     738         if iMult(L) is infinite, -1 is returned.
     739THEORY:  If r=size(L)=2 then iMult(L) = vdim(std(L[1]+L[2])) and in general
     740         iMult(L) = sum{ iMult(L[j],Lj) | j=1..r-1 } with Lj the intersection
     741         of L[j+1],...,L[r]. If I is the intersection of all ideals in L then
     742         we have delta(I) = delta(L[1])+...+delta(L[r]) + iMult(L) where
     743         delta(I) = vdim (normalisation(R/I)/(R/I)), R the basering.
     744EXAMPLE: example iMult; shows an example
    381745"
    382 {
    383    int i,j,y,withdelta,withgens;
    384    string sr;
    385    list result,prim,keepresult;
    386    y = printlevel-voice+2;
    387    if(size(#)>0)
    388    {
    389      if(typeof(#[1])=="string")
     746{    int i,mul,mu;
     747     int sp = size(prim);
     748     int y = printlevel-voice+2;
     749     if ( sp > 1 )
    390750     {
    391        if(#[1]=="g")
    392        {
    393           withgens=1;
    394        }
    395        else
    396        {
    397           withdelta=1;
    398        }
    399        kill #;
    400        list #;
     751        ideal I(sp-1) = prim[sp];
     752        mu = vdim(std(I(sp-1)+prim[sp-1]));
     753        mul = mu;
     754        if ( y>=1 )
     755        {
     756          "// intersection multiplicity of component",sp,"with",sp-1,":"; mu;
     757        }
     758        if ( mu >= 0 )
     759        {
     760           for (i=sp-2; i>=1 ; i--)
     761           {
     762              ideal I(i) = intersect(I(i+1),prim[i+1]);
     763              mu = vdim(std(I(i)+prim[i]));
     764              if ( mu < 0 ) 
     765              {
     766                break;
     767              }
     768              mul = mul + mu;
     769              if ( y>=1 )
     770              {
     771                "// intersection multiplicity of components",sp,"...",i+1,"with",i; mu;
     772              }
     773           }
     774        }
    401775     }
    402    }
    403    attrib(id,"isRadical",1);
    404    if ( ord_test(basering) != 1)
    405    {
    406      "";
    407      "// Not implemented for this ordering,";
    408      "// please change to global ordering!";
    409      return(result);
    410    }
    411    if(withgens)
    412    {
    413       list pr=minAssGTZ(id);
    414       if(size(pr)>1){ERROR("ideal is not prime");}
    415       def R=basering;
    416       if(defined(ker)){kill ker;}
    417       ideal ker=id;
    418       export(ker);
    419       list l=R;
    420       l=primeClosure(l);
    421       list gens=closureGenerators(l);
    422       list resu=l[size(l)],gens;
    423       dbprint(y+1,"
    424 // 'normal' created a list of one ring.
    425 // nor[2] is a list of elements of the basering such that
    426 // nor[2][i]/nor[2][size(nor[2])] generate the integral closure.
    427 // To see the rings, type (if the name of your list is nor):
    428      show( nor);
    429 // To access the 1-st ring and map (similar for the others), type:
    430      def R = nor[1]; setring R;  norid; normap;
    431 // R/norid is the 1-st ring of the normalization and
    432 // normap the map from the original basering to R/norid");
    433 
    434       return(resu);
    435    }
    436    if( typeof(attrib(id,"isCompleteIntersection"))=="int" )
    437    {
    438       if(attrib(id,"isCompleteIntersection")==1)
    439       {
    440          attrib(id,"isCohenMacaulay",1);
    441          attrib(id,"isEquidimensional",1);
    442       }
    443    }
    444    if( typeof(attrib(id,"isCohenMacaulay"))=="int" )
    445    {
    446       if(attrib(id,"isCohenMacaulay")==1)
    447       {
    448          attrib(id,"isEquidimensional",1);
    449       }
    450    }
    451    if( typeof(attrib(id,"isPrim"))=="int" )
    452    {
    453       if(attrib(id,"isPrim")==1)
    454       {
    455          attrib(id,"isEquidimensional",1);
    456       }
    457    }
    458    if(size(#)==0)
    459    {
    460       if( typeof(attrib(id,"isEquidimensional"))=="int" )
    461       {
    462          if(attrib(id,"isEquidimensional")==1)
    463          {
    464             prim[1]=id;
    465          }
    466          else
    467          {
    468             prim=equidim(id);
    469          }
    470       }
    471       else
    472       {
    473          prim=equidim(id);
    474       }
    475       if(y>=1)
    476       {
    477          "// we have ",size(prim),"equidimensional components";
    478       }
    479       if(withdelta &&(size(prim)>1))
    480       {
    481          withdelta=0;
    482          "WARNING!  cannot compute delta,";
    483          "the ideal is not equidimensional";
    484       }
    485       if(!withdelta)
    486       {
    487          option(redSB);
    488          for(j=1;j<=size(prim);j++)
    489          {
    490             keepresult=keepresult+facstd(prim[j]);
    491          }
    492          prim=keepresult;
    493          option(noredSB);
    494       }
    495    }
    496    else
    497    {
    498       if( typeof(attrib(id,"isPrim"))=="int" )
    499       {
    500          if(attrib(id,"isPrim")==1)
    501          {
    502             prim[1]=id;
    503          }
    504          else
    505          {
    506             prim=minAssGTZ(id);
    507          }
    508       }
    509       else
    510       {
    511          prim=minAssGTZ(id);
    512       }
    513       if(y>=1)
    514       {
    515          "// we have ",size(prim),"irreducible components";
    516       }
    517    }
    518    for(i=1; i<=size(prim); i++)
    519    {
    520       if(y>=1)
    521       {
    522          "// we are in loop ",i;
    523       }
    524       attrib(prim[i],"isCohenMacaulay",0);
    525       if(size(#)!=0)
    526       {
    527          attrib(prim[i],"isPrim",1);
    528       }
    529       else
    530       {
    531          attrib(prim[i],"isPrim",0);
    532       }
    533       attrib(prim[i],"isRegInCodim2",0);
    534       attrib(prim[i],"isIsolatedSingularity",0);
    535       attrib(prim[i],"isEquidimensional",1);
    536       attrib(prim[i],"isCompleteIntersection",0);
    537       attrib(prim[i],"onlySingularAtZero",0);
    538       if( typeof(attrib(id,"onlySingularAtZero"))=="int" )
    539       {
    540             if(attrib(id,"onlySingularAtZero")==1)
    541              {attrib(prim[i],"onlySingularAtZero",1); }
    542       }
    543 
    544       if( typeof(attrib(id,"isIsolatedSingularity"))=="int" )
    545       {
    546             if(attrib(id,"isIsolatedSingularity")==1)
    547              {attrib(prim[i],"isIsolatedSingularity",1); }
    548       }
    549 
    550       if( typeof(attrib(id,"isCompleteIntersection"))=="int" )
    551       {
    552             if((attrib(id,"isIsolatedSingularity")==1)&&(size(#)==0))
    553              {attrib(prim[i],"isIsolatedSingularity",1); }
    554       }
    555       keepresult=normalizationPrimes(prim[i],maxideal(1),0);
    556 
    557       for(j=1;j<=size(keepresult)-1;j++)
    558       {
    559          result=insert(result,keepresult[j]);
    560       }
    561       sr = string(size(result));
    562    }
    563    if(withdelta)
    564    {
    565       sr = string(size(keepresult)-1);
    566       result=keepresult;
    567    }
    568       dbprint(y+1,"
    569 // 'normal' created a list of "+sr+" ring(s).");
    570       if(withdelta)
    571       {
    572         dbprint(y+1,"// nor["+sr+"+1] is the delta-invariant.");
    573       }
    574       dbprint(y+1,"// To see the rings, type (if the name of your list is nor):
    575      show( nor);
    576 // To access the 1-st ring and map (similar for the others), type:
    577      def R = nor[1]; setring R;  norid; normap;
    578 // R/norid is the 1-st ring of the normalization and
    579 // normap the map from the original basering to R/norid");
    580 
    581       //kill endphi,endid;
    582       return(result);
     776     return(mul);
    583777}
    584778example
    585779{ "EXAMPLE:"; echo = 2;
    586    ring r=32003,(x,y,z),wp(2,1,2);
    587    ideal i=z3-xy4;
    588    list nor=normal(i);
    589    show(nor);
    590    def r1=nor[1];
    591    setring r1;
    592    norid;
    593    normap;
    594 
    595    ring s=0,(x,y),dp;
    596    ideal i=(x-y^2)^2 - y*x^3;
    597    nor=normal(i,"wd");
    598    //the delta-invariant
    599    nor[size(nor)];
    600    nor=normal(i,"g");
    601    nor[size(nor)];
     780   ring s  = 23,(x,y),dp;
     781   list L = (x-y),(x3+y2);
     782   iMult(L);
     783   L = (x-y),(x3+y2),(x3-y4);
     784   iMult(L);
     785
     786///////////////////////////////////////////////////////////////////////////////
     787//check if I has a singularity only at zero, as needed in normalizationPrimes
     788
     789proc locAtZero (ideal I)
     790"USAGE:   locAtZero(I);  I = ideal
     791RETURN:  int, 1 if I has only one point which is located at zero, 0 otherwise
     792ASSUME:  I is given as a standard bases in the basering
     793NOTE:    only useful in affine rings, in local rings vdim does the check
     794EXAMPLE: example locAtZero; shows an example
     795"
     796{   
     797   int ii,jj, caz;                   //caz: conzentrated at zero
     798   int dbp = printlevel-voice+2;
     799   int nva = nvars(basering);
     800   int vdi = vdim(I);     
     801   if ( vdi < 0 )
     802   {
     803      if (dbp >=1)
     804      { "// non-isolated singularitiy";""; }         
     805      return(caz);
     806   }
     807
     808   //Now the ideal is 0-dim
     809   //First an easy test
     810   //If I is homogenous and not constant it is concentrated at 0
     811   if( homog(I)==1 && size(jet(I,0))==0)
     812   {
     813      caz=1;
     814      if (dbp >=1)
     815      { "// isolated singularity and homogeneous";""; }         
     816      return(caz);
     817   }
     818
     819   //Now the general case with I 0-dim. Choose an appropriate power pot,
     820   //and check each variable x whether x^pot is in I.
     821   int mi1 = mindeg1(lead(I));
     822   int pot = vdi;
     823   if ( (mi1+(mi1==1))^2 < vdi )
     824   {
     825      pot = (mi1+(mi1==1))^2;      //### alternativ: pot = vdi lassen
     826   }
     827
     828   while ( 1 )
     829   {
     830      caz = 1;
     831      for ( ii=1; ii<= nva; ii++ )
     832      {
     833        if ( NF(var(ii)^pot,I) != 0 )
     834        {
     835           caz = 0; break;
     836        }
     837      }
     838      if ( caz == 1 || pot >= vdi )
     839      {
     840        if (dbp >=1)
     841        {
     842          "// mindeg, exponent, vdim used in 'locAtZero':", mi1,pot,vdi; "";
     843        }         
     844        return(caz);
     845      }
     846      else
     847      {
     848        if ( pot^2 < vdi )
     849        { pot = pot^2; }
     850        else
     851        { pot = vdi; }
     852      }
     853   }
    602854}
     855example
     856{ "EXAMPLE:"; echo = 2;
     857   ring r = 0,(x,y,z),dp;
     858   poly f = z5+y4+x3+xyz;
     859   ideal i = jacob(f),f;
     860   i=std(i);
     861   locAtZero(i);
     862   i= std(i*ideal(x-1,y,z));
     863   locAtZero(i);
     864
    603865
    604866///////////////////////////////////////////////////////////////////////////////
    605 static proc normalizationPrimes(ideal i,ideal ihp,int delt, list #)
    606 "USAGE:   normalizationPrimes(i,ihp[,si]);  i equidimensional ideal, ihp map
    607          (partial normalization),delta partial delta-invariant,
    608           # ideal of singular locus
     867
     868//The next procedure normalizationPrimes computes the normalization of an
     869//irreducible or an equidimensional ideal i.
     870//- If i is irreducuble, then the returned list, say nor, has size 2
     871//with nor[1] the normalization ring and nor[2] the delta invariant.
     872//- If i is equidimensional, than the "splitting tools" can create a
     873//decomposition of i and nor can have more than 1 ring.
     874
     875static proc normalizationPrimes(ideal i,ideal ihp,int delt,intvec delti,list #)
     876"USAGE:   normalizationPrimes(i,ihp,delt[,si]);  i = equidimensional ideal,
     877         ihp = map (partial normalization), delt = partial delta-invariant,
     878         si = ideal s.t. V(si) contains singular locus (optional)
    609879RETURN:   a list of rings, say nor, and an integer, the delta-invariant
    610880          at the end of the list.
    611           each ring nor[i] contains two ideals
     881          each ring nor[j], j = 1..size(nor)-1, contains two ideals
    612882          with given names norid and normap such that
    613            - the direct sum of the rings nor[i]/norid is
    614              the normalization of basering/id;
     883           - the direct sum of the rings nor[j]/norid is
     884             the normalization of basering/i;
    615885           - normap gives the normalization map from basering/id
    616              to nor[i]/norid (for each i)
     886             to nor[j]/norid (for each j)
     887          nor[size(nor)] = dim_K(normalisation(P/i) / (P/i)) is the
     888          delta-invariant, where P is the basering.
    617889EXAMPLE: example normalizationPrimes; shows an example
    618890"
    619891{
    620 
     892   //Note: this procedure calls itself as long as the test for
     893   //normality, i.e if R==Hom(J,J), is negative.
     894
     895   int printlev = printlevel;   //store printlevel in order to reset it later
    621896   int y = printlevel-voice+2;  // y=printlevel (default: y=0)
    622 
    623897   if(y>=1)
    624898   {
    625899     "";
    626      "// START a normalization loop with the ideal";  "";
     900     "// START a normalization loop with the ideal";
    627901     i;  "";
     902     "// in the ring:";
    628903     basering;  "";
    629904     pause();
    630      newline;
     905     "";
    631906   }
    632907
    633908   def BAS=basering;
    634    list result,keepresult1,keepresult2;
     909   list result,keepresult1,keepresult2,JM,gnirlist;
    635910   ideal J,SB,MB;
    636    int depth,lauf,prdim;
     911   int depth,lauf,prdim,osaz;
    637912   int ti=timer;
    638 
     913   
     914   gnirlist = ringlist(BAS);
     915
     916//----------- the trivial case of a zero ideal as input, RETURN ------------
    639917   if(size(i)==0)
    640918   {
     
    643921          "// the ideal was the zero-ideal";
    644922      }
    645          execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),("
    646                       +ordstr(basering)+");");
     923     // execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),("
     924     //                 +ordstr(basering)+");");
     925         def newR7 = ring(gnirlist);
     926         setring newR7;
    647927         ideal norid=ideal(0);
    648928         ideal normap=fetch(BAS,ihp);
     
    650930         export normap;
    651931         result=newR7;
    652          result[size(result)+1]=delt;
     932         result[size(result)+1]=list(delt,delti);
    653933         setring BAS;
    654934         return(result);
    655935   }
    656936
     937//--------------- General NOTATION, compute SB of input -----------------
     938// SM is a list, the result of mstd(i)
     939// SM[1] = SB of input ideal i,
     940// SM[2] = (minimal) generators for i.
     941// We work with SM and will copy the attributes from i to SM[2]
     942// JM will be a list, either JM[1]=maxideal(1),JM[2]=maxideal(1)
     943// in case i has onlySingularAtZero, or JM = mstd(si) where si = #[1],
     944// or JM = mstd(J) where J is the ideal of the singular locus
     945// JM[2] must be (made) radical
     946
    657947   if(y>=1)
    658948   {
    659      "// SB-computation of the input ideal";
    660    }
    661    list SM=mstd(i);                //here the work starts
     949     "// SB-computation of the ideal";
     950   }
     951
     952   list SM = mstd(i);              //Now the work starts
    662953   int dimSM =  dim(SM[1]);        //dimension of variety to normalize
    663   // Case: Get an ideal containing a unit
     954   if(y>=1)
     955   {
     956      "// the dimension is:";  dimSM;
     957   }
     958//----------------- the general case, set attributes ----------------
     959   //Note: onlySingularAtZero is NOT preserved under the ring extension
     960   //basering --> Hom(J,J) (in contrast to isIsolatedSingularity),
     961   //therefore we reset it:
     962 
     963   attrib(i,"onlySingularAtZero",0);
     964
     965   if(attrib(i,"isPrim")==1)
     966   {
     967      attrib(SM[2],"isPrim",1);
     968   }
     969   else
     970   {
     971      attrib(SM[2],"isPrim",0);
     972   }
     973   if(attrib(i,"isIsolatedSingularity")==1)
     974   {
     975      attrib(SM[2],"isIsolatedSingularity",1);
     976   }
     977   else
     978   {
     979      attrib(SM[2],"isIsolatedSingularity",0);
     980   }
     981   if(attrib(i,"isCohenMacaulay")==1)
     982   {
     983      attrib(SM[2],"isCohenMacaulay",1);
     984   }
     985   else
     986   {
     987      attrib(SM[2],"isCohenMacaulay",0);
     988   }
     989   if(attrib(i,"isRegInCodim2")==1)
     990   {
     991      attrib(SM[2],"isRegInCodim2",1);
     992   }
     993   else
     994   {
     995      attrib(SM[2],"isRegInCodim2",0);
     996   }
     997   if(attrib(i,"isEquidimensional")==1)
     998   {
     999      attrib(SM[2],"isEquidimensional",1);
     1000   }
     1001   else
     1002   {
     1003      attrib(SM[2],"isEquidimensional",0);
     1004   }
     1005   if(attrib(i,"isCompleteIntersection")==1)
     1006   {
     1007     attrib(SM[2],"isCompleteIntersection",1);
     1008   }
     1009   else
     1010   {
     1011      attrib(SM[2],"isCompleteIntersection",0);
     1012   }
     1013   if(attrib(i,"isHypersurface")==1)
     1014   {
     1015     attrib(SM[2],"isHypersurface",1);
     1016   }
     1017   else
     1018   {
     1019      attrib(SM[2],"isHypersurface",0);
     1020   }
     1021
     1022   if(attrib(i,"onlySingularAtZero")==1)
     1023   {
     1024      attrib(SM[2],"onlySingularAtZero",1);
     1025   }
     1026   else
     1027   {
     1028      attrib(SM[2],"onlySingularAtZero",0);
     1029   }
     1030
     1031   //------- an easy and cheap test for onlySingularAtZero ---------
     1032   if( (attrib(SM[2],"isIsolatedSingularity")==1) && (homog(SM[2])==1) )
     1033   {
     1034      attrib(SM[2],"onlySingularAtZero",1);
     1035   }
     1036
     1037//-------------------- Trivial cases, in each case RETURN ------------------ 
     1038// input ideal is the ideal of a partial normalization
     1039
     1040   // ------------ Trivial case: input ideal contains a unit ---------------
    6641041   if( dimSM == -1)
    6651042   {  "";
     
    6781055         export normap;
    6791056         result=newR6;
    680          result[size(result)+1]=delt;
     1057         result[size(result)+1]=list(delt,delti);
    6811058         setring BAS;
    6821059         return(result);
    6831060   }
    684 
    685    if(y>=1)
    686    {
    687       "//   the dimension is:"; "";
    688       dimSM;"";
    689    }
    690    if(size(#)>0)
    691    {
    692       if(attrib(i,"onlySingularAtZero"))
    693       {
    694          list JM=maxideal(1),maxideal(1);
    695          attrib(JM[1],"isSB",1);
    696          attrib(JM[2],"isRad",1);
    697       }
    698       else
    699       {
    700          ideal te=#[1],SM[2];
    701          list JM=mstd(te);
    702          kill te;
    703          if( typeof(attrib(#[1],"isRad"))!="int" )
    704          {
    705             attrib(JM[2],"isRad",0);
    706          }
    707       }
    708    }
    709 
    710    if(attrib(i,"isPrim")==1)
    711    {
    712       attrib(SM[2],"isPrim",1);
    713    }
    714    else
    715    {
    716       attrib(SM[2],"isPrim",0);
    717    }
    718    if(attrib(i,"isIsolatedSingularity")==1)
    719    {
    720       attrib(SM[2],"isIsolatedSingularity",1);
    721    }
    722    else
    723    {
    724       attrib(SM[2],"isIsolatedSingularity",0);
    725    }
    726    if(attrib(i,"isCohenMacaulay")==1)
    727    {
    728       attrib(SM[2],"isCohenMacaulay",1);
    729    }
    730    else
    731    {
    732       attrib(SM[2],"isCohenMacaulay",0);
    733    }
    734    if(attrib(i,"isRegInCodim2")==1)
    735    {
    736       attrib(SM[2],"isRegInCodim2",1);
    737    }
    738    else
    739    {
    740       attrib(SM[2],"isRegInCodim2",0);
    741    }
    742    if(attrib(i,"isEquidimensional")==1)
    743    {
    744       attrib(SM[2],"isEquidimensional",1);
    745    }
    746    else
    747    {
    748       attrib(SM[2],"isEquidimensional",0);
    749    }
    750    if(attrib(i,"isCompleteIntersection")==1)
    751    {
    752       attrib(SM[2],"isCompleteIntersection",1);
    753    }
    754    else
    755    {
    756       attrib(SM[2],"isCompleteIntersection",0);
    757    }
    758    if(attrib(i,"onlySingularAtZero")==1)
    759    {
    760       attrib(SM[2],"onlySingularAtZero",1);
    761    }
    762    else
    763    {
    764       attrib(SM[2],"onlySingularAtZero",0);
    765    }
    766    if((attrib(SM[2],"isIsolatedSingularity")==1)&&(homog(SM[2])==1))
    767    {
    768       attrib(SM[2],"onlySingularAtZero",1);
    769    }
    770 
    771    //the smooth case
    772    if(size(#)>0)
    773    {
    774       if(dim(JM[1])==-1)
    775       {
    776          if(y>=1)
    777          {
    778             "// the ideal was smooth";
    779          }
    780          MB=SM[2];
    781          intvec rw;;
    782          list LL=substpart(MB,ihp,0,rw);
    783          def newR6=LL[1];
    784          setring newR6;
    785          ideal norid=endid;
    786          ideal normap=endphi;
    787          kill endid,endphi;
    788          export norid;
    789          export normap;
    790          result=newR6;
    791          result[size(result)+1]=delt;
    792          setring BAS;
    793          return(result);
    794      }
    795    }
    796 
    797    //the zero-dimensional case
    798    if((dim(SM[1])==0)&&(homog(SM[2])==1))
     1061   
     1062   // --- Trivial case: input ideal is zero-dimensional and homog ---
     1063   if( (dim(SM[1])==0) && (homog(SM[2])==1) )
    7991064   {
    8001065      if(y>=1)
     
    8031068      }
    8041069      MB=maxideal(1);
    805       intvec rw;
    806       list LL=substpart(MB,ihp,0,rw);
     1070      intvec rw; 
     1071      list LL=substpart(MB,ihp,0,rw);     
    8071072      def newR5=LL[1];
    8081073      setring newR5;
     
    8131078      export normap;
    8141079      result=newR5;
    815       result[size(result)+1]=delt;
     1080      result[size(result)+1]=list(delt,delti);
    8161081      setring BAS;
    8171082      return(result);
    8181083   }
    8191084
    820    //the one-dimensional case
    821    //in this case it is a line because
    822    //it is irreducible and homogeneous
    823    if((dim(SM[1])==1)&&(attrib(SM[2],"isPrim")==1)
    824         &&(homog(SM[2])==1))
     1085   // --- Trivial case: input ideal defines a line ---
     1086   //the one-dimensional, homogeneous case and degree 1 case
     1087   if( (dim(SM[1])==1) && (maxdeg1(SM[2])==1) && (homog(SM[2])==1) )
    8251088   {
    8261089      if(y>=1)
     
    8391102      export normap;
    8401103      result=newR4;
    841       result[size(result)+1]=delt;
     1104      result[size(result)+1]=list(delt,delti);
    8421105      setring BAS;
    8431106      return(result);
    8441107   }
    8451108
     1109//---------------------- The non-trivial cases start ------------------- 
    8461110   //the higher dimensional case
    847    //we test first of all CohenMacaulay and
    848    //complete intersection
    849    if(((size(SM[2])+dim(SM[1]))==nvars(basering))&&(homog(SM[2])==1))
    850    {
    851       //test for complete intersection
     1111   //we test first hypersurface, CohenMacaulay and complete intersection
     1112
     1113   if( ((size(SM[2])+dim(SM[1])) == nvars(basering)) )
     1114   {
     1115      //the test for complete intersection
    8521116      attrib(SM[2],"isCohenMacaulay",1);
    8531117      attrib(SM[2],"isCompleteIntersection",1);
     
    8581122      }
    8591123   }
    860    if((attrib(SM[2],"onlySingularAtZero")==0)&&(size(i)==1))
    861    {
    862       int tau=vdim(std(i+jacob(i)));
    863       if(tau>=0)
    864       {
    865         execute("ring BASL="+charstr(BAS)+",("+varstr(BAS)+"),ds;");
    866         ideal i=imap(BAS,i);
    867         int tauloc=vdim(std(i+jacob(i)));
    868         setring BAS;
    869         attrib(SM[2],"onlySingularAtZero",(tau==tauloc));
    870         kill BASL;
    871       }
    872    }
    873    //compute the singular locus
    874    if((attrib(SM[2],"onlySingularAtZero")==0)&&(size(#)==0))
    875    {
    876       J=minor(jacob(SM[2]),nvars(basering)-dim(SM[1]));
    877       if(y >=1 )
    878       {
    879          "// SB of singular locus will be computed";
    880       }
    881       ideal sin=J,SM[1];
    882       list JM=mstd(sin);
     1124   if( size(SM[2]) == 1 )
     1125   {
     1126      attrib(SM[2],"isHypersurface",1);
     1127      if(y>=1)
     1128      {
     1129         "// the ideal is a hypersurface";
     1130      }
     1131   }
     1132
     1133   //------------------- compute the singular locus -------------------
     1134   // Computation if singular locus is critical
     1135   // Notation: J ideal of singular locus or (if given) containing it
     1136   // JM = mstd(J) or maxideal(1),maxideal(1)
     1137   // JM[1] SB of singular locus, JM[2] minbasis, dimJ = dim(JM[1])
     1138   // SM[1] SB of the input ideal i, SM[2] minbasis
     1139   // Computation if singular locus is critical, because it determines the
     1140   // size of the ring Hom_R(J,J). We only need a test ideal contained in J.
     1141
     1142   //----------------------- onlySingularAtZero -------------------------
     1143   if( attrib(SM[2],"onlySingularAtZero") )
     1144   {
     1145       JM = maxideal(1),maxideal(1);
     1146       attrib(JM[1],"isSB",1);
     1147       attrib(JM[2],"isRadical",1);
     1148       if( dim(SM[1]) >=2 )
     1149       {
     1150         attrib(SM[2],"isRegInCodim2",1);
     1151       }
     1152   }
     1153
     1154   //-------------------- not onlySingularAtZero -------------------------
     1155   if( attrib(SM[2],"onlySingularAtZero") == 0 )
     1156   {
     1157      //--- the case where an ideal #[1] is given:
     1158      if( size(#)>0 )                 
     1159      {
     1160         J = #[1],SM[2];
     1161         JM = mstd(J);
     1162         if( typeof(attrib(#[1],"isRadical"))!="int" )
     1163         {
     1164            attrib(JM[2],"isRadical",0);
     1165         }
     1166      }
     1167
     1168      //--- the case where an ideal #[1] is not given:
     1169      if( (size(#)==0) )
     1170      {
     1171         if(y >=1 )
     1172         {
     1173            "// singular locus will be computed";
     1174         }
     1175
     1176         J = SM[1],minor(jacob(SM[2]),nvars(basering)-dim(SM[1]),SM[1]);
     1177         if( y >=1 )
     1178         {
     1179            "// SB of singular locus will be computed";
     1180         }
     1181         JM = mstd(J);
     1182      }
     1183
     1184      int dimJ = dim(JM[1]);
    8831185      attrib(JM[1],"isSB",1);
    884 
    885       //JM[1] SB of singular locus, JM[2]=minbasis of singular locus
    886       //SM[1] SB of the input ideal, SM[2] minbasis
    887       if(y>=1)
    888       {
    889          "//   the dimension of the singular locus is:";"";
    890          dim(JM[1]); "";
    891       }
    892 
    893       if(dim(JM[1])==-1)
     1186      if( y>=1 )
     1187      { 
     1188         "// the dimension of the singular locus is";  dimJ ; "";
     1189      }
     1190         
     1191      if(dim(JM[1]) <= dim(SM[1])-2)
     1192      {
     1193         attrib(SM[2],"isRegInCodim2",1);
     1194      }
     1195
     1196      //------------------ the smooth case, RETURN -------------------
     1197      if( dimJ == -1 )
    8941198      {
    8951199         if(y>=1)
     
    9081212         export normap;
    9091213         result=newR3;
    910          result[size(result)+1]=delt;
     1214         result[size(result)+1]=list(delt,delti);
    9111215         setring BAS;
    9121216         return(result);
    9131217      }
    914       if(dim(JM[1])==0)
    915       {
    916          attrib(SM[2],"isIsolatedSingularity",1);
    917          if(homog(SM[2])){attrib(SM[2],"onlySingularAtZero",1);}
    918       }
    919       if(dim(JM[1])<=dim(SM[1])-2)
    920       {
    921          attrib(SM[2],"isRegInCodim2",1);
    922       }
    923    }
    924    else
    925    {
    926      if(size(#)==0)
    927      {
    928         list JM=maxideal(1),maxideal(1);
    929 
    930         attrib(JM[1],"isSB",1);
    931         if(dim(SM[1])>=2){attrib(SM[2],"isRegInCodim2",1);}
    932      }
    933    }
    934    if((attrib(SM[2],"isRegInCodim2")==1)&&(attrib(SM[2],"isCohenMacaulay")==1))
     1218
     1219      //------- extra check for onlySingularAtZero, relatively cheap ----------
     1220      //it uses the procedure 'locAtZero' from for testing
     1221      //if an ideal is concentrated at 0
     1222       if(y>=1)
     1223       {
     1224         "// extra test for onlySingularAtZero:";
     1225       }
     1226       if ( locAtZero(JM[1]) ) 
     1227       {
     1228           attrib(SM[2],"onlySingularAtZero",1);
     1229           JM = maxideal(1),maxideal(1);
     1230           attrib(JM[1],"isSB",1);
     1231           attrib(JM[2],"isRadical",1);
     1232       }
     1233       else
     1234       {
     1235              attrib(SM[2],"onlySingularAtZero",0);
     1236       }
     1237   }
     1238 
     1239  //displaying the attributes:
     1240   if(y>=2)
     1241   {
     1242      "// the attributes of the ideal are:"; 
     1243      "// isCohenMacaulay:", attrib(SM[2],"isCohenMacaulay");
     1244      "// isCompleteIntersection:", attrib(SM[2],"isCompleteIntersection");
     1245      "// isHypersurface:", attrib(SM[2],"isHypersurface");
     1246      "// isEquidimensional:", attrib(SM[2],"isEquidimensional");
     1247      "// isPrim:", attrib(SM[2],"isPrim");
     1248      "// isRegInCodim2:", attrib(SM[2],"isRegInCodim2");
     1249      "// isIsolatedSingularity:", attrib(SM[2],"isIsolatedSingularity");
     1250      "// onlySingularAtZero:", attrib(SM[2],"onlySingularAtZero");
     1251      "// isRad:", attrib(SM[2],"isRad");"";
     1252   }
     1253
     1254   //------------- case: CohenMacaulay in codim 2, RETURN ---------------
     1255   if( (attrib(SM[2],"isRegInCodim2")==1) &&   
     1256       (attrib(SM[2],"isCohenMacaulay")==1) )
    9351257   {
    9361258      if(y>=1)
    9371259      {
    938             "// the ideal was CohenMacaulay and regular in codimension 2";
     1260         "// the ideal was CohenMacaulay and regular in codim 2, hence normal";
    9391261      }
    9401262      MB=SM[2];
     
    9491271      export normap;
    9501272      result=newR6;
    951       result[size(result)+1]=delt;
     1273      result[size(result)+1]=list(delt,delti);
    9521274      setring BAS;
    9531275      return(result);
    9541276   }
    9551277
    956    //if it is an isolated singularity only at 0 things are easier
    957    //JM ideal of singular locus, SM ideal of variety
    958    if(attrib(SM[2],"onlySingularAtZero"))
    959    {
     1278//---------- case: isolated singularity only at 0, RETURN ------------
     1279   // In this case things are easier, we can use the maximal ideal as radical
     1280   // of the singular locus;
     1281   // JM mstd of ideal of singular locus, SM mstd of input ideal
     1282
     1283   if( attrib(SM[2],"onlySingularAtZero") )
     1284   {
     1285   //------ check variables for being a non zero-divizor ------
     1286   // SL = ideal of vars not contained in ideal SM[1]:
     1287
    9601288      attrib(SM[2],"isIsolatedSingularity",1);
    961       ideal SL=simplify(reduce(maxideal(1),SM[1]),2);
    962       //vars not contained in ideal
    963       ideal Ann=quotient(SM[2],SL[1]);
    964       ideal qAnn=simplify(reduce(Ann,SM[1]),2);
    965       //qAnn=0 ==> the first var(=SL[1]) not contained in SM is a nzd of R/SM
    966       if(size(qAnn)==0)
     1289      ideal SL = simplify(reduce(maxideal(1),SM[1]),2);
     1290      ideal Ann = quotient(SM[2],SL[1]);
     1291      ideal qAnn = simplify(reduce(Ann,SM[1]),2);
     1292      //NOTE: qAnn=0 iff first var (=SL[1]) not in SM is a nzd of R/SM
     1293
     1294   //------------- We found a non-zerodivisor of R/SM -----------------------
     1295   // here the enlarging of the ring via Hom_R(J,J) starts
     1296
     1297      if( size(qAnn)==0 )
    9671298      {
    9681299         if(y>=1)
    9691300         {
    9701301            "";
    971             "//   the ideal rad(J):";
     1302            "// the ideal rad(J):"; maxideal(1);
    9721303            "";
    973             maxideal(1);
    974             newline;
    9751304         }
    976          //again test for normality
    977          //Hom(I,R)=R
     1305
     1306      // ------------- test for normality, compute Hom_R(J,J) -------------
     1307      // Note:
     1308      // HomJJ (ideal SBid, ideal id, ideal J, poly p) with
     1309      //        SBid = SB of id, J = radical ideal of basering  P with:
     1310      //        nonNormal(R) is in V(J), J contains the nonzero divisor p
     1311      //        of R = P/id (J = test ideal)
     1312      // returns a list l of three objects
     1313      // l[1] : a polynomial ring, containing two ideals, 'endid' and 'endphi'
     1314      //        s.t. l[1]/endid = Hom_R(J,J) and endphi= map R -> Hom_R(J,J)
     1315      // l[2] : an integer which is 1 if phi is an isomorphism, 0 if not
     1316      // l[3] : an integer, = dim_K(Hom_R(J,J)/R) if finite, -1 otherwise
     1317
    9781318         list RR;
    979          RR=SM[1],SM[2],maxideal(1),SL[1];
    980 
    981          RR=HomJJ(RR,y);
    982          if(RR[2]==0)
     1319         RR = SM[1],SM[2],maxideal(1),SL[1];
     1320         RR = HomJJ(RR,y);
     1321         // --------------------- non-normal case ------------------
     1322         //RR[2]==0 means that the test for normality is negative
     1323         if( RR[2]==0 )
    9831324         {
    9841325            def newR=RR[1];
    9851326            setring newR;
    9861327            map psi=BAS,endphi;
    987             list tluser=normalizationPrimes(endid,psi(ihp),delt+RR[3],an);
    988             setring BAS;
    989             return(tluser);
     1328            list JM = psi(JM); //###
     1329            ideal J = JM[2];
     1330            if ( delt>=0 && RR[3]>=0 )
     1331            {
     1332               delt = delt+RR[3];
     1333            }
     1334            else
     1335            { delt = -1; }
     1336            delti[size(delti)]=delt;
     1337
     1338            // ---------- recursive call of normalizationPrimes -----------
     1339        //normalizationPrimes(ideal i,ideal ihp,int delt,intvec delti,list #)
     1340        //ihp = (partial) normalisation map from basering
     1341        //#[1] ideal s.t. V(#[1]) contains singular locus of i (test ideal)
     1342
     1343            if ( y>=1 )
     1344            {
     1345            "// case: onlySingularAtZero, non-zerodivisor found";
     1346            "// contribution of delta in ringextension R -> Hom_R(J,J):"; delt;
     1347            }
     1348
     1349            //intvec atr=getAttrib(endid);
     1350            //"//### case: isolated singularity only at 0, recursive";
     1351            //"size endid:", size(endid), size(string(endid));
     1352            //"interred:";
     1353            //endid = interred(endid);
     1354            //endid = setAttrib(endid,atr);
     1355            //"size endid:", size(endid), size(string(endid));
     1356
     1357           printlevel=printlevel+1;
     1358           list tluser =
     1359                normalizationPrimes(endid,psi(ihp),delt,delti);
     1360           //list tluser =
     1361           //     normalizationPrimes(endid,psi(ihp),delt,delti,J);
     1362           //#### ??? improvement: give also the old ideal of sing locus???
     1363
     1364           printlevel = printlev;             //reset printlevel
     1365           setring BAS;   
     1366           return(tluser);         
    9901367         }
     1368
     1369         // ------------------ the normal case, RETURN -----------------
     1370         // Now RR[2] must be 1, hence the test for normality was positive
    9911371         MB=SM[2];
    992          execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),("
    993                       +ordstr(basering)+");");
     1372         //execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),("
     1373         //             +ordstr(basering)+");");
     1374         def newR7 = ring(gnirlist);
     1375         setring newR7;
    9941376         ideal norid=fetch(BAS,MB);
    9951377         ideal normap=fetch(BAS,ihp);
    996          delt=delt+RR[3];
     1378         if ( delt>=0 && RR[3]>=0 )
     1379         {
     1380               delt = delt+RR[3];
     1381         }
     1382         else
     1383         { delt = -1; }
     1384         delti[size(delti)]=delt;
     1385
     1386         intvec atr = getAttrib(norid);
     1387
     1388         //"//### case: isolated singularity only at 0, final";
     1389         //"size norid:", size(norid), size(string(norid));
     1390         //"interred:";
     1391         //norid = interred(norid);
     1392         //norid = setAttrib(norid,atr);
     1393         //"size norid:", size(norid), size(string(norid));
     1394
    9971395         export norid;
    9981396         export normap;
    9991397         result=newR7;
    1000          result[size(result)+1]=delt;
     1398         result[size(result)+1]=list(delt,delti);
    10011399         setring BAS;
    10021400         return(result);
    1003 
    1004        }
    1005       //Now the case where qAnn!=0, i.e.SL[1] is a zero divisor of R/SM
    1006       //and we have found a splitting: id and id1
    1007       //id=Ann defines components of R/SM in the complement of V(SL[1])
    1008       //id1 defines components of R/SM in the complement of V(id)
    1009        else
     1401      }
     1402
     1403   //------ zerodivisor of R/SM was found, gives a splitting ------------
     1404   //Now the case where qAnn!=0, i.e. SL[1] is a zero divisor of R/SM
     1405   //and we have found a splitting: id and id1
     1406   //id = Ann defines components of R/SM in the complement of V(SL[1])
     1407   //id1 defines components of R/SM in the complement of V(id)
     1408
     1409      else
    10101410       {
    1011           ideal id=Ann;
     1411          ideal id = Ann;
    10121412          attrib(id,"isCohenMacaulay",0);
    10131413          attrib(id,"isPrim",0);
    10141414          attrib(id,"isIsolatedSingularity",1);
    10151415          attrib(id,"isRegInCodim2",0);
     1416          attrib(id,"isHypersurface",0);
    10161417          attrib(id,"isCompleteIntersection",0);
    10171418          attrib(id,"isEquidimensional",0);
    10181419          attrib(id,"onlySingularAtZero",1);
    10191420
    1020           ideal id1=quotient(SM[2],Ann);
    1021           //ideal id=SL[1],SM[2];
     1421          ideal id1 = quotient(SM[2],Ann);
    10221422          attrib(id1,"isCohenMacaulay",0);
    10231423          attrib(id1,"isPrim",0);
    10241424          attrib(id1,"isIsolatedSingularity",1);
    10251425          attrib(id1,"isRegInCodim2",0);
     1426          attrib(id1,"isHypersurface",0);
    10261427          attrib(id1,"isCompleteIntersection",0);
    10271428          attrib(id1,"isEquidimensional",0);
    10281429          attrib(id1,"onlySingularAtZero",1);
    10291430
    1030           ideal t1=id,id1;
    1031           int mul=vdim(std(t1));
    1032           kill t1;
    1033 
    1034           keepresult1=normalizationPrimes(id,ihp,0);
    1035 
    1036           keepresult2=normalizationPrimes(id1,ihp,0);
    1037 
    1038           delt=delt+mul+keepresult1[size(keepresult1)]
    1039                          +keepresult1[size(keepresult1)];
    1040 
     1431          // ---------- recursive call of normalizationPrimes -----------
     1432          if ( y>=1 )
     1433          {
     1434            "// case: onlySingularAtZero, zerodivisor found, splitting:";
     1435            "// total delta before splitting:", delt;
     1436            "// splitting in two components:";
     1437          }
     1438
     1439          printlevel = printlevel+1;  //to see comments in normalizationPrimes
     1440          keepresult1 = normalizationPrimes(id,ihp,0,0);   //1st split factor
     1441          keepresult2 = normalizationPrimes(id1,ihp,0,0);  //2nd split factor
     1442          printlevel = printlev;                           //reset printlevel
     1443
     1444          int delt1 = keepresult1[size(keepresult1)][1];
     1445          int delt2 = keepresult2[size(keepresult2)][1];
     1446          intvec delti1 = keepresult1[size(keepresult1)][2];
     1447          intvec delti2 = keepresult2[size(keepresult2)][2];
     1448
     1449          if( delt>=0 && delt1>=0 && delt2>=0 ) 
     1450          {  ideal idid1=id,id1;
     1451             int mul = vdim(std(idid1));
     1452             if ( mul>=0 )
     1453             {
     1454               delt = delt+mul+delt1+delt2;
     1455             }
     1456             else
     1457             {
     1458               delt = -1;
     1459             }           
     1460          }
     1461         if ( y>=1 )
     1462         {
     1463           "// delta of first component:", delt1;
     1464           "// delta of second componenet:", delt2;
     1465           "// intersection multiplicity of both components:", mul;
     1466           "// total delta after splitting:", delt;
     1467         }
     1468
     1469          else
     1470          {
     1471            delt = -1;
     1472          }
    10411473          for(lauf=1;lauf<=size(keepresult2)-1;lauf++)
    10421474          {
    10431475             keepresult1=insert(keepresult1,keepresult2[lauf]);
    10441476          }
    1045           keepresult1[size(keepresult1)]=delt;
     1477          keepresult1[size(keepresult1)]=list(delt,delti);
     1478
    10461479          return(keepresult1);
    10471480       }
    10481481   }
    1049 
    1050    //test for non-normality
    1051    //Hom(I,I)<>R
     1482   // Case "onlySingularAtZero" has finished and returned result
     1483
     1484//-------------- General case, not onlySingularAtZero, RETURN ---------------
     1485   //test for non-normality, i.e. if Hom(I,I)<>R
    10521486   //we can use Hom(I,I) to continue
    1053    ideal SL=simplify(reduce(JM[2],SM[1]),2);
    1054    ideal Ann=quotient(SM[2],SL[1]);
    1055    ideal qAnn=simplify(reduce(Ann,SM[1]),2);
    1056 
    1057    if(size(qAnn)==0)
     1487
     1488   //------ check variables for being a non zero-divizor ------
     1489   // SL = ideal of vars not contained in ideal SM[1]:
     1490
     1491   ideal SL = simplify(reduce(JM[2],SM[1]),2);
     1492   ideal Ann = quotient(SM[2],SL[1]);
     1493   ideal qAnn = simplify(reduce(Ann,SM[1]),2);
     1494   //NOTE: qAnn=0 <==> first var (=SL[1]) not contained in SM is a nzd of R/SM
     1495
     1496   //------------- We found a non-zerodivisor of R/SM -----------------------
     1497   //SM = mstd of ideal of variety, JM = mstd of ideal of singular locus
     1498
     1499   if( size(qAnn)==0 )
    10581500   {
    10591501      list RR;
    10601502      list RS;
    1061       //now we have to compute the radical
     1503      // ----------------- Computation of the radical -----------------
    10621504      if(y>=1)
    10631505      {
    10641506         "// radical computation of singular locus";
    10651507      }
    1066       J=radical(JM[2]);   //the singular locus
    1067       JM=mstd(J);
    1068 
    1069       if((vdim(JM[1])==1)&&(size(reduce(J,std(maxideal(1))))==0))
    1070       {
    1071          attrib(SM[2],"onlySingularAtZero",1);
    1072       }
     1508      J = radical(JM[2]);   //the radical of singular locus
     1509      JM = mstd(J);
     1510
    10731511      if(y>=1)
    10741512      {
    1075         "//   radical is equal to:";"";
    1076         J;
     1513        "// radical is equal to:";"";  JM[2];
    10771514        "";
    10781515      }
    1079       if(deg(SL[1])>deg(J[1]))
     1516      // ------------ choose non-zerodivisor of smaller degree ----------
     1517      //### evtl. fuer SL[1] anderen Nichtnullteiler aus J waehlen ?
     1518      if( deg(SL[1]) > deg(J[1]) )
    10801519      {
    10811520         Ann=quotient(SM[2],J[1]);
    10821521         qAnn=simplify(reduce(Ann,SM[1]),2);
    1083          if(size(qAnn)==0){SL[1]=J[1];}
    1084       }
    1085 
    1086       //evtl. fuer SL[1] anderen Nichtnullteiler aus J waehlen
     1522         if(size(qAnn)==0)
     1523         {
     1524           SL[1]=J[1];
     1525         }
     1526      }
     1527
     1528      // --------------- computation of Hom(rad(J),rad(J)) --------------
    10871529      RR=SM[1],SM[2],JM[2],SL[1];
    10881530
    1089       //   evtl eine geeignete Potenz von JM?
    10901531     if(y>=1)
    10911532     {
     
    10931534     }
    10941535
    1095      RS=HomJJ(RR,y);
    1096 
    1097       if(RS[2]==1)
    1098       {
     1536     RS=HomJJ(RR,y);               //most important subprocedure
     1537         
     1538     // ------------------ the normal case, RETURN -----------------
     1539     // RS[2]==1 means that the test for normality was positive
     1540     if(RS[2]==1)
     1541     {
    10991542         def lastR=RS[1];
    11001543         setring lastR;
     
    11031546         ideal normap=psi1(ihp);
    11041547         kill endid,endphi;
     1548
     1549        intvec atr=getAttrib(norid);
     1550
     1551        //"//### general case: not isolated singularity only at 0, final";
     1552        //"size norid:", size(norid), size(string(norid));
     1553        //"interred:";
     1554        //norid = interred(norid);
     1555        //norid = setAttrib(norid,atr);
     1556        //"size norid:", size(norid), size(string(norid));
     1557
    11051558         export norid;
    11061559         export normap;
    11071560         result=lastR;
    1108          result[size(result)+1]=delt+RS[3];
     1561         if ( y>=1 )
     1562         {
     1563            "// case: not onlySingularAtZero, last ring Hom_R(J,J) computed";
     1564            "// delta before last ring:", delt;
     1565         }
     1566
     1567         if ( delt>=0 && RS[3]>=0 )
     1568         {
     1569            delt = delt+RS[3];
     1570         }
     1571         else
     1572         { delt = -1; }
     1573
     1574        // delti = delti,delt;
     1575         delti[size(delti)]=delt;
     1576
     1577         if ( y>=1 )
     1578         {
     1579           "// delta of last ring:", delt;
     1580         }
     1581
     1582         result[size(result)+1]=list(delt,delti);
    11091583         setring BAS;
    11101584         return(result);
    1111       }
    1112       int n=nvars(basering);
    1113       ideal MJ=JM[2];
     1585     }
     1586
     1587    // ----- the non-normal case, recursive call of normalizationPrimes -------
     1588    // RS=HomJJ(RR,y) was computed above, RS[1] contains endid and endphi
     1589    // RS[1] = new ring Hom_R(J,J), RS[2]= 0 or 1, RS[2]=contribution to delta
     1590    // now RS[2]must be 0, i.e. the test for normality was negative
     1591
     1592      int n = nvars(basering);
     1593      ideal MJ = JM[2];
    11141594
    11151595      def newR=RS[1];
    11161596      setring newR;
    1117 
    11181597      map psi=BAS,endphi;
     1598      if ( y>=1 )
     1599      {
     1600        "// case: not onlySingularAtZero, compute new ring = Hom_R(J,J)";
     1601        "// delta of old ring:", delt;
     1602      }
     1603      if ( delt>=0 && RS[3]>=0 )
     1604      {
     1605         delt = delt+RS[3];
     1606      }
     1607      else
     1608      { delt = -1; }
     1609      if ( y>=1 )
     1610      {
     1611        "// delta of new ring:", delt;
     1612      }
     1613
     1614      delti[size(delti)]=delt;
     1615      intvec atr=getAttrib(endid);
     1616
     1617      //"//### general case: not isolated singularity only at 0, recursive";
     1618      //"size endid:", size(endid), size(string(endid));
     1619      //"interred:";
     1620      //endid = interred(endid);
     1621      //endid = setAttrib(endid,atr);
     1622      //"size endid:", size(endid), size(string(endid));
     1623
     1624      printlevel = printlevel+1;
    11191625      list tluser=
    1120              normalizationPrimes(endid,psi(ihp),delt+RS[3],psi(MJ));
     1626          normalizationPrimes(endid,psi(ihp),delt,delti,psi(MJ));
     1627      printlevel = printlev;                //reset printlevel
    11211628      setring BAS;
    11221629      return(tluser);
    11231630   }
    1124     // A component with singular locus the whole component found
     1631
     1632   //---- A whole singular component was found, RETURN -----
    11251633   if( Ann == 1)
    11261634   {
     
    11411649         export normap;
    11421650         result=newR6;
    1143          result[size(result)+1]=delt;
     1651         result[size(result)+1]=lst(delt,delti);
    11441652         setring BAS;
    11451653         return(result);
    11461654   }
     1655
     1656   //------ zerodivisor of R/SM was found, gives a splitting ------------
     1657   //Now the case where qAnn!=0, i.e. SL[1] is a zero divisor of R/SM
     1658   //and we have found a splitting: new1 and new2
     1659   //id = Ann defines components of R/SM in the complement of V(SL[1])
     1660   //id1 defines components of R/SM in the complement of V(id)
     1661
    11471662   else
    11481663   {
    1149       int equi=attrib(SM[2],"isEquidimensional");
    1150       int oSAZ=attrib(SM[2],"onlySingularAtZero");
    1151       int isIs=attrib(SM[2],"isIsolatedSingularity");
    1152 
    1153       ideal new1=Ann;
    1154       ideal new2=quotient(SM[2],Ann);
     1664      if(y>=1)
     1665      {
     1666         "// zero-divisor found";
     1667      }
     1668      int equi = attrib(SM[2],"isEquidimensional");
     1669      int oSAZ = attrib(SM[2],"onlySingularAtZero");
     1670      int isIs = attrib(SM[2],"isIsolatedSingularity");
     1671
     1672      ideal new1 = Ann;
     1673      ideal new2 = quotient(SM[2],Ann);
    11551674      //ideal new2=SL[1],SM[2];
    11561675
    1157       int mul;
    1158       if(equi&&isIs)
    1159       {
    1160           ideal t2=new1,new2;
    1161           mul=vdim(std(t2));
    1162       }
    1163       execute("ring newR1="+charstr(basering)+",("+varstr(basering)+"),("
    1164                       +ordstr(basering)+");");
    1165       if(y>=1)
    1166       {
    1167          "// zero-divisor found";
    1168       }
    1169       ideal vid=fetch(BAS,new1);
    1170       ideal ihp=fetch(BAS,ihp);
     1676      //execute("ring newR1="+charstr(basering)+",("+varstr(basering)+"),("
     1677      //                +ordstr(basering)+");");
     1678      def newR1 = ring(gnirlist);
     1679      setring newR1;
     1680
     1681      ideal vid = fetch(BAS,new1);
     1682      ideal ihp = fetch(BAS,ihp);
    11711683      attrib(vid,"isCohenMacaulay",0);
    11721684      attrib(vid,"isPrim",0);
     
    11751687      attrib(vid,"onlySingularAtZero",oSAZ);
    11761688      attrib(vid,"isEquidimensional",equi);
     1689      attrib(vid,"isHypersurface",0);
    11771690      attrib(vid,"isCompleteIntersection",0);
    11781691
    1179       keepresult1=normalizationPrimes(vid,ihp,0);
    1180       int delta1=keepresult1[size(keepresult1)];
     1692      // ---------- recursive call of normalizationPrimes -----------
     1693      if ( y>=1 )
     1694      {
     1695        "// total delta before splitting:", delt;
     1696        "// splitting in two components:";
     1697      }
     1698      printlevel = printlevel+1;
     1699      keepresult1 =
     1700                  normalizationPrimes(vid,ihp,0,0);  //1st split factor
     1701
     1702      list delta1 = keepresult1[size(keepresult1)];
     1703
    11811704      setring BAS;
    1182 
    1183       execute("ring newR2="+charstr(basering)+",("+varstr(basering)+"),("
    1184                       +ordstr(basering)+");");
    1185 
    1186       ideal vid=fetch(BAS,new2);
    1187       ideal ihp=fetch(BAS,ihp);
     1705      //execute("ring newR2="+charstr(basering)+",("+varstr(basering)+"),("
     1706      //                +ordstr(basering)+");");
     1707      def newR2 = ring(gnirlist);
     1708      setring newR2;
     1709
     1710      ideal vid = fetch(BAS,new2);
     1711      ideal ihp = fetch(BAS,ihp);
    11881712      attrib(vid,"isCohenMacaulay",0);
    11891713      attrib(vid,"isPrim",0);
     
    11911715      attrib(vid,"isRegInCodim2",0);
    11921716      attrib(vid,"isEquidimensional",equi);
     1717      attrib(vid,"isHypersurface",0);
    11931718      attrib(vid,"isCompleteIntersection",0);
    11941719      attrib(vid,"onlySingularAtZero",oSAZ);
    11951720
    1196       keepresult2=normalizationPrimes(vid,ihp,0);
    1197       int delta2=keepresult2[size(keepresult2)];
    1198 
     1721      keepresult2 =
     1722                    normalizationPrimes(vid,ihp,0,0);
     1723      list delta2 = keepresult2[size(keepresult2)];   //2nd split factor
     1724      printlevel = printlev;                          //reset printlevel
     1725 
    11991726      setring BAS;
    12001727
     1728      //compute intersection multiplicity of both components:
     1729      new1 = new1,new2;
     1730      int mul=vdim(std(new1));
     1731
     1732     // ----- normalizationPrimes finished, add up results, RETURN --------
    12011733      for(lauf=1;lauf<=size(keepresult2)-1;lauf++)
    12021734      {
    1203          keepresult1=insert(keepresult1,keepresult2[lauf]);
    1204       }
    1205       keepresult1[size(keepresult1)]=delt+mul+delta1+delta2;
     1735         keepresult1 = insert(keepresult1,keepresult2[lauf]);
     1736      }
     1737      if ( delt >=0 && delta1[1] >=0 && delta2[1] >=0 && mul >=0 )
     1738      {
     1739         delt = delt+mul+delta1[1]+delta2[1];
     1740      }
     1741      else
     1742      {  delt = -1; }
     1743      delti = -2;
     1744
     1745      if ( y>=1 )
     1746      {
     1747        "// zero divisor produced a splitting into two components";
     1748        "// delta of first component:", delta1;
     1749        "// delta of second componenet:", delta2;
     1750        "// intersection multiplicity of both components:", mul;
     1751        "// total delta after splitting:", delt;
     1752      }
     1753      keepresult1[size(keepresult1)] = list(delt,delti);
    12061754      return(keepresult1);
    12071755   }
     
    12221770
    12231771   list pr=normalizationPrimes(i);
    1224    def r1=pr[1];
     1772   def r1 = pr[1];
    12251773   setring r1;
    12261774   norid;
    12271775   normap;
    12281776}
     1777
    12291778///////////////////////////////////////////////////////////////////////////////
    1230 proc substpart(ideal endid, ideal endphi, int homo, intvec rw)
     1779static proc substpart(ideal endid, ideal endphi, int homo, intvec rw)
    12311780
    12321781"//Repeated application of elimpart to endid, until no variables can be
     
    12341783//original weights, endphi (partial) normalization map";
    12351784
     1785//NOTE concerning iteration of maps: Let phi: x->f(y,z), y->g(x,z) then
     1786//phi: x+y+z->f(y,z)+g(x,z)+z, phi(phi):x+y+z->f(g(x,z),z)+g(f(y,z),z)+z
     1787//and so on: none of the x or y will be eliminated
     1788//Now subst: first x and then y: x+y+z->f(g(x,z),z)+g(x,z)+z eliminates y
     1789//further subst replaces x by y, makes no sense (objects more compicated).
     1790//Subst first y and then x eliminates x
     1791//In our situation we have triangular form: x->f(y,z), y->g(z).
     1792//phi: x+y+z->f(y,z)+g(z)+z, phi(phi):x+y+z->f(g(z),z)+g(z)+z eliminates x,y
     1793//subst x,y: x+y+z->f(g(z),z)+g(z)+z, eliminates x,y
     1794//subst y,x: x+y+z->f(y,z)+g(z)+z eliminates only x
     1795//HENCE: substitute vars depending on most other vars first
     1796//However, if the sytem xi-fi is reduced then xi does not appear in any of the
     1797//fj and hence the order does'nt matter when substitutinp xi by fi
     1798
    12361799{
    1237    def newRing=basering;
     1800   def newRing = basering;
    12381801   int ii,jj;
    1239    map phi = basering,maxideal(1);
    1240 
     1802   map phi = newRing,maxideal(1);    //identity map
    12411803   list Le = elimpart(endid);
    1242                                      //this proc and the next loop try to
    1243    int q = size(Le[2]);              //substitute as many variables as possible
    1244    intvec rw1 = 0;                   //indices of substituted variables
     1804   //this proc and the next loop try to substitute as many variables as
     1805   //possible indices of substituted variables
     1806
     1807   int q = size(Le[2]);    //q vars, stored in Le[2], have been substitutet
     1808   intvec rw1 = 0;         //will become indices of substituted variables
    12451809   rw1[nvars(basering)] = 0;
    1246    rw1 = rw1+1;
     1810   rw1 = rw1+1;            //rw1=1,..,1 (as many 1 as nvars(basering))
    12471811
    12481812   while( size(Le[2]) != 0 )
    12491813   {
    12501814      endid = Le[1];
     1815      if ( defined(ps) )
     1816      { kill ps; }
    12511817      map ps = newRing,Le[5];
    1252 
    12531818      phi = ps(phi);
    1254       for(ii=1;ii<=size(Le[2])-1;ii++)
     1819      for(ii=1;ii<=size(Le[2]);ii++)
    12551820      {
    12561821         phi=phi(phi);
    12571822      }
    12581823      //eingefuegt wegen x2-y2z2+z3
    1259       kill ps;
    12601824
    12611825      for( ii=1; ii<=size(rw1); ii++ )
    12621826      {
    1263          if( Le[4][ii]==0 )
     1827         if( Le[4][ii]==0 )        //ii = index of var which was substituted
    12641828         {
    1265             rw1[ii]=0;                             //look for substituted vars
     1829            rw1[ii]=0;             //substituted vars have entry 0 in rw1
    12661830         }
    12671831      }
    1268       Le=elimpart(endid);
     1832      Le=elimpart(endid);          //repeated application of elimpart
    12691833      q = q + size(Le[2]);
    12701834   }
    12711835   endphi = phi(endphi);
    1272 
    12731836//---------- return -----------------------------------------------------------
     1837// first the trivial case, where all variable have been eliminated
     1838   if( nvars(newRing) == q )
     1839   {
     1840     ring lastRing = char(basering),T(1),dp;
     1841     ideal endid = T(1);
     1842     ideal endphi = T(1);
     1843     for(ii=2; ii<=q; ii++ )
     1844     {
     1845        endphi[ii] = 0;
     1846     }
     1847     export(endid,endphi);
     1848     list L = lastRing;
     1849     setring newRing;
     1850     return(L);
     1851   }
     1852
    12741853// in the homogeneous case put weights for the remaining vars correctly, i.e.
    12751854// delete from rw those weights for which the corresponding entry of rw1 is 0
     
    12961875      ring lastRing = char(basering),(T(1..nvars(newRing)-q)),dp;
    12971876   }
    1298 
    12991877   ideal lastmap;
    1300    q = 1;
     1878   jj = 1;
     1879
    13011880   for(ii=1; ii<=size(rw1); ii++ )
    13021881   {
    1303       if ( rw1[ii]==1 ) { lastmap[ii] = T(q); q=q+1; }
     1882      if ( rw1[ii]==1 ) { lastmap[ii] = T(jj); jj=jj+1; }
    13041883      if ( rw1[ii]==0 ) { lastmap[ii] = 0; }
    13051884   }
    13061885   map phi1 = newRing,lastmap;
    1307    ideal endid  = phi1(endid);
     1886   ideal endid  = phi1(endid);      //### bottelneck
    13081887   ideal endphi = phi1(endphi);
     1888
     1889/*
     1890Versuch: subst statt phi
     1891   for(ii=1; ii<=size(rw1); ii++ )
     1892   {
     1893      if ( rw1[ii]==1 ) { endid = subst(endid,var(ii),T(jj)); }
     1894      if ( rw1[ii]==0 ) { endid = subst(endid,var(ii),0); }
     1895   }
     1896*/
    13091897   export(endid);
    13101898   export(endphi);
     
    13131901   return(L);
    13141902}
    1315 /////////////////////////////////////////////////////////////////////////////
     1903///////////////////////////////////////////////////////////////////////////////
    13161904
    13171905proc genus(ideal I,list #)
    1318 "USAGE:   genus(I) or genus(i,1); I a 1-dimensional ideal
     1906"USAGE:   genus(i) or genus(i,1); I a 1-dimensional ideal
    13191907RETURN:  an integer, the geometric genus p_g = p_a - delta of the projective
    1320          curve defined by I, where p_a is the arithmetic genus.
     1908         curve defined by i, where p_a is the arithmetic genus.
    13211909NOTE:    delta is the sum of all local delta-invariants of the singularities,
    13221910         i.e. dim(R'/R), R' the normalization of the local ring R of the
    1323          singularity.
    1324          genus(i,1) uses the normalization to compute delta. Usually this
    1325          is slow but sometimes not.
     1911         singularity. @*
     1912         genus(i,1) uses the normalization to compute delta. Usually genus(i,1)
     1913         is slower than genus(i) but sometimes not.
    13261914EXAMPLE: example genus; shows an example
    13271915"
     
    13361924      {
    13371925        // ERROR("This is not a curve");
    1338         if(w==1){"WARNING:This is not a curve";}
     1926        if(w==1){"** WARNING: Input does not define a curve **"; "";}
    13391927      }
    13401928   }
     
    13571945      return(-deg(p)+1);
    13581946   }
    1359    if(size(N[1])<nvars(R0))
     1947   if(size(N[1]) < nvars(R0))
    13601948   {
    13611949      string newvar=string(N[1]);
     
    15622150   if(size(#)!=0)
    15632151   {                              //uses the normalization to compute delta
    1564       list nor=normal(I,"wd");
    1565       delt=nor[size(nor)];
     2152      list nor=normal(I);
     2153      delt=nor[size(nor)][2];
    15662154      genus=genus-delt-deltainf;
    15672155      setring R0;
     
    19532541"USAGE:    primeClosure(L [,c]); L a list of a ring containing a prime ideal
    19542542                                 ker, c an optional integer
    1955 RETURN:   a list L consisting of rings L[1],...,L[n] such that
     2543RETURN:   a list L (of size n+1) consisting of rings L[1],...,L[n] such that
    19562544          - L[1] is a copy of (not a reference to!) the input ring L[1]
    19572545          - all rings L[i] contain ideals ker, L[2],...,L[n] contain ideals phi
     
    19632551            L[i]/ker are quotients of elements of L[i-1]/ker with denominator
    19642552            nzd via the injection phi.
     2553            L[n+1] is the delta invariant
    19652554NOTE:     - L is constructed by recursive calls of primeClosure itself.
    19662555          - c determines the choice of nzd:
     
    19712560"
    19722561{
    1973 // Start with a consistency check:
     2562  //---- Start with a consistency check:
    19742563
    19752564  if (!(typeof(L[1])=="ring"))
    1976     {
     2565  {
    19772566      "// Parameter must be a ring or a list containing a ring!";
    19782567      return(-1);
    1979     }
    1980 
    1981   int dblvl=printlevel-voice+2;
    1982 
    1983 
    1984 // Some auxiliary variables:
    1985 
    1986   int n=size(L);
    1987 
    1988 // How to choose the non-zerodivisor later on?
     2568  }
     2569
     2570  int dblvl = printlevel-voice+2;
     2571  list gnirlist = ringlist(basering);
     2572
     2573  //---- Some auxiliary variables:
     2574  int delt;                      //finally the delta invariant
     2575  if ( size(L) == 1 )
     2576  {
     2577      L[2] = delt;              //set delta to 0
     2578  }
     2579  int n = size(L)-1;            //L without delta invariant
     2580
     2581  //---- How to choose the non-zerodivisor later on?
    19892582
    19902583  int nzdoption=0;
    19912584  if (size(#)>0)
    1992     {
     2585  {
    19932586      nzdoption=#[1];
    1994     }
     2587  }
    19952588
    19962589// R0 is the ring to work with, if we are in step one, make a copy of the
     
    19992592
    20002593  if (n==1)
    2001     {
    2002       def R=L[1];
    2003       def BAS=basering;
     2594  {
     2595      def R = L[1];
     2596      list Rlist = ringlist(R);
     2597      def BAS = basering;
    20042598      setring R;
    20052599      if (!(typeof(ker)=="ideal"))
    2006         {
     2600      {
    20072601          "// No ideal ker in the input ring!";
    20082602          return (-1);
    2009         }
     2603      }
    20102604      ker=simplify(interred(ker),15);
    2011       execute ("ring R0="+charstr(R)+",("+varstr(R)+"),("+ordstr(R)+");");
     2605      //execute ("ring R0="+charstr(R)+",("+varstr(R)+"),("+ordstr(R)+");");
     2606      def R0 = ring(Rlist);
     2607      setring R0;
    20122608      ideal ker=fetch(R,ker);
    20132609
     
    20192615        attrib(R0,"iso_sing_Rees",attrib(L[1],"iso_sing_Rees"));
    20202616      }
    2021       L=R0;
    2022     }
     2617      L[1]=R0;
     2618  }
    20232619  else
    2024     {
    2025       def R0=L[n];
     2620  {
     2621      def R0 = L[n];
    20262622      setring R0;
    2027     }
     2623  }
    20282624
    20292625
     
    20312627// locus of ker, J:=rad(ker):
    20322628
    2033 //  if (homog(ker)==1)
    2034 //    {
    2035       list SM=mstd(ker);
    2036 //    }
    2037 /*  else
    2038     {
    2039       list SM=groebner(ker),ker;
    2040     }*/
     2629   list SM=mstd(ker);
    20412630
    20422631// In the first iteration, we have to compute the singular locus "from
    2043 // scratch". In further iterations, we can fetch it from the previous one but
    2044 // have to compute its radical.
    2045 
    2046   if (n==1)
    2047     {
     2632// scratch".
     2633// In further iterations, we can fetch it from the previous one but
     2634// have to compute its radical
     2635// the next rings R1 contain already the (fetched) ideal
     2636
     2637  if (n==1)                              //we are in R0=L[1]
     2638  {
    20482639      if (typeof(attrib(R0,"iso_sing_Rees"))=="int")
    20492640      {
     
    20532644          J=J,var(s);
    20542645        }
     2646        J = J,SM[2];
     2647        list JM = mstd(J);
    20552648      }
    20562649      else
    20572650      {
    2058         ideal J=minor(jacob(SM[2]),nvars(basering)-dim(SM[1]));
    2059       }
    2060       J=J+SM[2];
    2061       if (homog(J)==1)
    2062       {
    2063         J=mstd(J)[2];
    2064       }
    2065       J=radical(interred(J));
    2066     }
     2651        if ( dblvl >= 1 )
     2652        {"";
     2653           "// compute the singular locus";
     2654        }
     2655        //### Berechnung des singulŠren Orts geŠndert (ist so schneller)
     2656        ideal J = minor(jacob(SM[2]),nvars(basering)-dim(SM[1]),SM[1]);
     2657        J = J,SM[2];
     2658        list JM = mstd(J);
     2659      }
     2660
     2661      if ( dblvl >= 1 )
     2662      {"";
     2663         "// dimension of singular locus is", dim(JM[1]);
     2664         if (  dblvl >= 2 )
     2665         {"";
     2666            "// the singular locus is:"; JM[2];
     2667         }
     2668      }
     2669
     2670      if ( dblvl >= 1 )
     2671      {"";
     2672         "// compute radical of singular locus";
     2673      }
     2674
     2675      J = simplify(radical(JM[2]),2);
     2676      if ( dblvl >= 1 )
     2677      {"";
     2678         "// radical of singular locus is:"; J;
     2679         pause();
     2680      }
     2681  }
    20672682  else
    2068     {
    2069       J=radical(interred(J));
    2070     }
    2071 
    2072   // having computed the radical J of the ideal of the singular locus,
    2073   // we now need to pick an element nzd of J
    2074 
    2075   poly nzd=J[1];
    2076   if (nzdoption)
     2683  {
     2684      if ( dblvl >= 1 )
     2685      {"";
     2686         "// compute radical of test ideal in ideal of singular locus";
     2687      }
     2688      J = simplify(radical(J),2);
     2689      if ( dblvl >= 1 )
     2690      {"";
     2691         "// radical of test ideal is:"; J;
     2692         pause();
     2693      }
     2694  }
     2695
     2696  // having computed the radical J of/in the ideal of the singular locus,
     2697  // we now need to pick an element nzd of J;
     2698  // NOTE: nzd must be a non-zero divisor mod ker, i.e. not contained in ker
     2699
     2700  poly nzd = J[1];
     2701  poly nzd1 = NF(nzd,SM[1]);
     2702  if (nzd1 != 0)
     2703  {
     2704     if ( deg(nzd)>=deg(nzd1) && size(nzd)>size(nzd1) )
     2705     {
     2706        nzd = nzd1;
     2707     }
     2708  }
     2709
     2710  if (nzdoption || nzd1==0)
    20772711  {
    20782712    for (int ii=2;ii<=ncols(J);ii++)
    20792713    {
    2080       if ( (deg(nzd)>=deg(J[ii])) && (size(nzd)>size(J[ii])) )
    2081       {
    2082         nzd=J[ii];
     2714      nzd1 = NF(J[ii],SM[1]);
     2715      if ( nzd1 != 0 )
     2716      {
     2717        if ( (deg(nzd)>=deg(J[ii])) && (size(nzd)>size(J[ii])) )
     2718        {
     2719          nzd=J[ii];
     2720        }
     2721        if ( deg(nzd)>=deg(nzd1) && size(nzd)>size(nzd1) )
     2722        {
     2723          nzd = nzd1;
     2724        }
    20832725      }
    20842726    }
     
    20862728
    20872729  export nzd;
    2088   list RR=SM[1],SM[2],J,nzd;
    2089   list RS=HomJJ(RR);
    2090 
    2091 
    2092 //////////////////////////////////////////////////////////////////////////////
    2093 
    2094 
     2730  list RR = SM[1],SM[2],J,nzd;
     2731
     2732  if ( dblvl >= 1 )
     2733  {"";
     2734     "// compute the first ring extension:";
     2735  }
     2736
     2737  list RS = HomJJ(RR);
     2738
     2739//-------------------------------------------------------------------------
    20952740// If we've reached the integral closure (as determined by the result of
    20962741// HomJJ), then we are done, otherwise we have to prepare the next iteration.
    20972742
    2098   if (RS[2]==1)               // we've reached the integral closure
     2743  if (RS[2]==1)     // we've reached the integral closure, we are still in R0
    20992744    {
    21002745      kill J;
     2746      if ( n== 1)
     2747      {
     2748        def R1 = RS[1];
     2749        setring R1;
     2750        ideal norid, normap = endid, endphi;
     2751        kill endid,  endphi;
     2752
     2753        //"//### case: primeClosure, final";
     2754        //"size norid:", size(norid), size(string(norid));
     2755        //"interred:";
     2756        //norid = interred(norid);
     2757        //"size norid:", size(norid), size(string(norid));
     2758
     2759        export (norid, normap);
     2760        L[1] = R1;
     2761      }
    21012762      return(L);
    21022763    }
     
    21042765    {
    21052766      if (n==1)               // In the first iteration: keep only the data
    2106         {                     // needed later on.
    2107           kill RR,SM;
    2108 
    2109           export(ker);
    2110         }
    2111 
    2112       def R1=RS[1];           // The data of the next ring R1:
     2767      {                       // needed later on.
     2768         kill RR,SM;
     2769         export(ker);
     2770      }
     2771      if ( dblvl >= 1 )
     2772      {"";
     2773         "// computing the next ring extension, we are in loop"; n+1;
     2774      }
     2775
     2776      def R1 = RS[1];         // The data of the next ring R1:
     2777      delt = RS[3];           // the delta invariant of the ring extension
    21132778      setring R1;             // keep only what is necessary and kill
    21142779      ideal ker=endid;        // everything else.
    21152780      export(ker);
    21162781      ideal norid=endid;
     2782
     2783      //"//### case: primeClosure, loop", n+1;
     2784      //"size norid:", size(norid), size(string(norid));
     2785      //"interred:";
     2786      //norid = interred(norid);        //????
     2787      //"size norid:", size(norid), size(string(norid));
     2788
    21172789      export(norid);
    21182790      kill endid;
    21192791
    2120       map phi=R0,endphi;      // fetch the singular locus
    2121       ideal J=mstd(simplify(phi(J)+ker,4))[2];
     2792      map phi = R0,endphi;                        // fetch the singular locus
     2793      ideal J = mstd(simplify(phi(J)+ker,4))[2];  // ideal J in R1
    21222794      export(J);
    21232795      if(n>1)
     
    21312803      export(normap);
    21322804      kill phi;              // we save phi as ideal, not as map, so that
    2133       ideal phi=endphi;       // we have more flexibility in the ring names
     2805      ideal phi=endphi;      // we have more flexibility in the ring names
    21342806      kill endphi;           // later on.
    21352807      export(phi);
    21362808      L=insert(L,R1,n);       // Add the new ring R1 and go on with the
     2809                              // next iteration
     2810      if ( L[size(L)] >= 0 && delt >= 0 )
     2811      {
     2812         delt = L[size(L)] + delt;
     2813      }
     2814      else
     2815      {
     2816         delt = -1;
     2817      }     
     2818      L[size(L)] = delt;
     2819
    21372820      if (size(#)>0)
    2138         {
     2821      {
    21392822          return (primeClosure(L,#));
    2140         }
     2823      }
    21412824      else
    2142         {
     2825      {
    21432826          return(primeClosure(L));         // next iteration.
    2144         }
     2827      }
    21452828    }
    21462829}
     
    21622845}
    21632846
    2164 
    2165 //////////////////////////////////////////////////////////////////////////////
    2166 //////////////////////////////////////////////////////////////////////////////
    2167 
    2168 proc closureRingtower(list L)
    2169 "USAGE:    closureRingtower(list L); L a list of rings
    2170 CREATE:   rings R(1),...,R(n) such that R(i)=L[i] for all i
    2171 EXAMPLE:  example closureRingtower; shows an example
    2172 "
    2173 {
    2174   int n=size(L);
    2175 
    2176   for (int i=1;i<=n;i++)
    2177     {
    2178       if (defined(R(i))) {
    2179         string s="Fixed name R("+string(i)+") leads to conflict with existing "
    2180               +"object having this name";
    2181         ERROR(s);
    2182       }
    2183       def R(i)=L[i];
    2184       export R(i);
    2185     }
    2186 
    2187   return();
    2188 }
    2189 example
    2190 {
    2191   "EXAMPLE:"; echo=2;
    2192   ring R=0,(x,y),dp;
    2193   ideal I=x4,y4;
    2194   list L=primeClosure(ReesAlgebra(I)[1]);
    2195   closureRingtower(L);
    2196   R(1);
    2197   R(4);
    2198   kill R(1),R(2),R(3),R(4);
    2199 }
    2200 
    2201 //////////////////////////////////////////////////////////////////////////////
    2202 //////////////////////////////////////////////////////////////////////////////
     2847///////////////////////////////////////////////////////////////////////////////
    22032848
    22042849proc closureFrac(list L)
    2205 "USAGE:    closureFrac (L); L a list as in the result of primeClosure, L[n]
    2206                            containing an additional poly f
     2850"USAGE:    closureFrac (L); L a list of size n+1 as in the result of
     2851          primeClosure, L[n] contains an additional poly f
    22072852CREATE:   a list fraction of two elements of L[1], such that
    22082853          f=fraction[1]/fraction[2] via the injections phi L[i]-->L[i+1].
     
    22122857// Define some auxiliary variables:
    22132858
    2214   int n=size(L);
    2215   int j,k,l;
     2859  int n=size(L)-1;
     2860  int i,j,k,l;
    22162861  string mapstr;
    2217 
    2218   for (int i=1;i<=n;i++) { def R(i)=L[i]; }
     2862  for (i=1; i<=n; i++) { def R(i) = L[i]; }
    22192863
    22202864// The quotient representing f is computed as in 'closureGenerators' with
     
    22242868//   - we have to make sure that no more objects of the rings R(i) survive.
    22252869
    2226   for (j=1;j<=2;j++)
     2870  for (j=1; j<=2; j++)
    22272871    {
    22282872      setring R(n);
    22292873      if (j==1)
    2230         {
    2231           poly p=f;
    2232         }
     2874      {
     2875         poly p=f;
     2876      }
    22332877      else
    2234         {
    2235           p=1;
    2236         }
    2237 
    2238       for (k=n;k>1;k--)
    2239         {
    2240 
     2878      {
     2879         p=1;
     2880      }
     2881
     2882      for (k=n; k>1; k--)
     2883      {
    22412884          if (j==1)
    2242             {
    2243               map phimap=R(k-1),phi;
    2244             }
     2885          {
     2886             map phimap=R(k-1),phi;
     2887          }
    22452888
    22462889          p=p*phimap(nzd);
     
    22522895
    22532896          if (j==1)
    2254             {
    2255               execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+",
    2256                        Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k)))
    2257                        +"),dp("+string(ncols(phi))+"));");
     2897          {
     2898             //### noch abfragen ob Z(i) definiert ist
     2899             list gnirlist = ringlist(R(k));
     2900             int n2 = size(gnirlist[2]);
     2901             int n3 = size(gnirlist[3]);
     2902             for( i=1; i<=ncols(phi); i++)
     2903             {
     2904               gnirlist[2][n2+i] = "Z("+string(i)+")";
     2905             }
     2906             intvec V;
     2907             V[ncols(phi)]=0; V=V+1;
     2908             gnirlist[3] = insert(gnirlist[3],list("dp",V),n3-1);
     2909             def S(k) = ring(gnirlist);
     2910             setring S(k);
     2911
     2912             //execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+",
     2913             //          Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k)))
     2914             //          +"),dp("+string(ncols(phi))+"));");
     2915
    22582916              ideal phi = imap(R(k),phi);
    2259               ideal J= imap (R(k),ker);
     2917              ideal J = imap (R(k),ker);
    22602918              for (l=1;l<=ncols(phi);l++)
    2261                 {
     2919              {
    22622920                  J=J+(Z(l)-phi[l]);
    2263                 }
     2921              }
    22642922              J=groebner(J);
    22652923              poly h=NF(imap(R(k),p),J);
    2266             }
     2924          }
    22672925          else
    2268             {
     2926          {
    22692927              setring S(k);
    22702928              h=NF(imap(R(k),p),J);
    22712929              setring R(k);
    22722930              kill p;
    2273             }
     2931          }
    22742932
    22752933          setring R(k-1);
    22762934
    22772935          if (j==1)
    2278             {
    2279               mapstr=" map backmap = S(k),";
    2280               for (l=1;l<=nvars(R(k));l++)
    2281                 {
    2282                   mapstr=mapstr+"0,";
    2283                 }
    2284               execute (mapstr+"maxideal(1);");
    2285 
     2936          {
     2937              ideal maxi;
     2938              maxi[nvars(R(k))] = 0;
     2939              maxi = maxi,maxideal(1);
     2940              map backmap = S(k),maxi;
     2941         
     2942              //mapstr=" map backmap = S(k),";
     2943              //for (l=1;l<=nvars(R(k));l++)
     2944              //{
     2945              //  mapstr=mapstr+"0,";
     2946              //}
     2947              //execute (mapstr+"maxideal(1);");
    22862948              poly p;
    2287             }
     2949          }
    22882950          p=NF(backmap(h),std(ker));
    22892951          if (j==2)
     
    23342996}
    23352997
    2336 //////////////////////////////////////////////////////////////////////////////
    2337 //////////////////////////////////////////////////////////////////////////////
    2338 
    2339 static
    2340 proc closureGenerators(list L);    // called inside normalI
     2998///////////////////////////////////////////////////////////////////////////////
     2999// closureGenerators is called inside proc normal (option "withGens" )
     3000//
     3001
     3002// INPUT is the output of proc primeClosure (except for the last element, the
     3003// delta invariant) : hence input is a list L consisting of rings
     3004// L[1],...,L[n] (denoted R(1)...R(n) below) such that
     3005// - L[1] is a copy of (not a reference to!) the input ring L[1]
     3006// - all rings L[i] contain ideals ker, L[2],...,L[n] contain ideals phi
     3007// such that
     3008//                L[1]/ker --> ... --> L[n]/ker
     3009// are injections given by the corresponding ideals phi, and L[n]/ker
     3010// is the integral closure of L[1]/ker in its quotient field.
     3011// - all rings L[i] contain a polynomial nzd such that elements of
     3012// L[i]/ker are quotients of elements of L[i-1]/ker with denominator
     3013// nzd via the injection phi.
     3014
     3015// COMPUTE: In the list L of rings R(1),...,R(n), compute representations of
     3016// the ring variables of the last ring R(n) as fractions of elements of R(1):
     3017// The proc returns an ideal preim s.t. preim[i]/preim[size(preim)] expresses
     3018// the ith variable of R(n) as fraction of elements of the basering R(1)
     3019// preim[size(preim)] is a non-zero divisor of basering/i.
     3020
     3021proc closureGenerators(list L);   
    23413022{
    2342   // In the list L of rings R(1),...,R(n), compute representations of the ring
    2343   // ring variables of the last ring R(n) as fractions of elements of R(1).
    2344 
    2345   def Rees=basering;              // when called inside normalI, the Rees
    2346                                   // Algebra is the current basering.
    2347 
    2348   // First of all we need some variable declarations...
    2349 
    2350   list preimages;
    2351   int n=size(L);                  // the number of rings R(1)-->...-->R(n)
     3023  def Rees=basering;         // when called inside normalI (in reesclos.lib)
     3024                             // the Rees Algebra is the current basering
     3025
     3026  // ------- First of all we need some variable declarations -----------
     3027  int n = size(L);                // the number of rings R(1)-->...-->R(n)
     3028  int length = nvars(L[n]);       // the number of variables of the last ring
    23523029  int j,k,l;
    2353   int length=nvars(L[n]);         // the number of variables of the last ring
    2354   string mapstr;
    2355 
    2356   for (int i=1;i<=n;i++) { def R(i)=L[i]; }
     3030  string mapstr;   
     3031  list preimages;                 
     3032  //Note: the empty list belongs to no ring, hence preimages can be used
     3033  //later in R(1)
     3034  //this is not possible for ideals (belong always to some ring)
     3035
     3036  for (int i=1; i<=n; i++)
     3037  {
     3038     def R(i)=L[i];          //give the rings from L a name
     3039  }
    23573040
    23583041  // For each variable (counter j) and for each intermediate ring (counter k):
     
    23603043  // Finally, do the same for nzd.
    23613044
    2362   for (j=1;j<=length+1;j++)
    2363     {
     3045  for (j=1; j <= length+1; j++ )
     3046  {
    23643047      setring R(n);
    2365 
    23663048      if (j==1)
     3049      {
     3050        poly p;
     3051      }
     3052      if (j <= length )
     3053      {
     3054        p=var(j);
     3055      }
     3056      else
     3057      {
     3058        p=1;
     3059      }
     3060      //i.e. p=j-th var of R(n) for j<=length and p=1 for j=length+1
     3061
     3062      for (k=n; k>1; k--)
     3063      {
     3064
     3065        if (j==1)
    23673066        {
    2368           poly p;
    2369         }
    2370 
    2371       if (j<=nvars(R(n)))
    2372         {
    2373           p=var(j);
    2374         }
    2375       else
    2376         {
    2377           p=1;
    2378         }
    2379 
    2380       for (k=n;k>1;k--)
    2381         {
    2382 
    2383           if (j==1)
    2384           {
    2385             map phimap=R(k-1),phi;      // phimap is the map corresponding
    2386           }                             // to phi
    2387 
    2388           p=p*phimap(nzd);
     3067          map phimap=R(k-1),phi;   //phimap:R(k-1)-->R(n), k=2..n, is the map
     3068                                   //belonging to phi in R(n)
     3069        }                             
     3070
     3071        p = p*phimap(nzd);
    23893072
    23903073          // Compute the preimage of [p mod ker(k)] under phi in R(k-1):
    23913074          // As p is an element of Image(phi), there is a polynomial h such
    23923075          // that h is mapped to [p mod ker(k)], and h can be computed as the
    2393           // normal form of p w.r.t. a Gröbner basis of
    2394           // J(k):=<ker(k),Z(l)-phi(k)(l)> in R(k)[Z]=:S(k)
    2395 
    2396           if (j==1)   // In the first iteration: Create S(k), fetch phi and
    2397                       // ker(k) and construct the ideal J(k).
    2398             {
    2399               execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+",
    2400                        Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k)))
    2401                        +"),dp("+string(ncols(phi))+"));");
    2402               ideal phi=imap(R(k),phi);
    2403               ideal J=imap (R(k),ker);
    2404               for (l=1;l<=ncols(phi);l++)
    2405                 {
    2406                   J=J+(Z(l)-phi[l]);
    2407                 }
    2408               J=groebner(J);
    2409               poly h=NF(imap(R(k),p),J);
    2410             }
    2411           else
    2412             {
    2413               setring S(k);
    2414               h=NF(imap(R(k),p),J);
    2415             }
    2416 
    2417           setring R(k-1);
    2418 
    2419           if (j==1)  // In the first iteration: Compute backmap:S(k)-->R(k-1)
    2420             {
    2421               mapstr=" map backmap = S(k),";
    2422               for (l=1;l<=nvars(R(k));l++)
    2423                 {
    2424                   mapstr=mapstr+"0,";
    2425                 }
    2426               execute (mapstr+"maxideal(1);");
    2427 
    2428               poly p;
    2429             }
    2430           p=NF(backmap(h),std(ker));
     3076          // normal form of p w.r.t. a Groebner basis of
     3077          // J(k) := <ker(k),Z(l)-phi(k)(l)> in R(k)[Z]=:S(k)
     3078
     3079        if (j==1)   // In the first iteration: Create S(k), fetch phi and
     3080                    // ker(k) and construct the ideal J(k).
     3081        {
     3082         //### noch abfragen ob Z(i) definiert ist
     3083         list gnirlist = ringlist(R(k));
     3084         int n2 = size(gnirlist[2]);
     3085         int n3 = size(gnirlist[3]);
     3086         for( i=1; i<=ncols(phi); i++)
     3087         {
     3088            gnirlist[2][n2+i] = "Z("+string(i)+")";
     3089         }
     3090         intvec V;
     3091         V[ncols(phi)]=0;
     3092         V=V+1;
     3093         gnirlist[3] = insert(gnirlist[3],list("dp",V),n3-1);
     3094         def S(k) = ring(gnirlist);
     3095         setring S(k);
     3096
     3097        // execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+",
     3098        //           Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k)))
     3099        //           +"),dp("+string(ncols(phi))+"));");
     3100
     3101          ideal phi = imap(R(k),phi);
     3102          ideal J = imap (R(k),ker);
     3103          for ( l=1; l<=ncols(phi); l++ )
     3104          {
     3105             J=J+(Z(l)-phi[l]);
     3106          }
     3107          J = groebner(J);
     3108          poly h = NF(imap(R(k),p),J);
    24313109        }
    2432 
    2433       // When down to R(1), store the result in the list preimages
    2434 
    2435       preimages = insert(preimages,p,j-1);
     3110        else
     3111        {
     3112           setring S(k);
     3113           h = NF(imap(R(k),p),J);
     3114        }
     3115
     3116        setring R(k-1);
     3117
     3118        if (j==1)  // In the first iteration: Compute backmap:S(k)-->R(k-1)
     3119        {
     3120           ideal maxi;
     3121           maxi[nvars(R(k))] = 0;
     3122           maxi = maxi,maxideal(1);
     3123           map backmap = S(k),maxi;
     3124         
     3125           //mapstr=" map backmap = S(k),";
     3126           //for (l=1;l<=nvars(R(k));l++)
     3127           //{
     3128           //  mapstr=mapstr+"0,";
     3129           //}
     3130           //execute (mapstr+"maxideal(1);");
     3131
     3132           poly p;
     3133        }
     3134        p = NF(backmap(h),std(ker));
     3135     }
     3136     // Whe are down to R(1), store here the result in the list preimages
     3137     preimages = insert(preimages,p,j-1);
     3138  }
     3139  ideal preim;                  //make the list preimages to an ideal preim
     3140  for ( i=1; i<=size(preimages); i++ )
     3141  {
     3142     preim[i] = preimages[i];
     3143  }
     3144  // R(1) was a copy of Rees, so we have to get back to the basering Rees from
     3145  // the beginning and fetch the result (the ideal preim) to this ring.
     3146  setring Rees;
     3147  return (fetch(R(1),preim));
     3148}
     3149
     3150///////////////////////////////////////////////////////////////////////////////
     3151//                From here: procedures for char p with Frobenius
     3152///////////////////////////////////////////////////////////////////////////////
     3153
     3154proc normalP(ideal id,list #)
     3155"USAGE:   normalP(id [,choose]); id a radical ideal, choose a comma separated
     3156         list of optional strings: \"withRing\" or \"isPrim\" or \"noFac\".@*
     3157         If choose = \"noFac\", factorization is avoided during the computation
     3158         of the minimal associated primes; choose = \"isPrim\" disables the
     3159         computation of the minimal associated primes (should only be used
     3160         if the ideal is known to be prime).@*
     3161ASSUME:  The characteristic of the ground field must be positive. The ideal
     3162         id is assumed to be radical. However, if choose does not contain
     3163         \"isPrim\" the minimal associated primes of id are computed first
     3164         and hence normal computes the normalization of the radical of id.
     3165         If choose = \"isPrim\" the ideal must be a prime ideal (this is not
     3166         tested) otherwise the result may be wrong.
     3167RETURN:  a list, say 'nor' of size 2 (default) or, if \"withRing\" is given,
     3168         of size 3. @*         
     3169         nor[1] (resp. nor[2] if \"withRing\" is given) is a list of ideals
     3170         Ii, i=1..r, in the basering where r is the number of associated prime
     3171         ideals P_i (irreducible components) of id.@*
     3172         - Ii is an ideal given by polynomials g_1,...,g_k,g_k+1 such that
     3173           g_1/g_k+1,...,g_k/g_k+1 generate the integral closure of
     3174           basering/P_i as module (over the basering) in its quotient field.@*
     3175         
     3176         nor[2] (resp. nor[3] if choose=\"withRing\") is a list of an intvec
     3177         of size r, the delta invariants of the r components, and an integer,
     3178         the total delta invariant of basering/id (-1 means infinite, and 0
     3179         that basering/P_i resp. basering/input is normal). @*
     3180
     3181         If the optional string \"withRing\" is given, the ring structure of
     3182         the normalization is computed too and nor[1] is a list of r rings.@*
     3183         Each ring Ri = nor[1][i], i=1..r, contains two ideals with given names
     3184         @code{norid} and @code{normap} such that @*
     3185         - Ri/norid is the normalization of the i-th rime component P_i, i.e.
     3186           isomorphic to the integral closure of basering/P_i in its field
     3187           of fractions; @*
     3188         - the direct sum of the rings Ri/norid is the normalization
     3189           of basering/id; @*
     3190         - @code{normap} gives the normalization map from basering/P_i to
     3191           Ri/norid (for each i).@*
     3192THEORY:  The delta invariant of a reduced ring K[x1,...,xn]/id is
     3193             dim_K(normalization(K[x1,...,xn]/id) / K[x1,...,xn]/id)
     3194         We call this number also the delta invariant of id. normalP uses
     3195         the qth-power algorithm suggested by Leonard-Pellikaan (using the
     3196         Frobenius) in part similair to an implementation by Singh-Swanson.
     3197NOTE:    To use the i-th ring type: @code{def R=nor[1][i]; setring R;}.
     3198@*       Increasing/decreasing printlevel displays more/less comments
     3199         (default: printlevel = 0).
     3200@*       Not implemented for local or mixed orderings or quotient rings.
     3201@*       If the input ideal id is weighted homogeneous a weighted ordering may
     3202         be used (qhweight(id); computes weights).
     3203@*       works only in characteristic p > 0.
     3204KEYWORDS: normalization; integral closure; delta invariant.
     3205SEE ALSO: normal
     3206EXAMPLE: example normalP; shows an example
     3207"
     3208{
     3209   int i,j,y, wring, isPrim, noFac, sr, del, co;;
     3210   intvec deli;
     3211   list resu, Resu, prim, Gens, mstdid;
     3212   ideal gens;
     3213   y = printlevel-voice+2;
     3214
     3215   if ( ord_test(basering) != 1)
     3216   {
     3217     "";
     3218     "// Not implemented for this ordering,";
     3219     "// please change to global ordering!";
     3220     return(resu);
     3221   }
     3222   if ( char(basering) <= 0)
     3223   {
     3224     "";
     3225     "// Algorithm works only in positive characteristic,";
     3226     "// use procedure 'normal' if the characteristic is 0";
     3227     return(resu);
     3228   }
     3229
     3230//--------------------------- define the method ---------------------------
     3231   string method;                //make all options one string in order to use
     3232                                 //all combinations of options simultaneously
     3233   for ( i=1; i<= size(#); i++ )
     3234   {
     3235     if ( typeof(#[i]) == "string" )
     3236     {
     3237       method = method + #[i];
     3238     }
     3239   }
     3240
     3241   if ( find(method,"withring") or find(method,"withRing") )
     3242   {
     3243     wring=1;
     3244   }
     3245   if ( find(method,"isPrim") or find(method,"isprim") )
     3246   {
     3247     isPrim=1;
     3248   }
     3249   if ( find(method,"noFac") )
     3250   {
     3251     noFac=1;
     3252   }
     3253
     3254   kill #;
     3255   list #;
     3256//--------------------------- start computation ---------------------------
     3257   ideal II,K1,K2;
     3258
     3259   //----------- check first (or ignore) if input id is prime -------------
     3260
     3261   if ( isPrim )
     3262   {
     3263      prim[1] = id;
     3264      if( y >= 0 )
     3265      { "";
     3266    "// ** WARNING: result is correct if ideal is prime (not checked) **";
     3267    "// disable option \"isPrim\" to decompose ideal into prime components";"";
     3268      }
     3269   }
     3270   else
     3271   {
     3272      if(y>=1)
     3273      {  "// compute minimal associated primes"; }
     3274
     3275      if( noFac )
     3276      { prim = minAssGTZ(id,1); }
     3277      else
     3278      { prim = minAssGTZ(id); }
     3279
     3280      if(y>=1)
     3281      { 
     3282         prim;"";
     3283         "// number of irreducible components is", size(prim);
     3284      }
     3285   }
     3286
     3287   //----------- compute integral closure for every component -------------
     3288
     3289      for(i=1; i<=size(prim); i++)
     3290      {
     3291         if(y>=1)
     3292         {
     3293            ""; pause(); "";
     3294            "// start computation of component",i;
     3295            "   --------------------------------";
     3296         }
     3297         if(y>=1)
     3298         {  "// compute SB of ideal";
     3299         }
     3300         mstdid = mstd(prim[i]);
     3301         if(y>=1)
     3302         {  "// dimension of component is", dim(mstdid[1]);"";}
     3303
     3304      //------- 1-st main subprocedure: compute module generators ----------
     3305         printlevel = printlevel+1;
     3306         II = normalityTest(mstdid);
     3307
     3308      //------ compute also the ringstructure if "withRing" is given -------
     3309         if ( wring )
     3310         {
     3311         //------ 2-nd main subprocedure: compute ring structure -----------
     3312            resu = list(computeRing(II,prim[i])) + resu;
     3313         }
     3314         printlevel = printlevel-1;
     3315
     3316      //----- rearrange module generators s.t. denominator comes last ------
     3317         gens=0;
     3318         for( j=2; j<=size(II); j++ )
     3319         {
     3320            gens[j-1]=II[j];
     3321         }
     3322         gens[size(gens)+1]=II[1];
     3323         Gens = list(gens) + Gens;
     3324      //------------------------------ compute delta -----------------------
     3325         K1 = mstdid[1]+II;
     3326         K1 = std(K1);
     3327         K2 = mstdid[1]+II[1];
     3328         K2 = std(K2);       
     3329         // K1 = std(mstdid[1],II);      //### besser
     3330         // K2 = std(mstdid[1],II[1]);   //### besser: Hannes, fixen!
     3331         co = codim(K1,K2);
     3332         deli = co,deli;
     3333         if ( co >= 0 && del >= 0 )
     3334         {
     3335            del = del + co;
     3336         }
     3337         else
     3338         { del = -1; }
     3339      }
     3340
     3341      if ( del >= 0 )
     3342      {
     3343         int mul = iMult(prim);
     3344         del = del + mul;
     3345      }
     3346      else
     3347      { del = -1; }
     3348
     3349      deli = deli[1..size(deli)-1];
     3350      if ( wring )
     3351      { Resu = resu,Gens,list(deli,del); }
     3352      else
     3353      { Resu = Gens,list(deli,del); }
     3354
     3355   sr = size(prim);
     3356
     3357//-------------------- Finally print comments and return --------------------
     3358   if(y >= 0)
     3359   {"";
     3360     if ( wring )
     3361     {
     3362"// 'normalP' created a list, say nor, of three lists:
     3363// nor[1] resp. nor[2] are lists of",sr,"ring(s) resp. ideal(s)
     3364// and nor[3] is a list of an intvec and an integer.
     3365// To see the result, type
     3366     nor;
     3367// To access the i-th ring nor[1][i] give it a name, say Ri, and type e.g.
     3368     def R1 = nor[1][1]; setring R1;  norid; normap;
     3369// for the other rings type first setring r; (if r is the name of your
     3370// original basering) and then continue as for the first ring;
     3371// Ri/norid is the affine algebra of the normalization of the i-th
     3372// component r/P_i (where P_i is an associated prime of the input ideal)
     3373// and normap the normalization map from r to Ri/norid;
     3374//    nor[2] is a list of",sr,"ideal(s), each ideal nor[2][i] consists of
     3375// elements g1..gk of r such that the gj/gk generate the integral
     3376// closure of r/P_i as (r/P_i)-module in the quotient field of r/P_i.
     3377//    nor[3] shows the delta-invariant of each component and of the input
     3378// ideal (-1 means infinite, and 0 that r/P_i is normal).";
     3379     }
     3380     else
     3381     {
     3382"// 'normalP' computed a list, say nor, of two lists:
     3383//    nor[1] is a list of",sr,"ideal(s), where each ideal nor[1][i] consists
     3384// of elements g1..gk of the basering such that gj/gk generate the integral
     3385// closure of the i-th component as (basering/P_i)-module in the quotient
     3386// field of basering/P_i (P_i an associated prime of the input ideal);
     3387//    nor[2] shows the delta-invariant of each component and of the input ideal
     3388// (-1 means infinite, and 0 that r/P_i is normal).";
     3389     }
     3390   }
     3391
     3392   return(Resu);
     3393}
     3394example
     3395{ "EXAMPLE:"; echo = 2;
     3396   ring r  = 11,(x,y,z),wp(2,1,2);
     3397   ideal i = x*(z3 - xy4 + x2);
     3398   list nor= normalP(i); nor;
     3399   //the result says that both components of i are normal, but i itself
     3400   //has infinite delta
     3401   pause("hit return to continue");
     3402
     3403   ring s = 2,(x,y),dp;
     3404   ideal i = y*((x-y^2)^2 - x^3);
     3405   list nor = normalP(i,"withRing"); nor;
     3406
     3407   def R2  = nor[1][2]; setring R2;
     3408   norid; normap;
     3409}
     3410
     3411///////////////////////////////////////////////////////////////////////////////
     3412// Assume: mstdid is the result of mstd(prim[i]), prim[i] a prime component of
     3413// the input ideal id of normalP.
     3414// Output is an ideal U s.t. U[i]/U[1] are module generators.
     3415 
     3416static proc normalityTest(list mstdid)
     3417{
     3418   int y = printlevel-voice+2;
     3419   intvec op = option(get);
     3420   option(redSB);
     3421   def R = basering;
     3422   int n, p = nvars(R), char(R);
     3423   int ii;
     3424
     3425   ideal J = mstdid[1];         //J is the SB of I
     3426   ideal I = mstdid[2];
     3427   int h = n-dim(J);            //codimension of V(I), I is a prime ideal
     3428
     3429   //-------------------------- compute singular locus ----------------------
     3430   qring Q = J;                 //pass to quotient ring
     3431   ideal I = imap(R,I);
     3432   ideal J = imap(R,J);
     3433   attrib(J,"isSB",1);
     3434   if ( y >= 1)
     3435   { "start normality test";  "compute singular locus";}
     3436
     3437   ideal M = minor(jacob(I),h,J); //use the command minor modulo J (hence J=0)
     3438   M = std(M);                    //this makes M much smaller
     3439   //keep only minors which are not 0 mod I (!) this is important since we
     3440   //need a nzd mod I
     3441
     3442   //---------------- choose nzd from ideal of singular locus --------------
     3443   ideal D = M[1];
     3444   for( ii=2; ii<=size(M); ii++ )            //look for the shortest one
     3445   {
     3446      if( size(M[ii]) < size(D[1]) )
     3447      {
     3448          D = M[ii];
     3449      }
     3450   }
     3451
     3452   //--------------- start p-th power algorithm and return ----------------
     3453   ideal F = var(1)^p;
     3454   for(ii=2; ii<=n; ii++)
     3455   { 
     3456      F=F,var(ii)^p;
     3457   }
     3458
     3459   ideal Dp=D^(p-1);
     3460   ideal U=1;
     3461   ideal K,L;
     3462   map phi=Q,F;
     3463   if ( y >= 1)
     3464   {  "compute module generators of integral closure";
     3465      "denominator D is:";  D; 
     3466      pause();
     3467   } 
     3468
     3469   ii=0;
     3470   list LK;
     3471   while(1)
     3472   {
     3473      ii=ii+1;
     3474      if ( y >= 1)
     3475      { "iteration", ii; }
     3476      L = U*Dp + I;             
     3477      //### L=interred(L) oder msdt(L)[2]?
     3478      //Wird dadurch kleiner aber string(L) wird groesser
     3479      K = preimage(Q,phi,L);    //### Improvement by block ordering?
     3480      option(returnSB);
     3481      K = intersect(U,K);          //K is the new U, it is a SB
     3482      LK = mstd(K);
     3483      K = LK[2];
     3484
     3485   //---------------------------- simplify output --------------------------
     3486      if(size(reduce(U,LK[1]))==0)  //previous U coincides with new U
     3487      {                             //i.e. we reached the integral closure
     3488         U=simplify(reduce(U,groebner(D)),2);
     3489         U = D,U;
     3490         poly gg = gcd(U[1],U[size(U)]);
     3491         for(ii=2; ii<=size(U)-1 ;ii++)
     3492         {
     3493            gg = gcd(gg,U[ii]);
     3494         }
     3495         for(ii=1; ii<=size(U); ii++)
     3496         {
     3497            U[ii]=U[ii]/gg;
     3498         }
     3499         U = simplify(U,6);
     3500         //if ( y >= 1)
     3501         //{ "module generators are U[i]/U[1], with U:"; U;
     3502         //  ""; pause(); }
     3503         option(set,op);
     3504         setring R;
     3505         ideal U = imap(Q,U);
     3506         return(U);
     3507      }
     3508      U=K;
     3509   }
     3510}
     3511
     3512///////////////////////////////////////////////////////////////////////////////
     3513
     3514static proc substpartSpecial(ideal endid, ideal endphi)
     3515{
     3516   //Note: newRing is of the form (R the original basering):
     3517   //char(R),(T(1..N),X(1..nvars(R))),(dp(N),...);
     3518
     3519   int ii,jj,kk;
     3520   def BAS = basering;
     3521   int n = nvars(basering);
     3522
     3523   list Le = elimpart(endid);
     3524   int q = size(Le[2]);                   //q variables have been substituted
     3525//Le;"";
     3526   if ( q == 0 )
     3527   {
     3528      ideal normap = endphi;
     3529      ideal norid = endid;
     3530      export(norid);
     3531      export(normap);
     3532      list L = BAS;
     3533      return(L);
     3534   }
     3535
     3536      list gnirlist = ringlist(basering);
     3537      endid = Le[1];
     3538//endphi;"";
     3539      for( ii=1; ii<=n; ii++)
     3540      {
     3541         if( Le[4][ii] == 0 )            //ii=index of substituted var
     3542         {
     3543            endphi = subst(endphi,var(ii),Le[5][ii]);
     3544         }
     3545      }
     3546//endphi;"";
     3547      list g2 = gnirlist[2];             //the varlist
     3548      list g3 = gnirlist[3];             //contains blocks of orderings
     3549      int n3 = size(g3); 
     3550   //----------------- first identify module ordering ------------------
     3551      if ( g3[n3][1]== "c" or g3[n3][1] == "C" )
     3552      {
     3553         list gm = g3[n3];              //last blockis module ordering
     3554         g3 = delete(g3,n3);
     3555         int m = 0;
     3556      }
     3557      else
     3558      {
     3559         list gm = g3[1];              //first block is module ordering
     3560         g3 = delete(g3,1);
     3561         int m = 1;
     3562      }
     3563   //---- delete variables which were substituted and weights  --------
     3564//gnirlist;"";
     3565      intvec V;
     3566      int n(0);
     3567      list newg2;
     3568      list newg3;
     3569      for ( ii=1; ii<=n3-1; ii++ )
     3570      {
     3571         V = V,g3[ii][2];           //copy weights for ordering in each block
     3572         if ( ii==1 )               //into one intvector
     3573         {
     3574            V = V[2..size(V)];
     3575         }
     3576        // int n(ii) = size(g3[ii][2]);
     3577        int n(ii) = size(V);
     3578        intvec V(ii);
     3579
     3580        for ( jj = n(ii-1)+1; jj<=n(ii); jj++)
     3581        {
     3582//"ii, jj", ii,jj;
     3583          if( Le[4][jj] !=0 )     //jj=index of var which was not substituted
     3584          {
     3585            kk=kk+1;
     3586            newg2[kk] = g2[jj];   //not substituted var from varlist
     3587            V(ii)=V(ii),V[jj];    //weight of not substituted variable
     3588//"V(",ii,")", V(ii);
     3589          }
     3590        }
     3591        if ( size(V(ii)) >= 2 )
     3592        {
     3593           V(ii) = V(ii)[2..size(V(ii))];
     3594           list g3(ii)=g3[ii][1],V(ii);
     3595           newg3 = insert(newg3,g3(ii),size(newg3));
     3596//"newg3"; newg3;
     3597        }
     3598      }
     3599//"newg3"; newg3;
     3600      //newg3 = delete(newg3,1);    //delete empty list
     3601     
     3602/*
     3603//### neue Ordnung, 1 Block fuer alle vars, aber Gewichte erhalten;
     3604//vorerst nicht realisiert, da bei leonhard1 alte Version (neue Variable T(i)
     3605//ein neuer Block) ein kuerzeres Ergebnis liefert
     3606      kill g3;
     3607      list g3;
     3608      V=0;
     3609      for ( ii= 1; ii<=n3-1; ii++ )
     3610      {
     3611        V=V,V(ii);
     3612      }
     3613      V = V[2..size(V)];
     3614
     3615      if ( V==1 )
     3616      {   
     3617         g3[1] = list("dp",V);
     3618      }
     3619      else
     3620      {
     3621         g3[1] = lis("wp",V);         
     3622      }
     3623      newg3 = g3;
     3624
     3625//"newg3";newg3;"";
     3626//### Ende neue Ordnung
     3627*/
     3628
     3629      if ( m == 0 )
     3630      {
     3631         newg3 = insert(newg3,gm,size(newg3));
     3632      }
     3633      else
     3634      {
     3635         newg3 = insert(newg3,gm);
     3636      }
     3637      gnirlist[2] = newg2;                   
     3638      gnirlist[3] = newg3;
     3639
     3640//gnirlist;
     3641      def newBAS = ring(gnirlist);            //change of ring to less vars
     3642      setring newBAS;
     3643      ideal normap = imap(BAS,endphi);
     3644      //normap = simplify(normap,2);
     3645      ideal norid =  imap(BAS,endid);
     3646      export(norid);
     3647      export(normap);
     3648      list L = newBAS;
     3649      return(L);
     3650
     3651   //Hier scheint interred gut zu sein, da es Ergebnis relativ schnell
     3652   //verkleinert. Hier wird z.B. bei leonard1 size(norid) verkleinert aber
     3653   //size(string(norid)) stark vergroessert, aber es hat keine Auswirkungen
     3654   //da keine map mehr folgt.
     3655   //### Bei Leonard2 haengt interred (BUG)
     3656   //mstd[2] verkleinert norid nocheinmal um die Haelfte, dauert aber 3.71 sec
     3657   //### Ev. Hinweis auf mstd in der Hilfe?
     3658
     3659}
     3660
     3661///////////////////////////////////////////////////////////////////////////////
     3662// Computes the ring structure of a ring given by module generators.
     3663// Assume: J[i]/J[1] are the module generators in the quotient field
     3664// with J[1] as universal denominator.
     3665// If option "noRed" is not given, a reduction in the number of variables is
     3666// attempted.
     3667static proc computeRing(ideal J, ideal I, list #)
     3668{
     3669  int i, ii,jj;
     3670  intvec V;                          // to be used for variable weights
     3671  int y = printlevel-voice+2;
     3672  def R = basering;
     3673  poly c = J[1];                     // the denominator
     3674  list gnirlist = ringlist(basering);
     3675  string svars = varstr(basering);
     3676  int nva = nvars(basering);
     3677  string svar;
     3678  ideal maxid = maxideal(1);
     3679 
     3680  int noRed = 0;     // By default, we try to reduce the number of generators.
     3681  if(size(#) > 0){
     3682    if ( typeof(#[1]) == "string" )
     3683    {
     3684      if (#[1] == "noRed"){noRed = 1;}
    24363685    }
    2437 
    2438   // R(1) was a copy of Rees, so we have to get back to the basering Rees from
    2439   // the beginning and fetch the result (the list preimages) to this ring.
    2440 
    2441   setring Rees;
    2442   return (fetch(R(1),preimages));
     3686  }
     3687
     3688  if ( y >= 1){"// computing the ring structure...";}
     3689   
     3690  if(c==1)
     3691  {
     3692    if( defined(norid) )  { kill norid; }
     3693    if( defined(normap) ) { kill normap; }
     3694    ideal norid = I;
     3695    ideal normap =  maxid;
     3696    export norid;
     3697    export normap;
     3698    if(noRed == 1){
     3699      setring R;
     3700      return(R);
     3701    } else {
     3702      list L = substpartSpecial(norid,normap);
     3703      def lastRing = L[1];
     3704      setring R;
     3705      return(lastRing);
     3706    }
     3707  }
     3708
     3709
     3710  //-------------- Enlarge ring by creating new variables ------------------
     3711  //check first whether variables T(i) and then whether Z(i),...,A(i) exist
     3712  //old variable names are not touched
     3713
     3714  if ( find(svars,"T(") == 0 )       
     3715  {
     3716    svar = "T";
     3717  }
     3718  else
     3719  {
     3720    for (ii=90; ii>=65; ii--) 
     3721    {
     3722      if ( find(svars,ASCII(ii)+"(") == 0 )       
     3723      {
     3724        svar = ASCII(ii);  break;
     3725      }
     3726    }
     3727  }
     3728
     3729  int q = size(J)-1;
     3730  if ( size(svar) != 0 )
     3731  {
     3732    for ( ii=q; ii>=1; ii-- )
     3733    {
     3734      gnirlist[2] = insert(gnirlist[2],svar+"("+string(ii)+")");
     3735    }
     3736  }
     3737  else
     3738  {       
     3739    for ( ii=q; ii>=1; ii-- )
     3740    {
     3741      gnirlist[2] = insert(gnirlist[2],"T("+string(100*nva+ii)+")");
     3742    }
     3743  }
     3744
     3745  V[q]=0;                        //create intvec of variable weights
     3746  V=V+1;
     3747  gnirlist[3] = insert(gnirlist[3],list("dp",V));
     3748
     3749  //this is a block ordering with one dp-block (1st block) for new vars
     3750  //the remaining weights and blocks for old vars are kept
     3751  //### perhaps better to make only one block, keeping weights ?
     3752  //this might effect syz below
     3753  //alt: ring newR = char(R),(X(1..nvars(R)),T(1..q)),dp;
     3754  //Reihenfolge geŠndert:neue Variablen kommen zuerst, Namen ev. nicht T(i)
     3755
     3756  def newR = ring(gnirlist);   
     3757  setring newR;                //new extended ring
     3758  ideal I = imap(R,I);
     3759
     3760  //------------- Compute linear and quadratic relations ---------------
     3761  if(y>=1)
     3762  {
     3763     "// compute linear relations:";
     3764  }
     3765  qring newQ = std(I);
     3766 
     3767  ideal f = imap(R,J);
     3768  module syzf = syz(f);
     3769  ideal pf = f[1]*f;               
     3770  //f[1] is the denominator D from normalityTest, a non zero divisor of R/I
     3771
     3772  ideal newT = maxideal(1);
     3773  newT = 1,newT[1..q];
     3774  //matrix T = matrix(ideal(1,T(1..q)),1,q+1);   //alt
     3775  matrix T = matrix(newT,1,q+1);
     3776  ideal Lin = ideal(T*syzf);
     3777  //Lin=interred(Lin);
     3778  //### interred reduziert ev size aber size(string(LIN)) wird groesser
     3779
     3780  if(y>=1)
     3781  {
     3782    if(y>=3)
     3783    {
     3784      "//   the linear relations:";  Lin; pause();"";
     3785    }
     3786      "// the ring structure of the normalization as affine algebra";
     3787      "//   number of linear relations:", size(Lin);
     3788  }
     3789
     3790  if(y>=1)
     3791  {
     3792    "// compute quadratic relations:";
     3793  }
     3794  matrix A;
     3795  ideal Quad;
     3796  poly ff;
     3797  newT = newT[2..size(newT)];
     3798  matrix u;  // The units for non-global orderings.
     3799
     3800  // Quadratic relations
     3801  for (ii=2; ii<=q+1; ii++ )
     3802  {
     3803    for ( jj=2; jj<=ii; jj++ )
     3804    {
     3805      ff = NF(f[ii]*f[jj],std(0));     // this makes lift much faster
     3806      // For non-global orderings, we have to take care of the units.
     3807      if(ord_test(basering) != 1){
     3808        A = lift(pf, ff, u);
     3809        Quad = Quad,ideal(newT[jj-1]*newT[ii-1] * u[1, 1]- T*A); 
     3810      } else {
     3811        A = lift(pf,ff);              // ff lin. comb. of elts of pf mod I
     3812        Quad = Quad,ideal(newT[jj-1]*newT[ii-1] - T*A);
     3813      }
     3814      //A = lift(pf, f[ii]*f[jj]);
     3815      //Quad = Quad, ideal(T(jj-1)*T(ii-1) - T*A); 
     3816    }
     3817  }
     3818  Quad = Quad[2..ncols(Quad)];
     3819
     3820  if(y>=1)
     3821  {
     3822    if(y>=3)
     3823    {
     3824      "//   the quadratic relations"; Quad; pause();"";
     3825    }
     3826      "//   number of quadratic relations:", size(Quad);
     3827  }
     3828  ideal Q1 = Lin,Quad;     //elements of Q1 are in NF w.r.t. I
     3829
     3830  //Q1 = mstd(Q1)[2];
     3831  //### weglassen, ist sehr zeitaufwendig.
     3832  //Ebenso interred, z.B. bei Leonard1 (1. Komponente von Leonard):
     3833  //"size Q1:", size(Q1), size(string(Q1));   //75 60083
     3834  //Q1 = interred(Q1);
     3835  //"size Q1:", size(Q1), size(string(Q1));   //73 231956 (!)
     3836  //### Speicherueberlauf bei substpartSpecial bei 'ideal norid  = phi1(endid)'
     3837  //Beispiel fuer Hans um map zu testen!
     3838
     3839  setring newR;
     3840  ideal endid  = imap(newQ,Q1),I;
     3841  ideal endphi = imap(R,maxid);
     3842
     3843  if(noRed == 0){   
     3844    list L=substpartSpecial(endid,endphi);
     3845    def lastRing=L[1];
     3846    if(y>=1)
     3847    {
     3848      "//   number of substituted variables:", nvars(newR)-nvars(lastRing);
     3849      pause();"";
     3850    }
     3851    return(lastRing);
     3852  } else {
     3853    ideal norid = endid;
     3854    ideal normap = endphi;
     3855    export(norid);
     3856    export(normap);
     3857    setring R;
     3858    return(newR);
     3859  }   
    24433860}
     3861
     3862//                Up to here: procedures for char p with Frobenius
     3863///////////////////////////////////////////////////////////////////////////////
     3864
     3865///////////////////////////////////////////////////////////////////////////////
     3866//                From here: subprocedures for normal
     3867
     3868static proc normalM(ideal I, int decomp, int withDelta){
     3869// Computes the normalization of a ring R / I using the module structure as far
     3870// as possible.
     3871// The ring R is the basering.
     3872// Input: ideal I
     3873// Output: a list of 3 elements (resp 4 if withDelta = 1), say nor.
     3874// - nor[1] = U, an ideal of R.
     3875// - nor[2] = c, an element of R.
     3876// U and c satisfy that 1/c * U is the normalization of R / I in the
     3877// quotient field Q(R/I).
     3878// - nor[3] = ring say T, containing two ideals norid and normap such that
     3879// normap gives the normalization map from R / I to T / norid.
     3880// - nor[4] = the delta invariant, if withDelta = 1.
     3881
     3882// Details:
     3883// --------
     3884// Computes the ideal of the minors in the first step and then reuses it in all
     3885// steps.
     3886// In step s, the denominator is D^s, where D is a nzd of the original quotient
     3887// ring, contained in the radical of the singular locus.
     3888// This denominator is used except when the degree of D^i is greater than the
     3889// degree of a conductor.
     3890// The nzd is taken as the smallest degree polynomial in the radical of the
     3891// singular locus.
     3892
     3893// It assumes that the ideal I is equidimensional radical. This is not checked
     3894// in the procedure!
     3895// If decomp = 0 or decomp = 3 it assumes further that I is prime. Therefore
     3896// any non-zero element in the jacobian ideal is assumed to be a
     3897// non-zerodivisor.
     3898
     3899// It works over the given basering.
     3900// If it has a non-global ordering, it changes it to dp global only for
     3901// computing radical.
     3902
     3903// The delta invariant is only computed if withDelta = 1, and decomp = 0 or
     3904// decomp = 3 (meaning that the ideal is prime).
     3905
     3906  option("redSB");
     3907  option("returnSB");
     3908  int step = 0;                       // Number of steps. (for debugging)
     3909  int dbg = printlevel - voice + 2;   // dbg = printlevel (default: dbg = 0)
     3910  int i;                              // counter
     3911  int isGlobal = ord_test(basering);
     3912
     3913  poly c;                     // The common denominator.
     3914
     3915  def R = basering;
     3916   
     3917  // ---------------- computation of the singular locus ---------------------
     3918  // We compute the radical of the ideal of minors modulo the original ideal.
     3919  // This is done only in the first step.
     3920
     3921  if(isGlobal == 1){
     3922    list IM = mstd(I);
     3923    I = IM[1];
     3924    ideal IMin = IM[2];   // A minimal set of generators in the groebner basis.
     3925  } else {
     3926    // The minimal set of generators is not computed by mstd for
     3927    // non-global orderings.
     3928    I = groebner(I);
     3929    ideal IMin = I;
     3930  }
     3931  int d = dim(I);
     3932 
     3933  qring Q = I;   // We work in the quotient by the groebner base of the ideal I
     3934  option("redSB");
     3935  option("returnSB");
     3936  ideal I = fetch(R, I);
     3937  attrib(I, "isSB", 1);
     3938  ideal IMin = fetch(R, IMin);
     3939
     3940  dbprint(dbg, "Computing the jacobian ideal...");
     3941  ideal J = minor(jacob(IMin), nvars(basering) - d, I);
     3942  J = groebner(J);
     3943 
     3944  // -------------------- election of the conductor -------------------------   
     3945  poly condu = getSmallest(J);   // Choses the polynomial of smallest degree
     3946                                 // of J as universal denominator.
     3947  if(dbg >= 1){
     3948    "";
     3949    "The universal denominator is ", condu;
     3950  }
     3951
     3952  // ---------  splitting the ideal by the conductor (if possible) -----------
     3953  // If the ideal is equidimensional, but not necessarily prime, we check if
     3954  // the conductor is a non-zerodivisor of R/I.
     3955  // If not, we split I.
     3956  if((decomp == 1) or (decomp == 2)){ 
     3957    ideal Id1 = quotient(0, condu);
     3958    if(size(Id1) > 0){
     3959      // We have to split.
     3960      if(dbg >= 1){
     3961        "A zerodivisor was found. We split the ideal. The zerodivisor is ", condu;
     3962      }
     3963      setring R;
     3964      ideal Id1 = fetch(Q, Id1), I;
     3965      Id1 = groebner(Id1);
     3966      ideal Id2 = quotient(I, Id1);
     3967      // I = I1 \cap I2
     3968      printlevel = printlevel + 1;
     3969      list nor1 = normalM(Id1, decomp, withDelta)[1];
     3970      list nor2 = normalM(Id2, decomp, withDelta)[1];
     3971      printlevel = printlevel - 1;   
     3972      return(list(nor1, nor2));
     3973    }
     3974  }
     3975
     3976  // --------------- computation of the first test ideal ---------------------   
     3977  // To compute the radical we go back to the original ring.
     3978  // If we are using a non-global ordering, we must change to the global
     3979  // ordering.
     3980  if(isGlobal == 1){
     3981    setring R;
     3982    ideal J = fetch(Q, J);
     3983    J = J, I;
     3984    if(dbg >= 1){
     3985      "The original singular locus is";
     3986      groebner(J);
     3987      if(dbg >= 2){pause();}
     3988       "";
     3989    }
     3990    J = radical(J);
     3991  } else {
     3992    // We change to global dp ordering.
     3993    list rl = ringlist(R);
     3994    list origOrd = rl[3];
     3995    list newOrd = list("dp", intvec(1:nvars(R))), list("C", 0);
     3996    rl[3] = newOrd;
     3997    def globR = ring(rl);
     3998    setring globR;
     3999    ideal J = fetch(Q, J);
     4000    ideal I = fetch(R, I);
     4001    J = J, I;
     4002    if(dbg >= 1){
     4003      "The original singular locus is";
     4004      groebner(J);
     4005      if(dbg>=2){pause();}
     4006      "";
     4007    }
     4008    J = radical(J);
     4009    setring R;
     4010    ideal J = fetch(globR, J);
     4011  }
     4012   
     4013  if(dbg >= 1){
     4014    "The radical of the original singular locus is";
     4015    J;
     4016    if(dbg>=2){pause();}
     4017  }
     4018
     4019  // ---------------- election of the non zero divisor ---------------------
     4020  setring Q;
     4021  J = fetch(R, J);
     4022  J = interred(J);         
     4023  poly D = getSmallest(J);    // Chooses the poly of smallest degree as
     4024                              // non-zerodivisor.
     4025  if(dbg >= 1){
     4026    "The non zero divisor is ", D;
     4027    "";
     4028  }
     4029
     4030  // ------- splitting the ideal by the non-zerodivisor (if possible) --------   
     4031  // If the ideal is equidimensional, but not necessarily prime, we check if D
     4032  // is actually a non-zerodivisor of R/I.
     4033  // If not, we split I.
     4034  if((decomp == 1) or (decomp == 2)){ 
     4035    // We check if D is actually a non-zerodivisor of R/I.
     4036    // If not, we split I.
     4037    Id1 = quotient(0, D);
     4038    if(size(Id1) > 0){
     4039      // We have to split.
     4040      if(dbg >= 1){
     4041        "A zerodivisor was found. We split the ideal. The zerodivisor is ", D;
     4042      }   
     4043      setring R;
     4044      ideal Id1 = fetch(Q, Id1), I;
     4045      Id1 = groebner(Id1);
     4046      ideal I2 = quotient(I, Id1);
     4047      // I = Id1 \cap Id2
     4048      printlevel = printlevel + 1;
     4049      list nor1 = normalM(Id1, decomp, withDelta)[1];
     4050      list nor2 = normalM(Id2, decomp, withDelta)[1];
     4051      printlevel = printlevel - 1;   
     4052      return(list(nor1, nor2));   
     4053    }
     4054  }
     4055
     4056  // --------------------- normalization ------------------------------------
     4057  // We call normalMEqui to compute the normalization.
     4058  setring R;
     4059  poly D = fetch(Q, D);
     4060  poly condu = fetch(Q, condu);
     4061  J = fetch(Q, J);
     4062  printlevel = printlevel + 1;
     4063  list result = normalMEqui(I, J, condu, D, withDelta);
     4064  printlevel = printlevel - 1;
     4065  return(list(result));
     4066}
     4067
     4068///////////////////////////////////////////////////////////////////////////////
     4069 
     4070static proc normalMEqui(ideal I, ideal origJ, poly condu, poly D, int withDelta)
     4071// Here is where the normalization is actually computed.
     4072
     4073// Computes the normalization of R/I. (basering is R)
     4074// I is assumed to be radical and equidimensional.
     4075// origJ is the first test ideal.
     4076// D is a non-zerodivisor of R/I.
     4077// condu is a non-zerodivisor in the conductor.
     4078// If withDelta = 1, computes the delta invariant.
     4079{
     4080  int step = 0;                       // Number of steps. (for debugging)
     4081  int dbg = printlevel - voice + 2;   // dbg = printlevel (default: dbg = 0)
     4082  int i;                              // counter
     4083  int isNormal = 0;                   // check for exiting the loop
     4084  int isGlobal = ord_test(basering);
     4085  int delt;
     4086 
     4087  def R = basering;
     4088  poly c = D;
     4089  ideal U;
     4090  ideal cJ;
     4091  list testOut;                 // Output of proc testIdeal
     4092                                // (the test ideal and the ring structure)
     4093   
     4094  qring Q = groebner(I);
     4095  option("redSB");
     4096  option("returnSB"); 
     4097  ideal J = imap(R, origJ);
     4098  poly c = imap(R, c);
     4099  poly D = imap(R, D);
     4100  poly condu = imap(R, condu);
     4101  ideal cJ;
     4102  ideal cJMod;
     4103
     4104  dbprint(dbg, "Preliminar step begins.");
     4105
     4106  // --------------------- computation of A1 -------------------------------
     4107  dbprint(dbg, "Computing the quotient (DJ : J)...");
     4108  ideal U = groebner(quotient(D*J, J)); 
     4109  ideal oldU = 1;
     4110
     4111  if(dbg >= 2){
     4112    "The quotient is"; U;
     4113  }
     4114
     4115  // ----------------- Grauer-Remmert criterion check -----------------------
     4116  // We check if the equality in Grauert - Remmert criterion is satisfied.
     4117  isNormal = checkInclusions(D*oldU, U);
     4118  if(isNormal == 0){
     4119    if(dbg >= 1){
     4120      "In this step, we have the ring 1/c * U, with c =", c;
     4121      "and U = "; U;
     4122    }
     4123  } else {       
     4124    // The original ring R/I was normal. Nothing to do.
     4125    // We define anyway a new ring, equal to R, to be able to return it.
     4126    setring R;
     4127    list lR = ringlist(R);
     4128    def ROut = ring(lR);
     4129    setring ROut;
     4130    ideal norid = 0;
     4131    ideal normap = maxideal(1);
     4132    export norid;
     4133    export normap;
     4134    setring R;
     4135    if(withDelta){
     4136      list output = ideal(1), poly(1), ROut, 0;
     4137    } else {
     4138      list output = ideal(1), poly(1), ROut;
     4139    }
     4140    return(output);
     4141  }
     4142
     4143  // ----- computation of the chain of ideals A1 c A2 c ... c An ------------
     4144  while(isNormal == 0){
     4145    step++;
     4146    if(dbg >= 1){
     4147      "";
     4148      "Step ", step, " begins.";
     4149    }
     4150    dbprint(dbg, "Computing the test ideal...");
     4151   
     4152    // --------------- computation of the test ideal ------------------------
     4153    // Computes a test ideal for the new ring.
     4154    // The test ideal will be the radical in the new ring of the original
     4155    // test ideal.
     4156    setring R;
     4157    U = imap(Q, U);
     4158    c = imap(Q, c);
     4159    testOut = testIdeal(I, U, origJ, c, D);
     4160    cJ = testOut[1];
     4161   
     4162    setring Q;
     4163    cJ = imap(R, cJ);
     4164    cJ = groebner(cJ);
     4165   
     4166    // cJ / c is now the ideal mapped back.
     4167    // We have the generators as an ideal in the new ring,
     4168    // but we want the generators as an ideal in the original ring.
     4169    cJMod = getGenerators(cJ, U, c);
     4170
     4171    if(dbg >= 2){
     4172      "The test ideal in this step is ";
     4173      cJMod;
     4174    }
     4175   
     4176    cJ = cJMod;
     4177
     4178    // ------------- computation of the quotient (DJ : J)--------------------
     4179    oldU = U;
     4180    dbprint(dbg, "Computing the quotient (c*D*cJ : cJ)...");
     4181    U = quotient(c*D*cJ, cJ);
     4182    if(dbg >= 2){"The quotient is "; U;}
     4183
     4184    // ------------- Grauert - Remmert criterion check ----------------------
     4185    // We check if the equality in Grauert - Remmert criterion is satisfied.
     4186    isNormal = checkInclusions(D*oldU, U);
     4187
     4188    if(isNormal == 1){       
     4189      // We go one step back. In the last step we didnt get antyhing new,
     4190      // we just verified that the ring was already normal.
     4191      dbprint(dbg, "The ring in the previous step was already normal.");
     4192      dbprint(dbg, "");
     4193      U = oldU;
     4194    } else {
     4195      // ------------- preparation for next iteration ----------------------
     4196      // We have to go on.
     4197      // The new denominator is chosen.
     4198      c = D * c;
     4199      if(deg(c) > deg(condu)){
     4200        U = changeDenominatorQ(U, c, condu);
     4201        c = condu;
     4202      }
     4203      if(dbg >= 1){
     4204        "In this step, we have the ring 1/c * U, with c =", c;
     4205        "and U = ";
     4206        U;
     4207        if(dbg>=2){pause();}
     4208      }
     4209    }
     4210  }
     4211
     4212  // ------------------------- delta computation ----------------------------
     4213  if(withDelta){
     4214    ideal UD = groebner(U);
     4215    delt = vdim(std(modulo(UD, c)));
     4216  }
     4217 
     4218  // -------------------------- prepare output -----------------------------   
     4219  setring R;
     4220  U = fetch(Q, U);
     4221  c = fetch(Q, c);
     4222
     4223  // Ring structure of the new ring
     4224  def ere = testOut[2];
     4225  if(withDelta){
     4226    list output = U, c, ere, delt;
     4227  } else {
     4228    list output = U, c, ere;
     4229  }
     4230  return(output);
     4231 
     4232}
     4233
     4234///////////////////////////////////////////////////////////////////////////////
     4235
     4236static proc lineUp(ideal U, poly c)
     4237// Sets c as the first generator of U.
     4238{
     4239  int i;
     4240  ideal newU = c;
     4241  for (i = 1; i <= ncols(U); i++){
     4242    if(U[i] != c){
     4243      newU = newU, U[i];
     4244    }
     4245  }
     4246  return(newU);
     4247}
     4248
     4249///////////////////////////////////////////////////////////////////////////////
     4250
     4251static proc getSmallest(ideal J){
     4252// Computes the polynomial of smallest degree of J.
     4253// If there are more than one, it chooses the one with smallest number
     4254// of monomials.
     4255  int i;
     4256  poly p = J[1];
     4257  int d = deg(p);
     4258  int di;
     4259  for(i = 2; i <= ncols(J); i++){
     4260    if(J[i] != 0){
     4261      di = deg(J[i]);
     4262      if(di < d){
     4263        p = J[i];
     4264        d = di;
     4265      } else {
     4266        if(di == d){
     4267          if(size(J[i]) < size(p)){
     4268            p = J[i];
     4269          }
     4270        }
     4271      }
     4272    }
     4273  }
     4274  return(p);
     4275}
     4276
     4277///////////////////////////////////////////////////////////////////////////////
     4278
     4279static proc getGenerators(ideal J, ideal U, poly c){
     4280// Computes the generators of J as an ideal in the original ring,
     4281// where J is given by generators in the new ring.
     4282
     4283// The new ring is given by 1/c * U in the total ring of fractions.
     4284
     4285  int i, j;                             // counters;
     4286  int dbg = printlevel - voice + 2;     // dbg = printlevel (default: dbg = 0) 
     4287  poly p;                               // The lifted polynomial
     4288  ideal JGr = groebner(J);              // Groebner base of J
     4289
     4290  if(dbg>1){"Checking for new generators...";}
     4291  for(i = 1; i <= ncols(J); i++){
     4292    for(j = 1; j <= ncols(U); j++){
     4293      p = lift(c, J[i]*U[j])[1,1];
     4294      p = reduce(p, JGr);
     4295      if(p != 0){
     4296        if(dbg>1){
     4297          "New polynoial added:", p;
     4298          if(dbg>4){pause();}
     4299        }
     4300        JGr = JGr, p;
     4301        JGr = groebner(JGr);
     4302        J = J, p;
     4303      }
     4304    }
     4305  }
     4306  return(J);
     4307}
     4308
     4309///////////////////////////////////////////////////////////////////////////////
     4310
     4311static proc testIdeal(ideal I, ideal U, ideal origJ, poly c, poly D){
     4312// Internal procedure, used in normalM.
     4313// Computes the test ideal in the new ring.
     4314// It takes the original test ideal and computes the radical of it in the
     4315// new ring.
     4316
     4317// The new ring is 1/c * U.
     4318// The original test ideal is origJ.
     4319// The original ring is R / I, where R is the basering.
     4320  int i;                                // counter
     4321  int dbg = printlevel - voice + 2;     // dbg = printlevel (default: dbg = 0) 
     4322  def R = basering;                      // We dont work in the quo
     4323  ideal J = origJ;
     4324 
     4325  // ---------- computation of the ring structure of 1/c * U ----------------
     4326  U = lineUp(U, c);
     4327 
     4328  if(dbg > 1){"Computing the new ring structure...";}
     4329  list ele = computeRing(U, I, "noRed");
     4330
     4331  def origEre = ele[1];
     4332  setring origEre;
     4333  if(dbg > 1){"The relations are"; norid;}
     4334
     4335  // ---------------- setting the ring to work in  -------------------------- 
     4336  int isGlobal = ord_test(origEre);      // Checks if the original ring has
     4337                                         // global ordering.
     4338  if(isGlobal != 1){
     4339    list rl = ringlist(origEre);
     4340    list origOrd = rl[3];
     4341    list newOrd = list("dp", intvec(1:nvars(origEre))), list("C", 0);
     4342    rl[3] = newOrd;
     4343    def ere = ring(rl);     // globR is the original ring but
     4344                            // with a global ordering.
     4345    setring ere;
     4346    ideal norid = imap(origEre, norid);
     4347  } else {
     4348    def ere = origEre;
     4349  }
     4350
     4351  ideal I = imap(R, I);
     4352  ideal J = imap(R, J);
     4353  J = J, norid, I;
     4354
     4355
     4356  // ----- computation of the test ideal using the ring structure of Ai ----- 
     4357  option("redSB");
     4358  option("returnSB");
     4359
     4360  if(dbg > 1){"Computing the radical of J...";}
     4361  J = radical(J);
     4362  if(dbg > 1){"Computing the interreduction of the radical...";}
     4363  J = groebner(J); 
     4364  //J = interred(J);
     4365  if(dbg > 1){
     4366    "The radical in the generated ring is";
     4367    J;
     4368    if(dbg>4){pause();}
     4369  }
     4370 
     4371  setring ere;
     4372 
     4373  // -------------- map from Ai to the total ring of fractions --------------- 
     4374  // Now we must map back this ideal J to U_i / c in the total ring of
     4375  // fractions.
     4376  // The map sends T_j -> u_j / c.
     4377  // The map is built by the following steps:
     4378  // 1) We compute the degree of the generators of J with respect to the
     4379  //    new variables T_j.
     4380  // 2) For each generator, we multiply each term by a power of c, as if
     4381  //    taking c^n as a common denominator (considering the new variables as
     4382  //    a polynomial in the old variables divided by c).
     4383  // 3) We replace the new variables T_j by the corresponding numerator u_j.
     4384  // 4) We lift the resulting polynomial to change the denominator
     4385  //    from c^n to c.
     4386  int nNewVars = nvars(ere) - nvars(R);      // Number of new variables
     4387  poly c = imap(R, c);
     4388  intvec @v = 1..nNewVars;    // Vector of the new variables.
     4389                              // They must be the first ones.
     4390  if(dbg > 1){"The indices of the new variables are", @v;}
     4391
     4392  // ---------------------- step 1 of the mapping --------------------------- 
     4393  intvec degs;
     4394  for(i = 1; i<=ncols(J); i++){
     4395    degs[i] = degSubring(J[i], @v);
     4396  }
     4397  if(dbg > 1){
     4398    "The degrees with respect to the new variables are";
     4399    degs;
     4400  }
     4401 
     4402  // ---------------------- step 2 of the mapping ---------------------------   
     4403  ideal mapJ = mapBackIdeal(J, c, @v);
     4404 
     4405  setring R;
     4406
     4407  // ---------------------- step 3 of the mapping --------------------------- 
     4408  ideal z;                    // The variables of the original ring in order.
     4409  for(i = 1; i<=nvars(R); i++){
     4410    z[i] = var(i);
     4411  }
     4412     
     4413  map f = ere, U[2..ncols(U)], z[1..ncols(z)]; // The map to the original ring.
     4414  if(dbg > 1){
     4415    "The map is ";
     4416    f;
     4417    if(dbg>4){pause();}
     4418  }
     4419 
     4420  if(dbg > 1){
     4421    "Computing the map...";
     4422  }
     4423     
     4424  J = f(mapJ);
     4425  if(dbg > 1){
     4426    "The ideal J mapped back (before lifting) is";
     4427    J;
     4428    if(dbg>4){pause();}
     4429  }
     4430
     4431  // ---------------------- step 4 of the mapping ---------------------------   
     4432  qring Q = groebner(I);
     4433  ideal J = imap(R, J);
     4434  poly c = imap(R, c);
     4435  for(i = 1; i<=ncols(J); i++){
     4436    if(degs[i]>1){
     4437      J[i] = lift(c^(degs[i]-1), J[i])[1,1];
     4438    } else {
     4439      if(degs[i]==0){
     4440        J[i] = c*J[i];
     4441      }
     4442    }
     4443  }
     4444
     4445  if(dbg > 1){
     4446    "The ideal J lifted is";
     4447    J;
     4448    if(dbg>4){pause();}
     4449  }
     4450
     4451  // --------------------------- prepare output ----------------------------   
     4452  J = groebner(J);
     4453 
     4454  setring R;
     4455  J = imap(Q, J);
     4456 
     4457  return(list(J, ele[1]));
     4458}
     4459
     4460///////////////////////////////////////////////////////////////////////////////
     4461
     4462static proc changeDenominator(ideal U1, poly c1, poly c2, ideal I){
     4463// Given a ring in the form 1/c1 * U, it computes a new ideal U2 such that the
     4464// ring is 1/c2 * U2.
     4465// The base ring is R, but the computations are to be done in R / I.
     4466  int a;      // counter
     4467  def R = basering;
     4468  qring Q = I;
     4469  ideal U1 = fetch(R, U1);
     4470  poly c1 = fetch(R, c1);
     4471  poly c2 = fetch(R, c2);
     4472  ideal U2 = changeDenominatorQ(U1, c1, c2);
     4473  setring R;
     4474  ideal U2 = fetch(Q, U2);
     4475  return(U2);
     4476}
     4477
     4478///////////////////////////////////////////////////////////////////////////////
     4479
     4480static proc changeDenominatorQ(ideal U1, poly c1, poly c2){
     4481// Given a ring in the form 1/c1 * U, it computes a new U2 st the ring
     4482// is 1/c2 * U2.
     4483// The base ring is already a quotient ring R / I.
     4484  int a;      // counter
     4485  ideal U2;
     4486  poly p;
     4487  for(a = 1; a <= ncols(U1); a++){
     4488    p = lift(c1, c2*U1[a])[1,1];
     4489    U2[a] = p;
     4490  }
     4491  return(U2);
     4492}
     4493
     4494///////////////////////////////////////////////////////////////////////////////
     4495
     4496static proc checkInclusions(ideal U1, ideal U2){
     4497// Checks if the identity A = Hom(J, J) of Grauert-Remmert criterion is
     4498// satisfied.
     4499  int dbg = printlevel - voice + 2;     // dbg = printlevel (default: dbg = 0)
     4500  list reduction1;
     4501  list reduction2;
     4502 
     4503  // ---------------------- inclusion Hom(J, J) c A ------------------------- 
     4504  if(dbg > 1){"Checking the inclusion Hom(J, J) c A:";}
     4505  // This interred is used only because a bug in groebner!
     4506  U1 = groebner(U1);
     4507  reduction1 = reduce(U2, U1);
     4508  if(dbg > 1){reduction1[1];}
     4509
     4510  // ---------------------- inclusion A c Hom(J, J) ------------------------- 
     4511  // The following check should always be satisfied.
     4512  // This is only used for debugging.
     4513  if(dbg > 1){
     4514    "and the inclusion A c Hom(J, J): (this should always be satisfied)";
     4515    // This interred is used only because a bug in groebner!
     4516    U2 = groebner(U2);
     4517    reduction2 = reduce(U1, groebner(U2));
     4518    reduction2[1];
     4519    if(size(reduction2[1]) > 0){
     4520      "Something went wrong... (this inclusion should always be satisfied)";
     4521      ~;
     4522    } else {
     4523      if(dbg>4){pause();}
     4524    }
     4525  }
     4526 
     4527  if(size(reduction1[1]) == 0){
     4528    // We are done! The ring computed in the last step was normal.
     4529    return(1);
     4530  } else {
     4531    return(0);
     4532  }
     4533}
     4534
     4535///////////////////////////////////////////////////////////////////////////////
     4536
     4537static proc degSubring(poly p, intvec @v){
     4538// Computes the degree of a polynomial taking only some variables as variables
     4539// and the others as parameters.
     4540
     4541// The degree is taken wrt the variables indicated in v.
     4542  int i;      // Counter
     4543  int d = 0;  // The degree
     4544  int e;      // Degree (auxiliar variable)
     4545  for(i = 1; i <= size(p); i++){
     4546    e = sum(leadexp(p[i]), @v);
     4547    if(e > d){d = e;}
     4548  }
     4549  return(d);
     4550}
     4551   
     4552///////////////////////////////////////////////////////////////////////////////
     4553
     4554static proc mapBackIdeal(ideal I, poly c, intvec @v){
     4555// Modifies all polynomials in I so that a map x(i) -> y(i)/c can be
     4556// carried out.
     4557
     4558// v indicates wicih variables x(i) of the ring will be mapped to y(i)/c.
     4559
     4560  int i;  // counter
     4561  for(i = 1; i <= ncols(I); i++){
     4562    I[i] = mapBackPoly(I[i], c, @v);
     4563  }
     4564  return(I);
     4565}
     4566
     4567///////////////////////////////////////////////////////////////////////////////
     4568
     4569static proc mapBackPoly(poly p, poly c, intvec @v){
     4570// Multiplies each monomial of p by a power of c so that a map x(i) -> y(i)/c
     4571// can be carried out.
     4572
     4573// v indicates wicih variables x(i) of the ring will be mapped to y(i)/c.
     4574  int i;  // counter
     4575  int e;  // exponent
     4576  int d = degSubring(p, @v);
     4577  poly g = 0;
     4578  for(i = 1; i <= size(p); i++){
     4579    e = sum(leadexp(p[i]), @v);
     4580    g = g + p[i] * c^(d-e);
     4581  }
     4582  return(g);
     4583}
     4584
     4585//                Up to here: procedures for normal
     4586///////////////////////////////////////////////////////////////////////////////
     4587
     4588
     4589///////////////////////////////////////////////////////////////////////////////
     4590//                From here: procedures for normalC
     4591
     4592// We first define resp. copy some attributes to be used in proc normal and
     4593// static proc normalizationPrimes, and ..., to speed up computation in
     4594// special cases
     4595//NOTE:  We use the following attributes:
     4596// 1     attrib(id,"isCohenMacaulay");         //--- Cohen Macaulay
     4597// 2     attrib(id,"isCompleteIntersection");  //--- complete intersection 
     4598// 3     attrib(id,"isHypersurface");          //--- hypersurface
     4599// 4     attrib(id,"isEquidimensional");       //--- equidimensional ideal
     4600// 5     attrib(id,"isPrim");                  //--- prime ideal
     4601// 6     attrib(id,"isRegInCodim2");           //--- regular in codimension 2
     4602// 7     attrib(id,"isIsolatedSingularity");   //--- isolated singularities
     4603// 8     attrib(id,"onlySingularAtZero");      //--- only singular at 0
     4604// 9     attrib(id,"isRadical");               //--- radical ideal
     4605//Recall: (attrib(id,"xy"),1) sets attrib xy to TRUE and
     4606//        (attrib(id,"xy"),0) to FALSE
     4607
     4608static proc getAttrib (ideal id)
     4609"USAGE:   getAttrib(id);  id=ideal
     4610COMPUTE: check attributes for id. If the attributes above are defined,
     4611         take its value, otherwise define it and set it to 0
     4612RETURN:  intvec of size 9, with entries 0 or 1,  values of attributes defined
     4613         above (in this order)
     4614EXAMPLE: no example
     4615"
     4616{
     4617  int isCoM,isCoI,isHy,isEq,isPr,isReg,isIso,oSAZ,isRad;
     4618
     4619  if( typeof(attrib(id,"isCohenMacaulay"))=="int" )   
     4620  {
     4621    if( attrib(id,"isCohenMacaulay")==1 )
     4622    { isCoM=1; isEq=1; }
     4623  }
     4624
     4625  if( typeof(attrib(id,"isCompleteIntersection"))=="int" )
     4626  {
     4627    if(attrib(id,"isCompleteIntersection")==1)
     4628    { isCoI=1; isCoM=1; isEq=1; }
     4629  }
     4630   
     4631  if( typeof(attrib(id,"isHypersurface"))=="int" )
     4632  {
     4633    if(attrib(id,"isHypersurface")==1)
     4634    { isHy=1; isCoI=1; isCoM=1; isEq=1; }
     4635  }
     4636   
     4637  if( typeof(attrib(id,"isEquidimensional"))=="int" )
     4638  {
     4639    if(attrib(id,"isEquidimensional")==1)
     4640    { isEq=1; }
     4641  }
     4642   
     4643  if( typeof(attrib(id,"isPrim"))=="int" )
     4644  {
     4645    if(attrib(id,"isPrim")==1) 
     4646    { isPr=1; }
     4647  }
     4648
     4649  if( typeof(attrib(id,"isRegInCodim2"))=="int" )
     4650  {
     4651    if(attrib(id,"isRegInCodim2")==1) 
     4652    { isReg=1; }
     4653  }
     4654   
     4655  if( typeof(attrib(id,"isIsolatedSingularity"))=="int" )
     4656  {
     4657    if(attrib(id,"isIsolatedSingularity")==1) 
     4658    { isIso=1; }
     4659  }
     4660 
     4661  if( typeof(attrib(id,"onlySingularAtZero"))=="int" )
     4662  {
     4663    if(attrib(id,"onlySingularAtZero")==1)
     4664    { oSAZ=1; }
     4665  }
     4666
     4667  if( typeof(attrib(id,"isRad"))=="int" )
     4668  {
     4669    if(attrib(id,"isRad")==1) 
     4670    { isRad=1; }
     4671  }
     4672
     4673  intvec atr = isCoM,isCoI,isHy,isEq,isPr,isReg,isIso,oSAZ,isRad;
     4674  return(atr);
     4675}
     4676
     4677///////////////////////////////////////////////////////////////////////////////
     4678
     4679static proc setAttrib (ideal id, intvec atr)
     4680"USAGE:   setAttrib(id,atr);  id ideal, atr intvec
     4681COMPUTE: set attributes to id specified by atr
     4682RETURN:  id, with assigned attributes from atr
     4683EXAMPLE: no example
     4684"
     4685{
     4686  attrib(id,"isCohenMacaulay",atr[1]);         //--- Cohen Macaulay
     4687  attrib(id,"isCompleteIntersection",atr[2]);  //--- complete intersection 
     4688  attrib(id,"isHypersurface",atr[3]);          //--- hypersurface
     4689  attrib(id,"isEquidimensional",atr[4]);       //--- equidimensional ideal
     4690  attrib(id,"isPrim",atr[5]);                  //--- prime ideal
     4691  attrib(id,"isRegInCodim2",atr[6]);           //--- regular in codimension 2
     4692  attrib(id,"isIsolatedSingularity",atr[7]);   //--- isolated singularities
     4693  attrib(id,"onlySingularAtZero",atr[8]);      //--- only singular at 0
     4694  attrib(id,"isRadical",atr[9]);               //--- radical ideal
     4695
     4696  return(id);
     4697}
     4698
     4699///////////////////////////////////////////////////////////////////////////////
     4700// copyAttribs is not used anywhere so far
     4701
     4702static proc copyAttribs (ideal id1, ideal id)
     4703"USAGE:   copyAttribs(id1,id);  id1, id ideals
     4704COMPUTE: copy attributes from id1 to id
     4705RETURN:  id, with assigned attributes from id1
     4706EXAMPLE: no example
     4707"
     4708{
     4709  if( typeof(attrib(id1,"isCohenMacaulay"))=="int" )   
     4710  {
     4711    if( attrib(id1,"isCohenMacaulay")==1 )
     4712    {
     4713      attrib(id,"isEquidimensional",1);
     4714    }
     4715  }
     4716  else
     4717  {
     4718    attrib(id,"isCohenMacaulay",0);
     4719  } 
     4720
     4721  if( typeof(attrib(id1,"isCompleteIntersection"))=="int" )
     4722  {
     4723    if(attrib(id1,"isCompleteIntersection")==1)
     4724    {
     4725      attrib(id,"isCohenMacaulay",1);
     4726      attrib(id,"isEquidimensional",1);
     4727    }
     4728  }
     4729  else
     4730  {
     4731    attrib(id,"isCompleteIntersection",0);
     4732  }
     4733   
     4734  if( typeof(attrib(id1,"isHypersurface"))=="int" )
     4735  {
     4736    if(attrib(id1,"isHypersurface")==1)
     4737    {
     4738      attrib(id,"isCompleteIntersection",1);
     4739      attrib(id,"isCohenMacaulay",1);
     4740      attrib(id,"isEquidimensional",1);
     4741    }
     4742  }
     4743  else
     4744  {
     4745    attrib(id,"isHypersurface",0);
     4746  }
     4747   
     4748  if( (typeof(attrib(id1,"isEquidimensional"))=="int") )
     4749  {
     4750    if(attrib(id1,"isEquidimensional")==1)
     4751    {
     4752      attrib(id,"isEquidimensional",1);
     4753    }
     4754  }
     4755  else
     4756  {
     4757    attrib(id,"isEquidimensional",0);
     4758  }
     4759
     4760  if( typeof(attrib(id1,"isPrim"))=="int" )
     4761  {
     4762    if(attrib(id1,"isPrim")==1)
     4763    {
     4764      attrib(id,"isEquidimensional",1);
     4765    }
     4766  }
     4767  else
     4768  {
     4769    attrib(id,"isPrim",0);
     4770  }
     4771   
     4772  if( (typeof(attrib(id1,"isRegInCodim2"))=="int") )
     4773  {
     4774    if(attrib(id1,"isRegInCodim2")==1)
     4775    {
     4776      attrib(id,"isRegInCodim2",1);
     4777    }
     4778  }
     4779  else
     4780  {
     4781    attrib(id,"isRegInCodim2",0);
     4782  }
     4783   
     4784  if( (typeof(attrib(id1,"isIsolatedSingularity"))=="int") )
     4785  {
     4786    if(attrib(id1,"isIsolatedSingularity")==1)
     4787    {
     4788      attrib(id,"isIsolatedSingularity",1);
     4789    }
     4790  }
     4791  else
     4792  {
     4793    attrib(id,"isIsolatedSingularity",0);
     4794  }
     4795 
     4796  if( typeof(attrib(id1,"onlySingularAtZero"))=="int" )
     4797  {
     4798    if(attrib(id1,"onlySingularAtZero")==1)
     4799    {
     4800      attrib(id,"isIsolatedSingularity",1);
     4801    }
     4802  }
     4803  else
     4804  {
     4805    attrib(id,"onlySingularAtZero",0);
     4806  }
     4807
     4808  if( typeof(attrib(id1,"isRad"))=="int" )
     4809  {
     4810    if(attrib(id1,"isRad")==1) 
     4811    {
     4812      attrib(id,"isRad",1);
     4813    }
     4814  }
     4815  else
     4816  {
     4817    attrib(id,"isRad",0);
     4818  }
     4819
     4820  return(id);
     4821}
     4822
     4823proc normalC(ideal id, list #)
     4824"USAGE:   normalC(id [,choose]);  id = radical ideal, choose = optional string
     4825         which may be a combination of \"equidim\", \"prim\", \"withGens\",
     4826         \"isPrim\", \"noFac\".@*
     4827         If choose is not given or empty, a default method is choosen@*
     4828         If choose = \"prim\" resp. \"equidim\" normalC computes a prime resp.
     4829         an equidimensional decomposition and then the normalization of each
     4830         component; if choose = \"noFac\" factorization is avoided in the
     4831         computation of the minimal associated primes; @*
     4832         if choose = \"withGens\" the minimal associated primes P_i of id are
     4833         computed and for each P_i, algebra generators of the integral closure
     4834         of basering/P_i are computed as elements of its quotient field;@*
     4835         \"isPrim\" disables \"equidim\" and \"prim\".@*
     4836ASSUME:  The ideal must be radical, for non-radical ideals the output may
     4837         be wrong (id=radical(id); makes id radical). However, if choose =
     4838         \"prim\" the minimal associated primes of id are computed first
     4839         and hence normalC computes the normalization of the radical of id.
     4840         \"isPrim\" should only be used if id is known to be irreducible.
     4841RETURN:  a list, say nor, of size 2 (resp. 3 if choose=\"withGens\").
     4842         The first list nor[1] consists of r rings, where r is the number
     4843         of irreducible components if choose = \"prim\" (resp. >= no of
     4844         equidimenensional components if choose =  \"equidim\").
     4845@format
     4846         Each ring Ri=nor[1][i], i=1..r, contains two ideals with given
     4847         names @code{norid} and @code{normap} such that @*
     4848         - Ri/norid is the normalization of the i-th component, i.e. the
     4849          integral closure in its field of fractions (as affine ring);
     4850         - the direct sum of the rings Ri/norid is the normalization
     4851           of basering/id; @*
     4852         - @code{normap} gives the normalization map from basering/id to
     4853           Ri/norid for each j.@*
     4854
     4855         If choose=\"withGens\", nor[2] is a list of size r of ideals Ii=
     4856         nor[2][i] in the basering, generating the integral closure of
     4857         basering/P_i in its quotient field, i=1..r, in two different ways:
     4858         - Ii is given by polynomials
     4859           g_1,...,g_k,g_k+1 such that the variables T(j) of the ring Ri
     4860           satisfy T(1)=g_1/g_k+1,..,T(k)=g_k/g_k+1. Hence the g_j/g_k+1
     4861           are algebra generators of the integral closure of basering/P_i
     4862           as sub-algebra in the quotient field of basering/P_i.
     4863 
     4864         nor[2] (resp. nor[3] if choose=\"withGens\") is a list of an intvec
     4865         of size r, the delta invariants of the r components, and an integer,
     4866         the total delta invariant of basering/id (-1 means infinite, and 0
     4867         that basering/P_i resp. basering/input is normal).
     4868         Return value -2 means that delta resp. delta of one of the components
     4869         is not computed (which may happen if \"equidim\" is given) .
     4870@end format
     4871THEORY:  The delta invariant of a reduced ring K[x1,...,xn]/id is
     4872             dim_K(normalization(K[x1,...,xn]/id) / K[x1,...,xn]/id)
     4873         We call this number also the delta invariant of id.
     4874         We use the algorithm described in [G.-M. Greuel, G. Pfister:
     4875         A SINGULAR Introduction to Commutative Algebra, 2nd Edition.
     4876         Springer Verlag (2007)].
     4877NOTE:    To use the i-th ring type: @code{def R=nor[1][i]; setring R;}.
     4878@*       Increasing/decreasing printlevel displays more/less comments
     4879         (default: printlevel=0).
     4880@*       Not implemented for local or mixed orderings and for quotient rings.
     4881@*       If the input ideal id is weighted homogeneous a weighted ordering may
     4882         be used (qhweight(id); computes weights).
     4883KEYWORDS: normalization; integral closure; delta invariant.
     4884EXAMPLE: example normalC; shows an example
     4885"
     4886
     4887   int i,j, wgens, withEqui, withPrim, isPrim, nfac;
     4888   int y = printlevel-voice+2;
     4889   int nvar = nvars(basering);
     4890   int chara  = char(basering);
     4891   list result,prim,keepresult;
     4892
     4893   if ( ord_test(basering) != 1 )
     4894   {
     4895     "";
     4896     "// Not implemented for this ordering,";
     4897     "// please change to global ordering!";
     4898     return(result);
     4899   }
     4900
     4901//--------------------------- define the method ---------------------------
     4902   string method;                //make all options one string in order to use
     4903                                 //all combinations of options simultaneously
     4904   for ( i=1; i <= size(#); i++ )
     4905   {
     4906     if ( typeof(#[i]) == "string" )
     4907     {
     4908       method = method + #[i];
     4909     }
     4910   }
     4911
     4912   //--------------------------- choosen methods -----------------------
     4913   //we have the methods
     4914   // "withGens": computes algebra generators for each irreducible component
     4915   // the general case: either "equidim" or not (then applying minAssGTZ)
     4916
     4917   if ( find(method,"withgens") or find(method,"withGens"))
     4918   {
     4919     wgens=1;
     4920   }
     4921   if ( find(method,"equidim") )
     4922   {
     4923     withEqui=1;
     4924   }
     4925   if ( find(method,"prim") )
     4926   {
     4927     withPrim=1;
     4928   }
     4929   if ( find(method,"isprim") or find(method,"isPrim") )
     4930   {
     4931     isPrim=1;
     4932   }
     4933   if ( find(method,"noFac") )
     4934   {
     4935     nfac=1;           
     4936   }
     4937
     4938   //------------------ default method, may be changed --------------------
     4939   //Use a prime decomposition only for small no of variables otherwise equidim
     4940   //Compute delta whenever possible.
     4941
     4942   if ( ((chara==0 || chara>30) && nvar>2 && !withPrim && !isPrim) ||
     4943   ((chara==0 || chara>30) && size(#)  ==  0) )
     4944   {
     4945      withEqui=1;
     4946   }
     4947   kill #;
     4948   list #;
     4949
     4950//------- Special algorithm with computation of the generators, RETURN -------
     4951   //--------------------- method "withGens" ----------------------------------
     4952   //the integral closure is computed in proc primeClosure. In the general case
     4953   //it is computed in normalizationPrimes. The main difference is that  in
     4954   //primeClosure the singular locus is only computed in the first iteration
     4955   //that no attributes are used and that the generators are computed.
     4956   //In primeClosure the (algebra) generators for each irreducible component
     4957   //are computed in static proc closureGenerators
     4958
     4959   if( wgens )
     4960   {
     4961      if( y >= 1 )
     4962      {  "";
     4963         "// We use method 'withGens'";
     4964      }
     4965      if ( isPrim )
     4966      {
     4967         prim[1] = id;
     4968         if( y >= 0 )
     4969         {
     4970           "";
     4971           "// ** WARNING: result is correct if ideal is prime (not checked) **";
     4972           "// if procedure is called with string \"prim\", primality is checked";
     4973         }
     4974      }
     4975      else
     4976      {
     4977         if(y>=1)
     4978         {  "// compute minimal associated primes"; }
     4979
     4980         if( nfac )
     4981         { prim = minAssGTZ(id,1); }
     4982         else
     4983         { prim = minAssGTZ(id); }
     4984
     4985         if(y>=1)
     4986         { 
     4987            prim;"";
     4988            "// number of irreducible components is", size(prim);
     4989         }
     4990      }
     4991   //----------- compute integral closure for every component -------------
     4992      int del;
     4993      intvec deli;
     4994      list Gens,l,resu,Resu;
     4995      ideal gens;
     4996      def R = basering;
     4997      poly gg;
     4998
     4999      for(i=1; i<=size(prim); i++)
     5000      {
     5001         if(y>=1)
     5002         {
     5003            ""; pause(); "";
     5004            "// start computation of component",i;
     5005            "   --------------------------------";
     5006         }
     5007
     5008         if( defined(ker) ) { kill ker; }
     5009         ideal ker = prim[i];
     5010         export(ker);
     5011         l = R;
     5012         l = primeClosure(l,1);               //here the work is done
     5013         //### ausprobieren ob primeClosure(l,1) schneller als primeClosure(l)
     5014         // 1 bedeutet: kŸrzester nzd
     5015
     5016         if ( l[size(l)] >= 0 && del >= 0 )
     5017         {
     5018            del = del + l[size(l)];
     5019         }
     5020         else
     5021         { del = -1; }
     5022         deli = l[size(l)],deli;
     5023
     5024         l = l[1..size(l)-1];
     5025         resu = list(l[size(l)]) + resu;
     5026         gens = closureGenerators(l);         //computes algebra(!) generators
     5027
     5028         //NOTE: gens[i]/gens[size(gens)] expresses the ith variable of resu[1]
     5029         //(the normalization) as fraction of elements of the basering;
     5030         //the variables of resu[1] are algebra generators.
     5031         //gens[size(gens)] is a non-zero divisor of basering/i
     5032
     5033         //divide by the greatest common divisor:
     5034         gg = gcd( gens[1],gens[size(gens)] );
     5035         for(j=2; j<=size(gens)-1; j++)
     5036         {
     5037            gg=gcd(gg,gens[j]);
     5038         }
     5039         for(j=1; j<=size(gens); j++)
     5040         {
     5041            gens[j]=gens[j]/gg;
     5042         }
     5043         Gens = list(gens) + Gens;
     5044
     5045/*       ### Da die gens Algebra-Erzeuger sind, ist reduce nach Bestimmung
     5046         der Algebra-Variablen T(i) nicht zulŠssig!
     5047         for(i=1;i<=size(gens)-1;i++)
     5048         {
     5049            gens[i]= reduce(gens[i],std(gens[size(gens)]));
     5050         }
     5051         for(i=size(gens)-1; i>=1; i--)
     5052         {
     5053            if(gens[i]==0)
     5054            { gens = delete(gens,i); }
     5055         }
     5056*/
     5057         if( defined(ker) ) { kill ker; }
     5058      }
     5059
     5060      if ( del >= 0 )
     5061      {
     5062         int mul = iMult(prim);
     5063         del = del + mul;
     5064      }
     5065      else
     5066      { del = -1; }
     5067      deli = deli[1..size(deli)-1];
     5068      Resu = resu,Gens,list(deli,del);
     5069      int sr = size(resu);
     5070
     5071      if ( y >= 0 )
     5072      {"";
     5073"// 'normalC' created a list, say nor, of three lists:
     5074// nor[1] resp. nor[2] are lists of",sr,"ring(s) resp. ideal(s)
     5075// and nor[3] is a list of an intvec and an integer.
     5076// To see the result, type
     5077     nor;
     5078// To access the i-th ring nor[1][i] give it a name, say Ri, and type e.g.
     5079     def R1 = nor[1][1]; setring R1;  norid; normap;
     5080// for the other rings type first setring r; (if r is the name of your
     5081// original basering) and then continue as for the first ring;
     5082// Ri/norid is the affine algebra of the normalization of the i-th
     5083// component r/P_i (where P_i is an associated prime of the input ideal)
     5084// and normap the normalization map from r to Ri/norid;
     5085//    nor[2] is a list of",sr,"ideal(s), each ideal nor[2][i] consists of
     5086// elements g1..gk of r such that the gj/gk generate the integral
     5087// closure of r/P_i as sub-algebra in the quotient field of r/P_i, with
     5088// gj/gk being mapped by normap to the j-th variable of Ri;
     5089//    nor[3] shows the delta-invariant of each component and of the input
     5090// ideal (-1 means infinite, and 0 that r/P_i resp. r/input is normal).";
     5091      }
     5092      return(Resu);
     5093   }
     5094
     5095//-------- The general case without computation of the generators -----------
     5096// (attrib(id,"xy"),1) sets attrib xy to TRUE and (attrib(id,"xy"),0) to FALSE
     5097// We use the following attributes:
     5098//   attrib(id,"isCohenMacaulay");         //--- Cohen Macaulay
     5099//   attrib(id,"isCompleteIntersection");  //--- complete intersection 
     5100//   attrib(id,"isHypersurface");          //--- hypersurface
     5101//   attrib(id,"isEquidimensional",-1);    //--- equidimensional ideal
     5102//   attrib(id,"isPrim");                  //--- prime ideal
     5103//   attrib(id,"isRegInCodim2");           //--- regular in codimension 2
     5104//   attrib(id,"isIsolatedSingularity";    //--- isolated singularities
     5105//   attrib(id,"onlySingularAtZero");      //--- only singular at 0   
     5106
     5107 //------------------- first set the attributes ----------------------
     5108   if( typeof(attrib(id,"isCohenMacaulay"))=="int" )   
     5109   {
     5110      if( attrib(id,"isCohenMacaulay")==1 )
     5111      {
     5112         attrib(id,"isEquidimensional",1);
     5113      }
     5114   }
     5115   else
     5116   {
     5117      attrib(id,"isCohenMacaulay",0);
     5118   } 
     5119
     5120   if( typeof(attrib(id,"isCompleteIntersection"))=="int" )
     5121   {
     5122      if(attrib(id,"isCompleteIntersection")==1)
     5123      {
     5124         attrib(id,"isCohenMacaulay",1);
     5125         attrib(id,"isEquidimensional",1);
     5126      }
     5127   }
     5128   else
     5129   {
     5130      attrib(id,"isCompleteIntersection",0);
     5131   }
     5132   
     5133   if( typeof(attrib(id,"isHypersurface"))=="int" )
     5134   {
     5135      if(attrib(id,"isHypersurface")==1)
     5136      {
     5137         attrib(id,"isCompleteIntersection",1);
     5138         attrib(id,"isCohenMacaulay",1);
     5139         attrib(id,"isEquidimensional",1);
     5140      }
     5141   }
     5142   else
     5143   {
     5144      attrib(id,"isHypersurface",0);
     5145   }
     5146   
     5147   if( ! (typeof(attrib(id,"isEquidimensional"))=="int") )
     5148   {
     5149         attrib(id,"isEquidimensional",0);
     5150   }
     5151   
     5152   if( typeof(attrib(id,"isPrim"))=="int" )
     5153   {
     5154      if(attrib(id,"isPrim")==1)
     5155      {
     5156         attrib(id,"isEquidimensional",1);
     5157      }
     5158   }
     5159   else
     5160   {
     5161      attrib(id,"isPrim",0);
     5162   }
     5163   
     5164   if( ! (typeof(attrib(id,"isRegInCodim2"))=="int") )
     5165   {
     5166         attrib(id,"isRegInCodim2",0);
     5167   }
     5168   
     5169   if( ! (typeof(attrib(id,"isIsolatedSingularity"))=="int") )
     5170   {
     5171         attrib(id,"isIsolatedSingularity",0);
     5172   }
     5173 
     5174   if( typeof(attrib(id,"onlySingularAtZero"))=="int" )
     5175   {
     5176      if(attrib(id,"onlySingularAtZero")==1)
     5177      {
     5178         attrib(id,"isIsolatedSingularity",1);
     5179      }
     5180   }
     5181   else
     5182   {
     5183      attrib(id,"onlySingularAtZero",0);
     5184   }
     5185
     5186   //-------------- compute equidimensional decomposition --------------------
     5187   //If the method "equidim" is given, compute the equidim decomposition
     5188   //and goto the next step (no normalization
     5189   //ACHTUNG: equidim berechnet bei nicht reduzierten id die eingebetteten
     5190   //Komponenten als niederdim Komponenten, waehrend diese bei primdecGTZ
     5191   //nicht auftauchen: ideal(x,y)*xy
     5192   //this is default for nvars > 2 and char = 0 or car > 30
     5193
     5194   if( withEqui )
     5195   {
     5196      withPrim = 0;                 //this is used to check later that prim
     5197                                    //contains equidim but not prime components
     5198      if( y >= 1 )
     5199      {
     5200         "// We use method 'equidim'";
     5201      }
     5202      if( typeof(attrib(id,"isEquidimensional"))=="int" )
     5203      {
     5204         if(attrib(id,"isEquidimensional")==1)
     5205         {
     5206            prim[1] = id;
     5207         }
     5208         else
     5209         {
     5210            prim = equidim(id);
     5211         }
     5212      }
     5213      else
     5214      {
     5215         prim = equidim(id);
     5216      }
     5217      if(y>=1)
     5218      {  "";
     5219         "// number of equidimensional components:", size(prim);
     5220      }
     5221      if ( !nfac )
     5222      {
     5223        intvec opt = option(get);
     5224        option(redSB);
     5225        for(j=1; j<=size(prim); j++)   
     5226        {
     5227           keepresult = keepresult+facstd(prim[j]);
     5228        }
     5229        prim = keepresult;
     5230        if ( size(prim) == 0 )
     5231        {
     5232          prim=ideal(0);     //Bug in facstd, liefert leere Liste bei 0-Ideal
     5233        }
     5234       
     5235        if(y>=1)
     5236        {  "";
     5237         "// number of components after application of facstd:", size(prim);
     5238        }
     5239        option(set,opt);
     5240      }
     5241   }
     5242
     5243   //------------------- compute associated primes -------------------------
     5244   //the case where withEqui = 0, here the min. ass. primes are computed
     5245   //start with the computation of the minimal associated primes:
     5246
     5247   else                                         
     5248   {
     5249    if( isPrim )
     5250    {
     5251      if( y >= 0 )
     5252      {
     5253         "// ** WARNING: result is correct if ideal is prime";
     5254         "// or equidimensional (not checked) **";
     5255         "// disable option \"isPrim\" to decompose ideal into prime";
     5256         "// or equidimensional components";"";
     5257      }
     5258      if( y >= 1 )
     5259      {
     5260        "// We use method 'isPrim'";"";
     5261      }
     5262      prim[1]=id;
     5263    }
     5264    else
     5265    {
     5266      withPrim = 1;                 //this is used to check later that prim
     5267                                    //contains prime but not equidim components
     5268      if( y >= 1 )
     5269      {
     5270         "// We use method 'prim'";
     5271      }
     5272
     5273      if( typeof(attrib(id,"isPrim"))=="int" )
     5274      {
     5275         if(attrib(id,"isPrim")==1)
     5276         {
     5277            prim[1]=id;
     5278         }
     5279         else
     5280         {
     5281            if( nfac )
     5282            { prim=minAssGTZ(id,1); }     //does not use factorizing groebner
     5283            else
     5284            { prim=minAssGTZ(id); }       //uses factorizing groebner
     5285         }
     5286      }
     5287      else
     5288      {
     5289            if( nfac )
     5290            { prim=minAssGTZ(id,1); }
     5291            else
     5292            { prim=minAssGTZ(id); }
     5293      }
     5294      if(y>=1)
     5295      {  "";
     5296         "// number of irreducible components:", size(prim);
     5297      }
     5298    }
     5299   }
     5300
     5301   //----- for each component (equidim or irred) compute normalization -----
     5302   int sr, skr, del;
     5303   intvec deli; 
     5304   int sp = size(prim);     //size of list prim (# irred or equidim comp)
     5305
     5306   for(i=1; i<=sp; i++)
     5307   {
     5308      if(y>=1)
     5309      {  "";
     5310         "// computing the normalization of component",i;
     5311         "   ----------------------------------------";
     5312      }
     5313      //-------------- first set attributes for components ------------------
     5314      attrib(prim[i],"isEquidimensional",1);
     5315      if( withPrim )
     5316      {
     5317         attrib(prim[i],"isPrim",1);
     5318      }
     5319      else
     5320      { attrib(prim[i],"isPrim",0); }
     5321
     5322      if(attrib(id,"onlySingularAtZero")==1)
     5323      { attrib(prim[i],"onlySingularAtZero",1); }
     5324      else
     5325      { attrib(prim[i],"onlySingularAtZero",0); }
     5326
     5327      if(attrib(id,"isIsolatedSingularity")==1)
     5328      { attrib(prim[i],"isIsolatedSingularity",1); }
     5329      else
     5330      { attrib(prim[i],"isIsolatedSingularity",0); }
     5331
     5332      if( attrib(id,"isHypersurface")==1 )
     5333      {
     5334         attrib(prim[i],"isHypersurface",1);
     5335         attrib(prim[i],"isCompleteIntersection",1);
     5336         attrib(prim[i],"isCohenMacaulay",1);
     5337      }
     5338      else
     5339      { attrib(prim[i],"isHypersurface",0); }
     5340
     5341      if ( sp == 1)         //the case of one component: copy attribs from id
     5342      {
     5343        if(attrib(id,"isRegInCodim2")==1)
     5344        {attrib(prim[i],"isRegInCodim2",1); }
     5345        else
     5346        {attrib(prim[i],"isRegInCodim2",0); }
     5347
     5348        if(attrib(id,"isCohenMacaulay")==1)
     5349        {attrib(prim[i],"isCohenMacaulay",1); }
     5350        else
     5351        {attrib(prim[i],"isCohenMacaulay",0); }
     5352
     5353        if(attrib(id,"isCompleteIntersection")==1)
     5354        {attrib(prim[i],"isCompleteIntersection",1); }
     5355        else
     5356        {attrib(prim[i],"isCompleteIntersection",0); }
     5357      }
     5358      else
     5359      { 
     5360        attrib(prim[i],"isRegInCodim2",0);
     5361        attrib(prim[i],"isCohenMacaulay",0);
     5362        attrib(prim[i],"isCompleteIntersection",0);
     5363      }
     5364
     5365      //------ Now compute the normalization of each component ---------
     5366      //note: for equidimensional components the "splitting tools" can
     5367      //create further decomposition
     5368      //We now start normalizationPrimes with
     5369      //ihp = partial normalisation map = identity map = maxideal(1)
     5370      //del = partial delta invariant = 0
     5371      //deli= intvec of partial delta invariants of components
     5372      //in normalizationPrimes all the work is done:
     5373
     5374      keepresult = normalizationPrimes(prim[i],maxideal(1),0,0);
     5375
     5376      for(j=1; j<=size(keepresult)-1; j++)
     5377      {
     5378         result=insert(result,keepresult[j]);
     5379      }
     5380      skr = size(keepresult);
     5381
     5382      //compute delta:             
     5383      if( del >= 0 && keepresult[skr][1] >=0 )
     5384      {
     5385         del = del + keepresult[skr][1];
     5386      }
     5387      else
     5388      { 
     5389         del = -1;
     5390      }
     5391      deli = keepresult[skr][2],deli;
     5392
     5393      if ( y>=1 )
     5394      {
     5395           "// delta of component",i; keepresult[skr][1];
     5396      }
     5397   }
     5398   sr = size(result);
     5399
     5400   // -------------- Now compute intersection multiplicities -------------
     5401   //intersection multiplicities of list prim, sp=size(prim).
     5402      if ( y>=1 )
     5403      {
     5404        "// Sum of delta for all components"; del;
     5405        if ( sp>1 )
     5406        {
     5407           "// Compute intersection multiplicities of the components";
     5408        }
     5409      }   
     5410
     5411      if ( sp > 1 )
     5412      {
     5413        int mul = iMult(prim);
     5414        if ( mul < 0 )
     5415        {
     5416           del = -1;
     5417        }
     5418        else
     5419        {
     5420           del = del + mul;
     5421        }
     5422      }
     5423   deli = deli[1..size(deli)-1];
     5424   result = result,list(deli,del);
     5425
     5426//--------------- Finally print comments and return ------------------
     5427   if ( y >= 0)
     5428   {"";
     5429"// 'normalC' created a list, say nor, of two lists:
     5430// nor[1] is a list of",sr,"ring(s), nor[2] a list of an intvec and an int.
     5431// To see the result, type
     5432      nor;
     5433// To access the i-th ring nor[1][i] give it a name, say Ri, and type e.g.
     5434      def R1 = nor[1][1];  setring R1;  norid;  normap;
     5435// and similair for the other rings nor[1][i];
     5436// Ri/norid is the affine algebra of the normalization of the i-th component
     5437// r/P_i (where P_i is a prime or an equidimensional ideal of the input ideal)
     5438// and normap the normalization map from the basering to Ri/norid;
     5439//    nor[2] shows the delta-invariant of each component and of the input
     5440// ideal (-1 means infinite, -2 that delta of a component was not computed).";
     5441   }
     5442   return(result);
     5443}
     5444
     5445example
     5446{ "EXAMPLE:";
     5447   printlevel = printlevel+1;
     5448   echo = 2;
     5449   ring s = 0,(x,y),dp;
     5450   ideal i = (x2-y3)*(x2+y2)*x;
     5451
     5452   list nor = normalC(i);
     5453
     5454   nor;
     5455   // 2 branches have delta = 1, and 1 branch has delta = 0
     5456   // the total delta invariant is 13
     5457
     5458   def R2 = nor[1][2];  setring R2;
     5459   norid; normap;
     5460   
     5461   echo = 0;
     5462   printlevel = printlevel-1;
     5463   pause("   hit return to continue"); echo=2;
     5464
     5465   ring r = 2,(x,y,z),dp;
     5466   ideal i = z3-xy4;
     5467   nor = normalC(i);  nor; 
     5468   // the delta invariant is infinite
     5469   // xy2z/z2 and xy3/z2 generate the integral closure of r/i as r/i-module
     5470   // in its quotient field Quot(r/i)
     5471
     5472   // the normalization as affine algebra over the ground field:             
     5473   def R = nor[1][1]; setring R;
     5474   norid; normap;
     5475
     5476   echo = 0; 
     5477   pause("   hit return to continue");echo = 2;
     5478
     5479   setring r;
     5480   nor = normalC(i, "withGens", "prim");    // a different algorithm
     5481   nor;
     5482}
     5483
     5484//////////////////////////////////////////////////////////////////////////////
     5485//closureRingtower seems not to be used anywhere
     5486static proc closureRingtower(list L)
     5487"USAGE:    closureRingtower(list L); L a list of rings
     5488CREATE:   rings R(1),...,R(n) such that R(i)=L[i] for all i
     5489EXAMPLE:  example closureRingtower; shows an example
     5490"
     5491{
     5492  int n=size(L);
     5493  for (int i=1;i<=n;i++)
     5494    {
     5495      if (defined(R(i))) {
     5496        string s="Fixed name R("+string(i)+") leads to conflict with existing "
     5497              +"object having this name";
     5498        ERROR(s);
     5499      }
     5500      def R(i)=L[i];
     5501      export R(i);
     5502    }
     5503
     5504  return();
     5505}
     5506example
     5507{
     5508  "EXAMPLE:"; echo=2;
     5509  ring R=0,(x,y),dp;
     5510  ideal I=x4,y4;
     5511  list L=primeClosure(ReesAlgebra(I)[1]);
     5512  L=delete(L,size(L));
     5513L;
     5514  closureRingtower(L);
     5515  R(1);
     5516  R(4);
     5517  kill R(1),R(2),R(3),R(4);
     5518}
     5519
     5520//                Up to here: procedures for normalC
     5521///////////////////////////////////////////////////////////////////////////////
     5522
     5523///////////////////////////////////////////////////////////////////////////////
     5524//                From here: miscellaneous procedures
     5525
     5526// Used for timing and comparing the different normalization procedures.
     5527// Option (can be entered in any order)
     5528// "normal"   -> uses the new algortihm (normal)
     5529// "normalP"  -> uses normalP
     5530// "normalC"  -> uses normalC, without "withGens" option
     5531// "primCl"   -> uses normalC, with option "withGens".
     5532// "111"      -> checks the output of normalM using norTest.
     5533// "p"        -> compares the output of norM with the output of normalP
     5534//               ("normalP" option must also be set).
     5535// "pc"       -> compares the output of norM with the output of normalC with
     5536//               option "withGens"
     5537//               ("primCl" option must also be set).
     5538proc timeNormal(ideal I, list #){
     5539  //--------------------------- define the method ---------------------------
     5540  int isPrim, useRing;
     5541  int decomp = -1;
     5542  int norM, norC, norP, primCl;
     5543  int checkP, check111, checkPC;
     5544  int i;
     5545  ideal U1, U2, W;
     5546  poly c1, c2;
     5547  int ch;
     5548  string check;
     5549  string method;                //make all options one string in order to use
     5550                                //all combinations of options simultaneously
     5551  for ( i=1; i <= size(#); i++ )
     5552  {
     5553    if ( typeof(#[i]) == "string" )
     5554    {
     5555      method = method + #[i];
     5556    }
     5557  }
     5558  if ( find(method, "normal"))
     5559  {norM = 1;} 
     5560  if ( find(method, "normalP") and (char(basering) > 0))
     5561  {norP = 1;} 
     5562  if ( find(method, "normalC"))
     5563  {norC = 1;}     
     5564  if ( find(method, "primCl"))
     5565  {primCl = 1;} 
     5566  if ( find(method, "isprim") or find(method,"isPrim") )
     5567  {decomp = 0;}
     5568  if ( find(method, "p") )
     5569  {checkP = 1;} 
     5570  if ( find(method, "pc") )
     5571  {checkPC = 1;} 
     5572  if ( find(method, "111") )
     5573  {check111 = 1;}   
     5574     
     5575  int tt;
     5576  if(norM){
     5577    tt = timer;
     5578    if(decomp == 0){
     5579      "Running normal(useRing, isPrim)...";
     5580      list a1 = normal(I, "useRing", "isPrim");
     5581      "Time normal(useRing, isPrim): ", timer - tt;
     5582    } else {
     5583      "Running normal(useRing)...";
     5584      list a1 = normal(I, "useRing");
     5585      "Time normal(useRing): ", timer - tt;
     5586    }
     5587    "";
     5588  }
     5589  if(norP){
     5590    tt = timer;
     5591    if(decomp == 0){
     5592      "Running normalP(isPrim)...";
     5593      list a2 = normalP(I, "isPrim");
     5594      "Time normalP(isPrim): ", timer - tt;
     5595    } else {
     5596      "Running normalP()...";
     5597      list a2 = normalP(I);
     5598      "Time normalP(): ", timer - tt;
     5599    }
     5600    "";
     5601  }
     5602 
     5603  if(norC){
     5604    tt = timer;
     5605    if(decomp == 0){
     5606      "Running normalC(isPrim)...";
     5607      list a3 = normalC(I, "isPrim");
     5608      "Time normalC(isPrim): ", timer - tt;
     5609    } else {
     5610      "Running normalC()...";
     5611      list a3 = normalC(I);
     5612      "Time normalC(): ", timer - tt;
     5613    }
     5614    "";
     5615  }
     5616 
     5617  if(primCl){
     5618    tt = timer;
     5619    if(decomp == 0){
     5620      "Running normalC(withGens, isPrim)...";
     5621      list a4 = normalC(I, "isPrim", "withGens");
     5622      "Time normalC(withGens, isPrim): ", timer - tt;
     5623    } else {
     5624      "Running normalC(withGens)...";   
     5625      list a4 = normalC(I, "withGens");
     5626      "Time normalC(withGens): ", timer - tt;
     5627    }
     5628    "";
     5629  }
     5630 
     5631  if(check111 and norM){
     5632    "Checking output with norTest...";
     5633    "WARNING: this checking only works if the original ideal was prime.";
     5634    list norL = list(a1[1][1][3]);
     5635    norTest(I, list(norL));
     5636    "";
     5637  }
     5638 
     5639  if(checkP and norP and norM){
     5640    "Comparing with normalP output...";
     5641    "WARNING: this checking only works if the original ideal was prime.";
     5642    U1 = a1[1][1][1];
     5643    c1 = a1[1][1][2];
     5644    U2 = a2[1][1];
     5645    c2 = a2[1][1][size(a2[1][1])];
     5646    W = changeDenominator(U1, c1, c2, groebner(I));
     5647    qring q = groebner(I);
     5648    ideal U2 = fetch(r, U2);
     5649    ideal W = fetch(r, W);
     5650    ch = 0;
     5651    if(size(reduce(U2, groebner(W))) == 0){
     5652      "U2 c U1";
     5653      ch = 1;
     5654    }
     5655    if(size(reduce(W, groebner(U2))) == 0){
     5656      "U1 c U2";
     5657      ch = ch + 1;
     5658    }
     5659    if(ch == 2){
     5660      "Output of normalP is equal.";
     5661    } else {
     5662      "ERROR: Output of normalP is different.";
     5663    }
     5664    "";
     5665    setring r;
     5666    kill q;
     5667  } 
     5668
     5669  if(checkPC and norM and primCl){   
     5670    "Comparing with primeClosure output...";
     5671    "WARNING: this checking only works if the original ideal was prime.";
     5672    // primeClosure check
     5673    U1 = a1[1][1][1];
     5674    c1 = a1[1][1][2];
     5675    U2 = a4[2][1];
     5676    c2 = a4[2][1][size(a4[2][1])];
     5677    W = changeDenominator(U1, c1, c2, groebner(I));
     5678    qring q = groebner(I);
     5679    ideal U2 = fetch(r, U2);
     5680    ideal W = fetch(r, W);
     5681    ch = 0;
     5682    if(size(reduce(U2, groebner(W))) == 0){
     5683      "U2 c U1";
     5684      ch = 1;
     5685    }
     5686    if(size(reduce(W, groebner(U2))) == 0){
     5687      "U1 c U2";
     5688      ch = ch + 1;
     5689    }
     5690    if(ch == 2){
     5691      "Output of normalC(withGens) is equal.";
     5692    } else {
     5693      "ERROR: Output of normalC(withGens) is different.";
     5694    }
     5695    "";
     5696    setring r;
     5697    kill q;   
     5698  }
     5699}
     5700
    24445701///////////////////////////////////////////////////////////////////////////
    2445 
     5702proc norTest (ideal i, list nor, list #)
     5703"USAGE:   norTest(i,nor,[n]); i=prime ideal, nor=list, n=optional integer
     5704ASSUME:  nor is the resulting list of normal(i) (any options) or the result
     5705         of normalP(i,"withRing"). In particular, the ring nor[1][1] contains
     5706         the ideal norid and the map normap: basering/i --> nor[1][1]/norid.
     5707RETURN:  an intvec v such that:
     5708@format
     5709         v[1] = 1 if the normap is injective and 0 otherwise
     5710         v[2] = 1 if the normap is finite and 0 otherwise
     5711         v[3] = 1 if nor[1][1]/norid is normal and 0 otherwise
     5712@end format
     5713         If n=1 (resp n=2) only v[1] (resp. v[2]) is computed and returned
     5714THEORY:  The procedure can be used to test whether the computation of the
     5715         normalization was correct: basering/i --> nor[1][1]/norid is the
     5716         normalization of basering/i iff v=1,1,0.
     5717NOTE:    For big examples it can be hard to fully test correctness; the
     5718         partial test norTest(i,nor,2) is usually fast
     5719EXAMPLE: example norTest; shows an example
     5720"
     5721{
     5722//### Sollte erweitert werden auf den reduziblen Fall: einen neuen affinen
     5723// Ring nor[1][1]+...+nor[1][r] (direkte Summe) erzeugen, map dorthin
     5724// definieren und dann testen.
     5725
     5726    int prl = printlevel - voice + 2;
     5727    int a,b,d;
     5728    int n,ii;
     5729    if (size(#) > 0) {  n = #[1];  }
     5730
     5731    def BAS = basering;
     5732
     5733    //### make a copy of nor to have a cpoy of nor[1][1]  (not a reference to)
     5734    // in order not to overwrite norid and normap.
     5735    // delete nor[2] (if it contains the module generators, which are not used)
     5736    // s.t. newnor does not belong to a ring.
     5737
     5738    list newnor = nor;         
     5739    if ( size(newnor) == 3 )
     5740    {
     5741       newnor = delete(newnor,2);
     5742    }
     5743    qring QAS = std(i);
     5744   
     5745    def R = newnor[1][1];
     5746    setring R;
     5747    int nva = nvars(R);
     5748    string svars = varstr(R);
     5749    string svar;
     5750
     5751    norid = interred(norid);
     5752
     5753    //--------- create new ring with one dp block keeping weights ------------
     5754    list LR = ringlist(R);
     5755    list g3 = LR[3];
     5756    int n3 = size(g3);
     5757    list newg3;
     5758    intvec V;
     5759
     5760    //--------- check first whether variables Z(i),...,A(i) exist -----------
     5761    for (ii=90; ii>=65; ii--) 
     5762    {
     5763       if ( find(svars,ASCII(ii)+"(") == 0 )       
     5764       {
     5765          svar = ASCII(ii);  break;
     5766       }
     5767    }
     5768    if ( size(svar) != 0 )
     5769    {
     5770        for ( ii = 1; ii <= nva; ii++ )
     5771        {
     5772            LR[2][ii] = svar+"("+string(ii)+")";
     5773            V[ii] = 1;
     5774        }
     5775    }
     5776    else
     5777    {       
     5778        for ( ii = 1; ii <= nva; ii++ )
     5779        {
     5780           LR[2][ii] = "Z("+string(100*nva+ii)+")";
     5781           V[ii] = 1;
     5782        }
     5783    }
     5784   
     5785    if ( g3[n3][1]== "c" or g3[n3][1] == "C" )
     5786    {
     5787       list gm = g3[n3];       //last blockis module ordering
     5788       newg3[1] = list("dp",V);
     5789       newg3 = insert(newg3,gm,size(newg3));
     5790    }
     5791    else
     5792    {
     5793       list gm = g3[1];              //first block is module ordering
     5794       newg3[1] = list("dp",V);
     5795       newg3 = insert(newg3,gm);
     5796    }
     5797    LR[3] = newg3;
     5798//LR;"";
     5799    def newR = ring(LR);
     5800
     5801    setring newR;
     5802    ideal norid = fetch(R,norid);
     5803    ideal normap = fetch(R,normap);
     5804    if( defined(lnorid) )  { kill lnorid; }     //um ** redefinig zu beheben
     5805    if( defined(snorid) )  { kill snorid; }     //sollte nicht noetig sein
     5806
     5807    //----------- go to quotient ring for checking injectivity -------------
     5808//"mstd";
     5809    list lnorid = mstd(norid);
     5810    ideal snorid = lnorid[1];
     5811//"size mstdnorid:", size(snorid),size(lnorid[2]);
     5812//"size string mstdnorid:", size(string(snorid)),size(string(lnorid[2]));
     5813    qring QR = snorid;
     5814    ideal qnormap = fetch(newR,normap);
     5815    //ideal qnormap = imap(newR,normap);
     5816    //ideal qnormap = imap(R,normap);
     5817    map Qnormap = QAS,qnormap;    //r/id --> R/norid
     5818   
     5819    //------------------------ check injectivity ---------------------------
     5820//"injective:";
     5821    a = is_injective(Qnormap,QAS);          //a. Test for injectivity of Qnormap
     5822    dbprint ( prl, "injective: "+string(a) );
     5823    if ( n==1 ) { return (a); }
     5824   a;
     5825
     5826    //------------------------ check finiteness ---------------------------
     5827    setring newR;
     5828    b = mapIsFinite(normap,BAS,lnorid[2]);  //b. Test for finiteness of normap
     5829    dbprint ( prl, "finite: "+string(b) );
     5830    if ( n==2 ) { return (intvec(a,b)); }
     5831   b;
     5832
     5833    //------------------------ check normality ---------------------------
     5834    list testnor = normal(lnorid[2],"isPrim","noFac");
     5835    //### Problem: bei mehrfachem Aufruf von norTest gibt es
     5836    // ** redefining norid & ** redefining normap
     5837    //Dies produziert Fehler, da alte norid und normap ueberschrieben werden
     5838    //norid und normap werden innnerhalb von proc computeRing ueberschrieben
     5839    //Die Kopie newR scheint das Problem zu loesen
     5840
     5841    printlevel=prl;
     5842    d = testnor[size(testnor)][2];             //d = delta
     5843    kill testnor;                              //### sollte ueberfluessig sein
     5844    int d1 = (d==0);                           //d1=1 if delta=0
     5845    dbprint ( prl, "delta: "+string(d) );
     5846    return(intvec(a,b,d1));
     5847}
     5848example
     5849{ "EXAMPLE:"; echo = 2;
     5850   int prl = printlevel;
     5851   printlevel = -1;
     5852   ring r = 0,(x,y),dp;
     5853   ideal i = (x-y^2)^2 - y*x^3;
     5854   list nor = normal(i);
     5855   norTest(i,nor);                //1,1,1 means that normal was correct
     5856
     5857   ring s = 2,(x,y),dp;
     5858   ideal i = (x-y^2)^2 - y*x^3;
     5859   nor = normalP(i,"withRing");
     5860   norTest(i,nor);               //1,1,1 means that normalP was correct
     5861   printlevel = prl;
     5862}
     5863
     5864///////////////////////////////////////////////////////////////////////////
     5865//
     5866//                            EXAMPLES
     5867//
     5868///////////////////////////////////////////////////////////////////////////
    24465869/*
    2447                            Examples:
    2448 LIB"normal.lib";
    2449 //Huneke
    2450 ring qr=31991,(a,b,c,d,e),dp;
     5870//commands for computing the normalization:
     5871// options for normal:  "equidim", "prim"
     5872//                      "noDeco", "isPrim", "noFac"
     5873//                       (prim by default)                     
     5874// options for normalP: "withRing", "isPrim" or "noFac"
     5875// options for normalC: "equidim", "prim", "withGens",
     5876//                      "noDeco", "isPrim", "noFac"
     5877
     5878//Commands for testing 'normal'
     5879 list nor = normal(i); nor;           
     5880 list nor = normal(i,"isPrim");nor;
     5881 list nor = normal(i,"equidim");nor;
     5882 list nor = normal(i,"prim");nor;
     5883 list nor = normal(i,"equidim","noFac");nor;
     5884 list nor = normal(i,"prim","noFac");nor;
     5885
     5886//Commands for testing 'normalP' in positive char
     5887 list nor = normalP(i);nor;              //withGens but no ringstructure
     5888 list nor = normalP(i,"withRing"); nor;  //compute the ringstructure
     5889 list nor = normalP(i,"isPrim"); nor;    //if i is known to be prime
     5890
     5891//Commands for testing 'normalC'
     5892 list nor = normal(i); nor;           
     5893 list nor = normal(i,"withGens");nor;
     5894 list nor = normal(i,"isPrim");nor;
     5895 list nor = normal(i,"equidim");nor;
     5896 list nor = normal(i,"prim");nor;
     5897 list nor = normal(i,"equidim","noFac");nor;
     5898 list nor = normal(i,"prim","noFac");nor;
     5899
     5900//Commands for testing correctness (i must be prime):
     5901list nor = normalP(i,"withRing","isPrim");
     5902list nor = normal(i,"isPrim");
     5903norTest(i,nor);       //full test for not too big examples (1,1,1 => ok)
     5904norTest(i,nor,2);     //partial test for big examples (1,1 => ok)
     5905factorize(i[1]);      //checks for irreducibility
     5906
     5907//----------------------Test Example for charp -------------------
     5908//Zu tun:
     5909//### nach minor nur std statt mstd verwenden
     5910//***hat bei keinem Beisp etwas gebracht -> wieder zurueck
     5911//### wenn interred ok, dann wieder einsetzen (am Schluss)
     5912//### bottelnecks bei maps beheben
     5913//### minor verbessern
     5914//### preimage verbessern (Ist imm Kern map oder imap verwendet?)
     5915//### Gleich in Ordnung dp wechseln, ringlist verwenden
     5916//### interred ev nur zum Schluss
     5917//    (z.B. wenn nacher std; wenn nacher minor: testen )
     5918
     5919//Zeiten mit normalV5.lib (mstd aktiv, interred inaktiv)
     5920
     5921//SWANSON EXAMPLES: (Macaulay2, icFracP=normalP, icFractions<->normal)
     5922//---------------------------------------------------------------------
     5923//1. Series Fp[x,y,u,v]/(x2v-y2u)
     5924//-------------------------------
     5925//characteristic p   2   3    5    7    11   13   17   37   97
     5926//icFracP          0.04 0.03 0.04 0.04 0.04 0.05 0.05 0.13 0.59  Mac
     5927//normalP           0   0    0    0     0    0    0    0   1    Sing
     5928//icFractions      0.08 0.09 0.09 0.09 0.14 0.15 0.15 0.15 0.15  Mac
     5929//normal             0   0    0    0     0    0    0    0    0   Sing
     5930
     59312. Series Fp[u, v, w, x, y, z]/u2x4+uvy4+v2z4
     5932//--------------------------------------------
     5933//characteristic p 2    3    5    7   11
     5934//icFracP         0.07 0.22 9.67 143 12543
     5935//normalP          0    0    5   42  1566
     5936//icFractions     1.16   *    *   *    *       *: > 6h
     5937//normal            0    0    0   0    0
     5938
     5939//3. Series Fp[u, v, w, x, y, z]/(u2xp+uvyp+v2zp)
     5940//-----------------------------------------------
     5941//characteristic p  2    3    5    7    11   13  17 19 23
     5942//icFracP          0.06 0.07 0.09 0.27 1.81 4.89 26 56 225
     5943//normalP          0     0    0    0    1    2  6  10  27
     5944//icFractions      0.16 1.49 75.00 4009  *    *   *  *  *
     5945//normal            0     0    2    836
     5946//### p=7 normal braucht 807 sec in:
     5947// ideal endid  = phi1(endid);      //### bottelneck'
     5948
     5949//1.
     5950int p = 2;  ring r = p,(u,v,x,y,z),dp; ideal i = x2v-y2u;
     5951//2.
     5952int p = 7; ring r=p,(u,v,w,x,y,z),dp; ideal i=u2x4+uvy4+v2z4;
     5953//3.
     5954int p=23; ring r=p,(u,v,w,x,y,z),dp; ideal i=u2*x^p+uv*y^p+v2*z^p;
     5955
     5956//IRREDUCIBLE EXAMPLES:
     5957//--------------------- 
     5958//timing for MacBookPro 2.2GHz Intel Core 2 Duo, 4GB Ram
     5959//Sing. ix86Mac-darwin version 3-1-0 (3100-2008101314)  Oct 13 2008 14:46:59
     5960//if no time is given: < 1  sec
     5961
     5962//Apply:
     5963list nor = normal(i,"isPrim"); nor;
     5964list nor = normalP(i,"withRing","isPrim"); nor;
     5965def R=nor[1][1]; setring R; norid; normap;
     5966setring r;
     5967norTest(i,nor);
     5968
     5969int tt = timer;
     5970list nor = normalP(i,"withRing","isPrim"); nor;
     5971timer-tt;
     5972int tt = timer;
     5973list nor = normal(i,"isPrim");
     5974timer-tt;
     5975
     5976ring r=19,(x,y,u,v),dp;    //delta -1
     5977ideal i=x2v-y2u;
     5978//norTest 2 sec
     5979
     5980ring r=2,(y,x2,x1),lp;     //delta -1
     5981ideal i=y^4+y^2*x2*x1+x2^3*x1^2+x2^2*x1^3;
     5982//### norid hat 1 Element nach interred
     5983
     5984ring r  = 11,(x,y,z),wp(2,1,2); //alles < 1 sec
     5985ideal i=z3 - xy4 + x2;          //not reduced, delta =0 ok
     5986ideal i=y4+x5+y2x;              //not reduced, delta -1
     5987//interred verkleinert norid
     5988
     5989ring r=3,(u,v,x,y,z),dp;   //delta -1
     5990ideal i=u2x3+uvy3+v2z3;
     5991
     5992ring r=3,(u,v,x,y,z),dp;   //delta -1
     5993ideal i=u2x4+uvy4+v2z4;
     5994//norTest(i,nor);  0 sec, norTest(i,nor) haengt!
     5995
     5996ring r=5,(u,v,x,y,z),dp;   //delta -1
     5997ideal i=u2x6+uvy6+v2z6; 
     5998//normalP 5sec, normalC 1sec
     5999//V5: norTest(i,nor); 45 sec bei normalP, V6 12 sec
     6000//28 sec bei normal
     6001
     6002ring r=5,(u,v,x,y,z),dp;   //delta -1
     6003ideal i=u2x5+uvy5+v2z5;
     6004//normalP 1sec, normalC 1 sec,
     6005//norTest lange: minor(jacob(I),h,J) 193 (308)sec, haengt dann bei M = std(M);
     6006//norTest(i,nor,2); verwenden!
     6007//Sing 3.0-4 orig  >9h! hŠngt bei Q = mstd(Q)[2];
     6008
     6009ring r=2,(y,x),wp(12,5);  //delta 3
     6010ideal i=y5+y2x4+y2x+yx2+x12;
     6011//normalP 0 sec (Test 0 sec), normalC 2 sec (Test 2 sec)
     6012//normalC withGens (ohne interred) 0sec
     6013
     6014ring r=2,(y,x),dp;       //delta= 22
     6015ideal i=y9+y8x+y8+y5+y4x+y3x2+y2x3+yx8+x9;
     6016//normalP 1sec, interred verkleinert norid betraechtlich
     6017//normalC haengt bei minor, ideal im loop wird zu gross ###
     6018//interred bei normalC vergroeesert string um Faktor 4000!
     6019//withGens haengt bei interred in loop 4 (> 10 h) oder
     6020//(nach Ausschalten von interred) bei
     6021//int delt=vdim(std(modulo(f,ideal(p)))); (>?h)
     6022
     6023//Leonard1: (1. Komponente von Leonard),  delta -1
     6024ring r=2,(v,u,z,y,x),dp;
     6025ideal i = z3+zyx+y3x2+y2x3, uyx+z2,uz+z+y2x+yx2, u2+u+zy+zx,
     6026          v3+vux+vz2+vzyx+vzx+uz3+uz2y+z3+z2yx2;
     6027//normalP 5 sec (withRing 9 sec), norTest(i,nor,2); 45 sec
     6028//normalC 102sec, 99sec
     6029//### Zeit wird bei ideal Ann = quotient(SM[2],SL[1]); und bei
     6030// f  = quotient(p*J,J); verbraucht
     6031//withGens (ohne interred) 131sec, norTest(i,nor,2); 2min25sec
     6032//norTest(i,nor,2);  45 sec
     6033
     6034 ring r=2,(y,x),wp(25,21); //Leonard2, delta 232
     6035 ring r=2,(y,x),dp;
     6036 ideal i=
     6037 y^21+y^20*x +y^18*(x^3+x+1) +y^17*(x^3+1) +y^16*(x^4+x)
     6038 +y^15*(x^7+x^6+x^3+x+1) +y^14*x^7 +y^13*(x^8+x^7+x^6+x^4+x^3+1)
     6039 +y^12*(x^9+x^8+x^4+1) +y^11*(x^11+x^9+x^8+x^5+x^4+x^3+x^2)
     6040 +y^10*(x^12+x^9+x^8+x^7+x^5+x^3+x+1)
     6041 +y^9*(x^14+x^13+x^10+x^9+x^8+x^7+x^6+x^3+x^2+1)
     6042 +y^8*(x^13+x^9+x^8+x^6+x^4+x^3+x) +y^7*(x^16+x^15+x^13+x^12+x^11+x^7+x^3+x)
     6043 +y^6*(x^17+x^16+x^13+x^9+x^8+x) +y^5*(x^17+x^16+x^12+x^7+x^5+x^2+x+1)
     6044 +y^4*(x^19+x^16+x^15+x^12+x^6+x^5+x^3+1)
     6045 +y^3*(x^18+x^15+x^12+x^10+x^9+x^7+x^4+x)
     6046 +y^2*(x^22+x^21+x^20+x^18+x^13+x^12+x^9+x^8+x^7+x^5+x^4+x^3)
     6047 +y*(x^23+x^22+x^20+x^17+x^15+x^14+x^12+x^9)
     6048 +(x^25+x^23+x^19+x^17+x^15+x^13+x^11+x^5);
     6049//normalP: dp 2sec withRing 8sec,
     6050//wp 4sec, withRing:51sec Zeit in lin = subst(lin, var(ii), vip); in elimpart ),
     6051//norTest(i,nor,2): haengt bei mstd(norid);
     6052//### normalC: (m. interred): haengt bei endid = interred(endid);
     6053//GEFIXTES INTERRED ABWARTEN. Dann interred aktivieren
     6054//interred(norid) haengt u. mst(norid) zu lange
     6055//(o.interred): haengt bei  haengt bei list SM = mstd(i);
     6056//ideal in der Mitte zu gross
     6057//i = Ideal (size 118, 13 var) fuer die neue Normalisierung
     6058
     6059REDUCIBLE EXAMPLES:
     6060------------------
     6061//Apply:
     6062int tt = timer;
     6063list nor=normalP(i,"isPrim","withRing");
     6064timer-tt;
     6065
     6066list nor = normal(i); nor;
     6067list nor = normalC(i); nor;
     6068list nor = normalC(i, "withGens"); nor;
     6069list nor = normalP(i,"withRing"); nor;
     6070list nor = normalP(i); nor;
     6071def R=nor[1][1]; setring R; norid; normap;
     6072
     6073//Leonhard 4 Komponenten, dim=2, delta: 0,0,0,-1
     6074ring r=2,(v,u,z,y,x),dp;      //lp zu lange
     6075ideal i=z3+zyx+y3x2+y2x3, uyx+z2, v3+vuyx+vux+vzyx+vzx+uy3x2+uy2x+zy3x+zy2x2;
     6076//normalP: 19 sec, withRing: 22 sec
     6077//normalC ohne (mit) interred: 112 (113)sec, equidim: 99sec
     6078//normalC 1. mal 111 sec, (2.mal) 450sec!! 3.mal 172 sec
     6079//(unterschiedlich lange primdec, mit Auswirkungen)
     6080//char 19: normalC: 15sec , withGens: 14sec (o.interr.)
     6081
     6082//----------------------Test Example for special cases -------------------
     6083int tt = timer;
     6084list nor=normalP(i,"withRing");nor;
     6085//list nor=normalP(i,"withRing", "isPrim");nor;
     6086timer-tt;
     6087def R1 = nor[1][1]; setring R1;  norid; normap; interred(norid);
     6088setring r;
     6089
     6090int tt = timer;
     6091list nor=normal(i,"isPrim");nor;
     6092timer-tt;
     6093
     6094ring r = 29,(x,y,z),dp;
     6095ideal i = x2y2,x2z2;       //Nicht equidimensional, equidim reduziert nicht, ok
     6096ideal i  = xyz*(z3-xy4);   //### interred(norid) verkuerzt
     6097//je 0 sec
     6098
     6099ideal j = x,y;
     6100ideal i = j*xy;
     6101equidim(i);           
     6102//hat eingebettete Komponente, equidim rechnet wie in Beschreibung (ok)
     6103   
     6104ring r  = 19,(x,y),dp;
     6105   ideal i = x3-y4;                   //delta = 3
     6106   ideal i = y*x*(x3-y4);             //delta = 11; 0,0,3
     6107   ideal i = (x2-y3)*(x3-y4);         //delta = 13; 1,3
     6108   ideal i = (x-y)*(x3+y2)*(x3-y4);   //delta = 23; 0,1,3     
     6109   ideal i = (x-1)*(x3+y2)*(x2-y3);   //delta = 16; 0,1,1
     6110   ideal i = (x-y^2)^2 - y*x^3;       //delta = 3
     6111   //singularities at not only at 0, hier rechnet equidim falsch
     6112
     6113// -------------------------- General Examples  ---------------------------//Huneke, irred., delta=2 (Version 3-0-4: < 1sec)
     6114//Version 3-0-6 default: 1sec, mit gens 2sec, mit delta 5 sec
     6115//(prim,noFac):ca 7 Min, prim:ca 10 min(wg facstd)
     6116//
     6117// "equidim" < 1sec irred. 5sec
     6118// ring r=31991,(a,b,c,d,e),dp;
     6119ring r=2,(a,b,c,d,e),dp;                    //delta=2
    24516120ideal i=
    245261215abcde-a5-b5-c5-d5-e5,
     
    24586127a4b2c-abc2d3-ab5e-b3c2de-ad5e+2a2bcde2+cd2e4,
    24596128b6c+bc6+a2b4e-3ab2c2de+c4d2e-a3cde2-abd3e2+bce5;
    2460 
    2461 
    2462 //Vasconcelos (dauert laenger: 70 sec)
    2463 ring r=32003,(x,y,z,w,t),dp;
    2464 ideal i=
    2465 x2+zw,
    2466 y3+xwt,
    2467 xw3+z3t+ywt2,
    2468 y2w4-xy2z2t-w3t3;
    2469 
    2470 //Theo1
    2471 ring r=32003,(x,y,z),wp(2,3,6);
     6129//normalC: char 2, 31991: 0 sec (isPrim); char 2, equidim: 7 sec
     6130//norTest(i,nor,2); 1sec
     6131//normalP char 2: 1sec (isPrim)
     6132//size(norid); size(string(norid));21 1219 interred(norid): 21 1245 (0 sec)
     6133
     6134int tt = timer;
     6135list nor=normalC(i);nor;
     6136timer-tt;
     6137
     6138list nor = normalP(i,"isPrim");
     6139
     6140//Vasconcelos irred., delta -1 (dauert laenger)
     6141//auf macbook pro = 20 sec mit alter Version,
     6142//Sing 3-0-6:
     6143// Char 32003: "equidim" 30 sec, "noFac": 30sec
     6144//gens: nach 9 min abgebr (haengt in Lin = ideal(T*syzf);) !!!! Hans zu tun
     6145//Char 2: default (charp) 2 sec, normalC ca 30 sec
     6146//ring r=32003,(x,y,z,w,t),dp;   //dim 2, dim s_locus 1
     6147ring r=2,(x,y,z,w,t),dp;   //dim 2, dim s_locus 1
     6148ideal i= x2+zw, y3+xwt, xw3+z3t+ywt2, y2w4-xy2z2t-w3t3;
     6149//normalC: char 2: 22,  sec (mit und ohne isPrim)
     6150//normalP char 2: 0sec (isPrim)      o. interred
     6151//char 32003: ### haengt in ideal endid  = phi1(endid);
     6152
     6153//-------------------------------------------------------
     6154//kleine Beispiele:
     6155
     6156//Theo1, irred, delta=-1
     6157//normalC: 1sec, normalP: 3 sec
     6158ring r=32003,(x,y,z),wp(2,3,6); //dim 2,dim slocus 1
    24726159ideal i=zy2-zx3-x6;
    2473 
    2474 //Theo1a (CohenMacaulay and regular in codimension 2)
    2475 ring r=32003,(x,y,z,u),wp(2,3,6,6);
     6160//normalC: char 2,19,32003: 0  sec (isPrim)
     6161//normalP (isPrim) char 2,19: 0sec, char 29: 1sec
     6162
     6163//Theo1a, CohenMacaulay regular in codim 2, dim slocus=1, delta=0
     6164//normalC: 0 sec, normalP: haegt in K=preimage(R,phi,L);
     6165ring r=32003,(x,y,z,u),dp;
    24766166ideal i=zy2-zx3-x6+u2;
    2477 
    2478 
    2479 //Theo2
    2480 ring r=32003,(x,y,z),wp(3,4,12);
     6167//normalC: char 2,32003: 0  sec (isPrim)
     6168//normalP (isPrim) char 2: 0sec, char 19: haengt in K = preimage(Q,phi,L);
     6169
     6170//Theo2, irreduzibel, reduziert, < 1sec, delta -1
     6171ring r=0,(x,y,z),wp(3,4,12);
    24816172ideal i=z*(y3-x4)+x8;
    2482 
    2483 //Theo2a
    2484 ring r=32003,(T(1..4)),wp(3,4,12,17);
     6173//normalC: char 2,32003,0: 0  sec (isPrim)
     6174//normalP (isPrim) char 2: 0 1sec, char 19: 1sec char 29: 7 sec
     6175
     6176//Theo2a, reduiziert, 2-dim, dim_slocus=1, alte Version 3 sec,
     6177//normalP ca 30 sec, normalC ca 4sec, delta -1
     6178//ring r=32003,(T(1..4)),wp(3,4,12,17);
     6179//ring r=11,(T(1..4)),dp;
     6180ring r=11,(T(1..4)),wp(3,4,12,17);
    24856181ideal i=
    24866182T(1)^8-T(1)^4*T(3)+T(2)^3*T(3),
     
    24886184T(1)^7+T(1)^3*T(2)^3-T(1)^3*T(3)+T(2)*T(4),
    24896185T(1)^6*T(2)*T(3)+T(1)^2*T(2)^4*T(3)+T(1)^3*T(2)^2*T(4)-T(1)^2*T(2)*T(3)^2+T(4)^2;
    2490 
    2491 //Theo3
    2492 ring r=32003,(x,y,z),wp(3,5,15);
     6186//normalC: char 2,32003: 0  sec (isPrim)
     6187//normalP (isPrim) char 2: 0sec, char 11 2se, char 19: 13sec
     6188//norTest 48sec in char11
     6189//### interred verkuerzt
     6190//char 29: haengt in K = preimage(Q,phi,L);
     6191
     6192//Theo3, irred, 2-dim, 1-dim sing, < 1sec
     6193ring r=11,(x,y,z),wp(3,5,15);
    24936194ideal i=z*(y3-x5)+x10;
    2494 
    2495 
    2496 //Theo4
    2497 ring r=32003,(x,y,z),dp;
    2498 ideal i=(x-y)*(x-z)*(y-z);
    2499 
    2500 //Theo5
    2501 ring r=32003,(x,y,z),wp(2,1,2);
    2502 ideal i=z3-xy4;
     6195//normalC: char 2,0: 0  sec (withRing)
     6196//normalP (withRing) char 2,11: 0sec, char 19: 13sec norTest 12sec(char 11)
     6197
     6198//Theo4 reducible, delta (0,0,0) -1
     6199ring r=29,(x,y,z),dp;
     6200ideal i=(x-y)*(x-z)*(y-z);
     6201//normalC: char 2,32003: 0  sec
     6202//normalP char withRing 2, 29: 0sec, 6sec
    25036203
    25046204//Theo6
    25056205ring r=32003,(x,y,z),dp;
    25066206ideal i=x2y2+x2z2+y2z2;
    2507 
    2508 ring r=32003,(a,b,c,d,e,f),dp;
     6207//normalC: char 2,32003: 0  sec
     6208//normalP char withRing 2, 29: 0sec, 4sec
     6209
     6210//Sturmfels, CM, 15 componenten, alle glatt
     6211ring r=0,(b,s,t,u,v,w,x,y,z),dp;
     6212ideal i= bv+su, bw+tu, sw+tv, by+sx, bz+tx, sz+ty,uy+vx,uz+wx,vz+wy,bvz;
     6213//normalC car 11, 0: 1sec, normalP 0 sec
     6214
     6215//riemenschneider, , dim 3, 5 Komp. delta (0,0,0,0,0), -1
     6216ring r=2,(p,q,s,t,u,v,w,x,y,z),wp(1,1,1,1,1,1,2,1,1,1);
     6217ideal i=xz,vx,ux,su,qu,txy,stx,qtx,uv2z-uwz,uv3-uvw,puv2-puw;
     6218//alles 0 sec in char 2
     6219
     6220//4 Komponenten, alle glatt, 0sec
     6221ring r=11,(x,y,z,t),dp;
     6222ideal i=x2z+xzt,xyz,xy2-xyt,x2y+xyt;
     6223
     6224//dim 3, 2 Komponenten delta (-1,0), -1
     6225ring r=2,(u,v,w,x,y,z),wp(1,1,1,3,2,1);
     6226ideal i=wx,wy,wz,vx,vy,vz,ux,uy,uz,y3-x2;
     6227//alles 0 sec in char 2
     6228//---------------------------------------------------------
     6229int tt = timer;
     6230list nor=normalP(i,"normalC","withRing");nor;
     6231timer-tt;
     6232
     6233//St_S/Y, 3 Komponenten, 2 glatt, 1 normal
     6234//charp haengt (in char 20) in K=preimage(R,phi,L);
     6235//ring r=32003,(b,s,t,u,v,w,x,y,z),dp;
     6236ring r=11,(b,s,t,u,v,w,x,y,z),dp;
     6237ideal i=wy-vz,vx-uy,tv-sw,su-bv,tuy-bvz;