Changeset 85e6ebc in git for Singular/LIB/resjung.lib


Ignore:
Timestamp:
Apr 8, 2011, 6:39:09 PM (13 years ago)
Author:
Burcin Erocal <burcin@…>
Branches:
(u'fieker-DuVal', '117eb8c30fc9e991c4decca4832b1d19036c4c65')(u'spielwiese', 'b9f50b373314e74e83c7c060a651dd2913e1f033')
Children:
67c8311a0aa0789fca80cdd2d2383ac1267e4448
Parents:
6dce0a2f79407a50343791008290059180184804
Message:
Add new version of resjung.lib received from the authors on 27.03.2011.

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

Legend:

Unmodified
Added
Removed
  • Singular/LIB/resjung.lib

    r6dce0a r85e6ebc  
    1 //
    2 version="$Id$";
    3 category="Algebraic Geometry";
     1///////////////////////////////////////////////////////////////////////////////
     2version="$Id: jung.lib,v 1.0 2011/27/03 10:32:00 Singular Exp $";
     3category="Commutative Algebra";
    44info="
    5 LIBRARY:  resjung.lib      Resolution of surface singularities (Desingularization)
    6                            by Jung's Algorithm
    7 AUTHORS:  Philipp Renner,   philipp_renner@web.de
    8 @*        Anne Fruehbis-Krueger, anne@math.uni-hannover.de
    9 OVERVIEW: This library implements resolution of singularities by Jung's algorithm,
    10 @*        which is only applicable to surfaces and persues the following strategy:
    11 @*        1) project surface to the plane
    12 @*        2) resolve singularities of the branch locus
    13 @*        3) pull-back the original surface by this resolution morphism
    14 @*        4) normalize the resulting surface so that the remaining singularities
    15 @*           are of Hirzebruch-Jung type
    16 @*        5) resolve Hirzebruch-Jung singularities explicitly
    17 @*        Currently, the Hirzebruch-Jung singularities are resolved by calling
    18 @*        the procedure resolve from the library resolve.lib, because this is not
    19 @*        overly expensive and the original last step of Jung's algorithm is not
    20 @*        implemented yet.
    21 REFERENCES:
    22 [1] Jung, H.: Darstellung der Funktionen eines algebraischen Koerpers zweier unabhaengigen
    23 Veraenderlichen x,y in der Umgebung x=a, y= b, Journal fuer Reine und Angewandte Mathematik
    24 133,289-314 (1908)
    25 @*  (the origin of this method)
    26 @*[2] J.Kollar: Lectures on Resolution of Singularities, Princeton University Press (2007)
    27 @*  (contains large overview over various known methods for curves and surfaces as well as
    28    a detailed description of the approach in the general case)
     5LIBRARY:  jung.lib      Resolution of surface singularities (Desingularization)
     6                           Algorithm of Jung
     7AUTHOR:  Philipp Renner,   philipp_renner@web.de 
    298
    309PROCEDURES:
    31  jungresolve(J,i)  computes a resolution of the surface given by the
    32                    ideal J using Jungs Method
    33 
    34  clocus(J)         computes the critical locus of the projection of V(J)
    35                    onto the coordinate plane of the last two coordinates
    36  embR(C)           computes a strong embedded resolution of the plane curve V(C)
    37  jungnormal(J,i)   computes intermediate step in Jung's algorithm
    38                    such that all singularities are of Hirzebruch-Jung type
     10 jungresolve(J[,is_noeth])  computes a resolution (!not a strong one) of the
     11                            surface given by the ideal J using Jungs Method,
     12 jungnormal(J[,is_noeth])   computes a representation of J such that all it's
     13                            singularities are of Hirzebruch-Jung type,
     14 jungfib(J[,is_noeth])      computes a representation of J such that all it's
     15                            singularities are quasi-ordinary
    3916";
    4017
     
    4522LIB "primdec.lib";
    4623
    47 //////////////////////////////////////////////////////////////////////////////
    48 //----------------------------------------------------------------------------
    49 //Critical locus for the Weierstrass map induced by the noether normalization
    50 //----------------------------------------------------------------------------
    51 proc clocus(ideal id)
    52 "USAGE:  clocus(ideal J);
     24
     25//-----------------------------------------------------------------------------------------
     26//Main procedure
     27//-----------------------------------------------------------------------------------------
     28 
     29proc jungfib(ideal id, list #)
     30"USAGE:  jungfib(J[,is_noeth]);
    5331@*       J = ideal
    54 ASSUME:  J  = two dimensional ideal in noether position with respect
    55          to the last two variables
    56 RETURN:  A ring containing the ideal Clocus respresenting the critical
    57          locus of the projection V(J)-->C^2 onto the coordinate plane
    58          of the last two coordinates
    59 EXAMPLE: example clocus;  shows an example
     32@*       j = int
     33ASSUME:  J  = two dimensional ideal
     34RETURN:  a list l of rings
     35         l[i] is a ring containing two Ideals: QIdeal and BMap.
     36         BMap defines a birational morphism from V(QIdeal)-->V(J), such that
     37         V(QIdeal) has only quasi-ordinary singularities.
     38         If is_noeth=1 the algorithm assumes J is in noether position with respect to
     39         the last two variables. As a default or if is_noeth = 0 the algorithm computes
     40         a coordinate change such that J is in noether position.
     41         NOTE: since the noether position algorithm is randomized the performance
     42         can vary significantly.
     43EXAMPLE: example jungfib; shows an example.
    6044"
    6145{
     46  int noeth = 0;
     47  if(size(#) == 0)
     48  {
     49     #[1]=0;
     50     noeth=0;
     51  }
     52  if(#[1]==1){
     53    noeth=1;
     54  }
     55  ideal I = id;
     56  I = radical(id);
     57  def A = basering;
     58  int n = nvars(A);                           
     59  if(deg(NF(1,groebner(slocus(id)))) == -1){
     60    list result;
     61    ideal QIdeal = I;
     62    ideal BMap = maxideal(1);
     63    export(QIdeal);
     64    export(BMap);
     65    result[1] = A;
     66    return(result);
     67  }
     68  if(char(A) <> 0){ERROR("only works for characterisitc 0");}  //dummy check
     69  if(dim(I)<> 2){ERROR("dimension is unequal 2");}  //dummy check
     70//Noether Normalization
     71  if(noeth == 0){
     72    if(n==3){
     73      int pos = NoetherP_test(I);
     74      if(pos ==0){
     75        ideal noethpos = NoetherPosition(I);
     76        map phi = A,noethpos;
     77        kill noethpos,pos;
     78      }
     79      else{
     80        ideal NoetherPos = var(pos);
     81        for(int i = 1;i<=3;i++){
     82          if(i<>pos){
     83            NoetherPos = NoetherPos + var(i);
     84          }
     85        }
     86        map phi = A,NoetherPos;
     87        kill i,pos,NoetherPos;
     88      }
     89    }
     90    else{
     91      map phi = A,NoetherPosition(I);
     92    }
     93    ideal NoetherN = ideal(phi(I));  //image of id under the NoetherN coordinate change
     94  }
     95  else{
     96    ideal NoetherN = I;
     97    map phi = A,maxideal(1);
     98  }
     99  kill I; 
     100//Critical Locus
     101  def C2 = branchlocus(NoetherN);
     102  setring C2;
     103//dim of critical locus is 0 then the normalization is an resolution
     104  if(dim(clocus) == 0){
     105    setring A;
     106    list nor = normal(NoetherN);
     107    list result;
     108    int sizeofnor = size(nor[1]);
     109    for(int i = 1;i<=sizeofnor;i++){
     110      def R = nor[1][i];
     111      setring R;
     112      ideal QIdeal = norid;
     113      ideal BMap = BMap;
     114      export(QIdeal);
     115      export(BMap);
     116      result[size(result)+1] = R;
     117      kill R;
     118      setring A;
     119    }
     120    kill sizeofnor;
     121    print("This is a resolution.");
     122    return(result);
     123  }
     124   
     125//dim of critical locus is 1, so compute embedded resolution of the discriminant curve
     126  list embresolvee = embresolve(clocus);
     127 
     128//build the fibreproduct
     129  setring A;
     130  list fibreP = buildFP(embresolvee,NoetherN,phi);
     131  //a list of lists, where fibreP[i] contains the information conserning
     132  //the i-th chart of the fibrepoduct
     133  //fibreP[i] is the ring; QIdeal the quotientideal; BMap is the map from A
     134  return(fibreP);
     135}
     136example{
     137 "EXAMPLE:";echo = 2;
     138//Computing a resolution of singularities of the variety z2-x3-y3
     139 ring r = 0,(x,y,z),dp;
     140 ideal I = z2-x3-y3;
     141//The ideal is in noether position
     142 list l = jungfib(I,1);
     143 def R1 = l[1];
     144 def R2 = l[2];
     145 setring R1;
     146 QIdeal;
     147 BMap;
     148 setring R2;
     149 QIdeal;
     150 BMap;
     151}
     152
     153proc jungnormal(ideal id,list #)
     154"USAGE:  jungnormal(ideal J[,is_noeth]);
     155@*       J = ideal
     156@*       i = int
     157ASSUME:  J  = two dimensional ideal
     158RETURN:  a list l of rings
     159         l[i] is a ring containing two Ideals: QIdeal and BMap.
     160         BMap defines a birational morphism from V(QIdeal)-->V(J), such that
     161         V(QIdeal) has only singularities of Hizebuch-Jung type.
     162         If is_noeth=1 the algorithm assumes J is in noether position with respect to
     163         the last two variables. As a default or if is_noeth = 0 the algorithm computes
     164         a coordinate change such that J is in noether position.
     165         NOTE: since the noether position algorithm is randomized the performance
     166         can vary significantly.
     167EXAMPLE: example jungnormal; gives an example.
     168"
     169{
     170  int noeth = 0;
     171  if(size(#) == 0)
     172  {
     173     #[1]=0;
     174     noeth=0;
     175  }
     176  if(#[1]==1){
     177    noeth=1;
     178  }
     179  def A = basering;
     180  list fibreP = jungfib(id,noeth);
     181  list result;
     182  for(int i =1;i<=size(fibreP);i++){
     183    def R1 = fibreP[i];
     184    setring R1;
     185    map f1 = A,BMap;
     186    list nor = normal(QIdeal);
     187    int sizeofnor = size(nor[1]);
     188    for(int j = 1;j<=sizeofnor;j++){
     189      def Ri2 = nor[1][j];
     190      setring Ri2;
     191      map f2 = R1,normap;
     192      ideal BMap = ideal(f2(f1));
     193      ideal QIdeal = norid;
     194      export(BMap);
     195      export(QIdeal);
     196      result[size(result)+1] = Ri2;
     197      kill Ri2,f2;
     198      setring R1;
     199    }
     200    kill j,sizeofnor,R1;
     201  }
     202  return(result);
     203}
     204example{
     205    "EXAMPLE:";echo = 2;
     206//Computing a resolution of singularities of the variety z2-x3-y3
     207    ring r = 0,(x,y,z),dp;
     208    ideal I = z2-x3-y3;
     209//The ideal is in noether position
     210    list l = jungnormal(I,1);
     211    def R1 = l[1];
     212    def R2 = l[2];
     213    setring R1;
     214    QIdeal;
     215    BMap;
     216    setring R2;
     217    QIdeal;
     218    BMap;
     219}
     220
     221proc jungresolve(ideal id,list #)
     222"USAGE:  jungresolve(ideal J[,is_noeth]);
     223@*       J = ideal
     224@*       i = int
     225ASSUME:  J  = two dimensional ideal
     226RETURN:  a list l of rings
     227         l[i] is a ring containing two Ideals: QIdeal and BMap.
     228         BMap defines a birational morphism from V(QIdeal)-->V(J), such that
     229         V(QIdeal) is smooth. For this the algorithm computes first with
     230         jungnormal a representation of V(J) with Hirzebruch-Jung singularities
     231         and then it uses Villamayor's algorithm to resolve these singularities
     232         If is_noeth=1 the algorithm assumes J is in noether position with respect to
     233         the last two variables. As a default or if is_noeth = 0 the algorithm computes
     234         a coordinate change such that J is in noether position.
     235         NOTE: since the noether position algorithm is randomized the performance
     236         can vary significantly.
     237EXAMPLE: example jungresolve; shows an example.
     238"
     239{
     240  int noeth = 0;
     241  if(size(#) == 0)
     242  {
     243     #[1]=0;
     244     noeth=0;
     245  }
     246  if(#[1]==1){
     247    noeth=1;
     248  }
     249  def A = basering;
     250  list result;
     251  list nor = jungnormal(id,noeth);
     252  for(int i = 1;i<=size(nor);i++){
     253    if(defined(R)){kill R;}
     254    def R3 = nor[i];
     255    setring R3;
     256    def R = changeord("dp");
     257    setring R;
     258    ideal QIdeal = imap(R3,QIdeal);
     259    ideal BMap = imap(R3,BMap);
     260    map f = A,BMap;
     261    if(QIdeal <> 0){
     262      list res = resolve(QIdeal);
     263      for(int j =1;j<=size(res[1]);j++){
     264        def R2 = res[1][j];
     265        setring R2;
     266        if(defined(QIdeal)){kill QIdeal;}
     267        if(defined(BMap)){kill BMap;}
     268        if(BO[1]<>0){ideal QIdeal = BO[1]+BO[2];}
     269        else{ideal QIdeal = BO[2];}
     270        map g = R,BO[5];
     271        ideal BMap = ideal(g(f));
     272        export(QIdeal);
     273        export(BMap);
     274        result[size(result)+1] = R2;
     275        kill R2;
     276      }
     277      kill j,res;
     278    }
     279    else{
     280      result[size(result)+1] = nor[i];
     281    }
     282    setring A;
     283    kill R,R3;
     284  }
     285  return(result);
     286}   
     287example{
     288    "EXAMPLE:";echo = 2;
     289//Computing a resolution of singularities of the variety z2-x3-y3
     290    ring r = 0,(x,y,z),dp;
     291    ideal I = z2-x3-y3;
     292//The ideal is in noether position
     293    list l = jungresolve(I,1);
     294    def R1 = l[1];
     295    def R2 = l[2];
     296    setring R1;
     297    QIdeal;
     298    BMap;
     299    setring R2;
     300    QIdeal;
     301    BMap;
     302}
     303
     304//---------------------------------------------------------------------------------------
     305//Critical locus for the Weierstrass map induced by the noether normalization
     306//---------------------------------------------------------------------------------------
     307static proc branchlocus(ideal id)     
     308{
     309//"USAGE:  branchlocus(ideal J);
     310//       J = ideal
     311//ASSUME:  J  = two dimensional ideal in noether position with respect of
     312//         the last two variables
     313//RETURN:  A ring containing the ideal clocus respresenting the criticallocus
     314// of the projection V(J)-->C^2 on the last two coordinates
     315//EXAMPLE: none"
    62316  def A = basering;
    63317  int n = nvars(A);
    64318  list l = equidim(id);
    65   int i,j;
    66319  int k = size(l);
    67320  ideal LastTwo = var(n-1),var(n);
    68   ideal lowdim = 1;   //the components of id with dimension smaller 2
     321  ideal lowdim = 1;           //the components of id with dimension smaller 2
    69322  if(k>1){
    70     for(j=1;j<k;j++){
    71       lowdim = intersect(lowdim,l[j]);
    72     }
    73   }
    74   //lowdim = radical(lowdim);  // affects performance
    75   ideal I = l[size(l)];
     323    for(int j=1;j<k;j++){
     324      lowdim = intersect(lowdim,radical(l[j]));
     325    }
     326  }
     327  kill k;
     328  lowdim = radical(lowdim);
     329  ideal I = radical(l[size(l)]); 
    76330  poly product=1;
    77   kill l;
    78   for(i=1; i < n-1; i++){
    79   //elimination of all variables exept var(i),var(n-1),var(n)
     331  kill l;                             
     332  for(int i=1; i < n-1; i++){ //elimination of all variables exept var(i),var(n-1),var(n)
    80333    intvec v;
    81     for(j=1; j < n-1; j++){
     334    for(int j=1; j < n-1; j++){
    82335      if(j<>i){
    83336        v[j]=1;
     
    89342    v[size(v)+1]=0;
    90343    v[size(v)+1]=0;
    91     if(defined(ringl)) {kill ringl;}
    92344    list ringl = ringlist(A);
    93345    list l;
     
    97349    ringl[3]=ll;
    98350    kill l,ll;
    99     def R = ring(ringl); //now x_j > x_i > x_n-1 > x_n forall j != i,n-1,n
     351    def R = ring(ringl); //now x_j > x_i > x_n-1 > x_n forall j <> i,n-1,n
    100352    setring R;
    101     ideal J = groebner(fetch(A,I));  //this eliminates the variables
     353    ideal J = groebner(fetch(A,I));//this eliminates the variables
    102354    setring A;
    103     ideal J = fetch(R,J);
     355    ideal J = fetch(R,J);   
    104356    attrib(J,"isPrincipal",0);
    105357    if(size(J)==1){
     
    109361    if(attrib(J,"isPrincipal")==0){
    110362      setring R;
    111       for(j = 1;j<=size(J);j++){   //determines the monic polynomial
    112                                    //in var(i) with coefficents in C2
    113         if(defined(w)) {kill w;}
     363      for(int j = 1;j<=size(J);j++){//determines the monic polynomial in var(i) with coefficents in C2
    114364        intvec w = leadexp(J[j]);
    115365        attrib(w,"isMonic",1);
    116         for(k = 1;k<=size(w);k++){
     366        for(int k = 1;k<=size(w);k++){
    117367          if(w[k] <> 0 && k <> i){
    118368            attrib(w,"isMonic",0);
     
    120370          }
    121371        }
     372        kill k;
    122373        if(attrib(w,"isMonic")==1){
    123374          index = j;
     
    126377        kill w;
    127378      }
     379      kill j;
    128380      setring A;
    129381    }
    130     product = product*resultant(J[index],diff(J[index],var(i)),var(i));
    131                        //Product of the discriminants, which lies in C2
     382    product = product*resultant(J[index],diff(J[index],var(i)),var(i)); 
     383    //Product of the discriminants, which lies in C2
    132384    kill index,J,v;
    133385  }
    134386  ring C2 = 0,(var(n-1),var(n)),dp;
    135387  setring C2;
    136   ideal Clocus = imap(A,product);      //the critical locus is contained in this
     388  ideal clocus= imap(A,product);      //the critical locus is contained in this
    137389  ideal I = preimage(A,LastTwo,lowdim);
    138   Clocus = radical(intersect(Clocus,I));  //radical is necessary since the
    139                                           //resultant is not reduced in general
    140   export(Clocus);
     390  clocus= radical(intersect(clocus,I));
     391  //radical is necessary since the resultant is in gerneral not reduced
     392  export(clocus);
    141393  return(C2);
    142394}
    143 example
    144 {"EXAMPLE:";
    145    echo = 2;
    146    ring R=0,(x,y,z),dp;
    147    ideal I=x2-y3z3;
    148    list li=clocus(I);
    149    def S=li[1];
    150    setring S;
    151    Clocus;
    152 }
    153 ///////////////////////////////////////////////////////////////////////////////
    154 //-----------------------------------------------------------------------------
    155 // Build the fibre product of the embedded resolution and
    156 // the coordinate ring of the variety
    157 //-----------------------------------------------------------------------------
    158 static proc buildFP(list embR,ideal NoetherN, map phi){
     395
     396//-----------------------------------------------------------------------------------------
     397//Build the fibre product of the embedded resolution and the coordinate ring of the variety
     398//-----------------------------------------------------------------------------------------
     399
     400static proc buildFP(list embresolve,ideal NoetherN, map phi){
    159401  def A = basering;
    160   int i,j,k;
    161402  list fibreP;
    162403  int n = nvars(A);
    163   for(i=1;i<=size(embR);i++){
    164     if(defined(R)) {kill R;}
    165     def R = embR[i];
     404  for(int i=1;i<=size(embresolve);i++){
     405    def R = embresolve[i];
    166406    setring R;
    167     list temp = ringlist(A);
    168 // create data for the new ring
    169 // e.g. if A=K[x_1,..,x_n] and R=K[y_1,..,y_m], K[x_1,..,x_n-2,y_1,..,y_m]
    170     for(j = 1; j<= nvars(R);j++){
     407    list temp = ringlist(A); 
     408    //data for the new ring which is, if A=K[x_1,..,x_n] and
     409    //R=K[y_1,..,y_m], K[x_1,..,x_n-2,y_1,..,y_m]
     410    for(int j = 1; j<= nvars(R);j++){
    171411       string st = string(var(j));
    172412       temp[2][n-2+j] = st;
    173413       kill st;
    174414    }
    175     temp[4]    = BO[1];
    176     ideal J = BO[5];        //ideal of the resolution map
     415    temp[4] = BO[1];
     416    ideal J = BO[5];             //ideal of the resolution map
    177417    export(J);
    178418    int m = size(J);
    179419    def R2 = ring(temp);
    180     kill temp;
     420    kill temp; 
    181421    setring R2;
    182     ideal Temp=0;           //defines map from R to R2 which is the inclusion
    183     for(k=n-1;k<n-1+nvars(R);k++){
     422    ideal Temp=0;              //defines map from R to R2 which is the inclusion
     423    for(int k=n-1;k<n-1+nvars(R);k++){
    184424      Temp = Temp + ideal(var(k));
    185425    }
    186426    map f = R,Temp;
    187     kill Temp;
    188     ideal FibPMI = ideal(0);       //defines the map from A to R2
    189     for(k=1;k<=nvars(A)-m;k++){
     427    kill Temp,k;
     428    ideal FibPMI = ideal(0);    //defines the map from A to R2
     429    for(int k=1;k<=nvars(A)-m;k++){
    190430      FibPMI=FibPMI+var(k);
    191431    }
    192432    FibPMI= FibPMI+ideal(f(J));
    193433    map FibMap = A,FibPMI;
    194     kill f,FibPMI;
     434    kill f,FibPMI; 
    195435    ideal TotalT = groebner(FibMap(NoetherN));
    196436    ideal QIdeal = TotalT;
     
    201441    fibreP[i] = R2;
    202442    setring R;
    203     kill J,R,R2,m;
     443    kill J,R,R2,k,j,m;
    204444  }
    205445  return(fibreP);
    206446}
    207447
    208 ///////////////////////////////////////////////////////////////////////////////
    209 //-----------------------------------------------------------------------------
    210 // embedded resolution for curves -- optimized for our situation
    211 //-----------------------------------------------------------------------------
    212 proc embR(ideal C)
    213 "USAGE:  embR(ideal C);
     448//-------------------------------------------------------------------------------
     449//embedded resolution for curves
     450//-------------------------------------------------------------------------------
     451
     452static proc embresolve(ideal C)
     453"USAGE:  embresolve(ideal C);
    214454@*       C = ideal
    215 ASSUME:  C  = ideal of plane curve
     455ASSUME:  C  = ideal of plane curve 
    216456RETURN:  a list l of rings
    217457         l[i] is a ring containing a basic object BO, the result of the
    218          resolution.
    219 THEORY:  Given a plain curve C, an embedded resolution of this curve
    220 @*         by means of a sequence of blow ups at singular points of C is
    221 @*         computed such that the resulting total transform consists
    222 @*         of non-singular components and only has strict normal crossings.
    223 @*         The result of each blow up is represented by means of
    224 @*         affine charts and hence also the final result is represented in
    225 @*         charts, which are collected in a list l of rings. Each ring
    226 @*         in this list corresponds to one chart. The collection of
    227 @*         data describing the ambient space, the strict transform, the
    228 @*         exceptional divisors and the combination of the blow ups
    229 @*         leading to this chart is contained in the list BO which resides
    230 @*         in this ring.
    231 NOTE:      - The best way to look at the data contained in BO is the
    232 @*           procedure showBO from the library resolve.lib.
    233 @*         - The algorithm does not touch normal crossings of V(C).
    234 EXAMPLE: example embR; shows an example
     458         resolution. Whereas the algorithm does not resolve normal
     459         crossings of V(C)
     460EXAMPLE: example embresolve shows an example
    235461"
    236462{
     
    238464  attrib(J,"iswholeRing",1);
    239465  list primdec = equidim(C);
    240   if(size(primdec)==2){
    241 // zero dimensional components of the discrimiant curve
    242 // are smooth an cross normally so they can be ignored
    243 // in the resolution process
     466  if(size(primdec)==2){   
     467  //zero dimensional components of the discrimiant curve are smooth
     468  //an cross normally so they can be ignored in the resolution process
    244469    ideal Lowdim = radical(primdec[1]);
    245470  }
     
    253478  list result = resolve2(BO);
    254479  if(defined(Lowdim)){
    255     for(int i = 1;i<=size(result);i++){
    256 // had zero dimensional components which are now added to the end result
    257       if(defined(R)) {kill R;}
    258       def R = result[i];
    259       setring R;
     480    for(int i = 1;i<=size(result);i++){ 
     481    //had zero dimensional components which I add now to the end result
     482      def RingforEmbeddedResolution = result[i];
     483      setring RingforEmbeddedResolution;
    260484      map f = R2,BO[5];
    261485      BO[2]=BO[2]*f(Lowdim);
    262       kill R,f;
     486      kill RingforEmbeddedResolution,f;
    263487    }
    264488  }
     
    266490}
    267491example
    268 {"EXAMPLE:";
    269   echo=2;
    270   ring R=0,(x,y),dp;
    271   ideal C=x2-y3;
    272   list li=embR(C);
    273   def S=li[1];
    274   setring S;
     492{
     493  "EXAMPLE:";echo=2;
     494  //The following curve is the critical locus of the projection z2-x3-y3
     495  //onto y,z-coordinates.
     496  ring R = 0,(y,z),dp;
     497  ideal C = z2-y3;
     498  list l = embresolve(C);
     499  def R1 = l[1];
     500  def R2 = l[2];
     501  setring R1;
    275502  showBO(BO);
    276 }
    277 ///////////////////////////////////////////////////////////////////////////////
     503  setring R2;
     504  showBO(BO);
     505}
     506
    278507static proc resolve2(list BO){
    279 // computes an embedded resolution for the basic object BO
    280 // and returns a list of rings with BO -- specifically optimized
    281 // to our situation
     508//computes an embedded resolution for the basic object BO and returns
     509//a list of rings with BO
    282510  def H = basering;
    283   int i,j,k;
    284   setring H;  attrib(BO[2],"smoothC",0);
     511  setring H;
     512  attrib(BO[2],"smoothC",0);
    285513  export(BO);
    286514  list result;
    287515  result[1]=H;
    288   attrib(result[1],"isResolved",0);    // has only simple normal crossings
    289   attrib(result[1],"smoothC",0);       // has smooth components
    290   int safety=0;                        // number of runs restricted to 30
     516  attrib(result[1],"isResolved",0);    //has only simple normal crossings
     517  attrib(result[1],"smoothC",0);       //has smooth components
     518  int safety=0;                        //number of runs restricted to 30
    291519  while(1){
    292     int count2 = 0;         // counts the number of smooth charts
     520    int count2 = 0;         //counts the number of smooth charts
    293521    int p = size(result);
    294     for(j = 1;j<=p;j++){
     522    for(int j = 1;j<=p;j++){
    295523      if(attrib(result[j],"isResolved")==0){
    296524        if(defined(R)){kill R;}
    297525        def R = result[j];
    298526        setring R;
    299         if(attrib(result[j],"smoothC")==0){
    300 // has possibly singular components so choose a singular point and blow up
     527        if(attrib(result[j],"smoothC")==0){     
     528        //has possibly singular components so choose a singular point and blow up
    301529          list primdecPC = primdecGTZ(BO[2]);
    302530          attrib(result[j],"smoothC",1);
    303           for(i = 1;i<=size(primdecPC);i++){
     531          for(int i = 1;i<=size(primdecPC);i++){
    304532            ideal Sl = groebner(slocus(primdecPC[i][2]));
    305             if(deg(NF(1,Sl))!=-1){
     533            if(deg(NF(1,Sl))<>-1){
    306534              list primdecSL = primdecGTZ(Sl);
    307535              for(int h =1;h<=size(primdecSL);h++){
     
    312540              if(defined(blowup)){kill blowup;}
    313541              list blowup = blowUpBO(BO,primdecSL[index][2],3);
    314 // if it has only a rational singularity, blow it up,
    315 // else choose some arbitary singular point
    316               if(attrib(primdecSL[1],"isRational")==0){
    317 // if we blew up a non rational singularity, the exeptional divisors
    318 // are reduzible, so we need to separate them
    319                 for(k=1;k<=size(blowup);k++){
     542              //if it has a rational singularity blow it up else choose
     543              //some arbitary singular point
     544              if(attrib(primdecSL[1],"isRational")==0){ 
     545              //if we blow up a non rational singularity the exeptional divisors
     546              //are reduzible so we need to separate them
     547                for(int k=1;k<=size(blowup);k++){
    320548                  def R2=blowup[k];
    321549                  setring R2;
     
    331559                  kill L,R2;
    332560                }
     561                kill k;
    333562              }
    334563              kill primdecSL;
    335564              list hlp;
    336               for(k = 1;k<j;k++){
     565              for(int k = 1;k<j;k++){
    337566                hlp[k]=result[k];
    338567                attrib(hlp[k],"isResolved",attrib(result[k],"isResolved"));
    339568                attrib(hlp[k],"smoothC",attrib(result[k],"smoothC"));
    340569              }
    341               for(k =1;k<=size(blowup);k++){
     570              kill k;
     571              for(int k =1;k<=size(blowup);k++){
    342572                hlp[size(hlp)+1]=blowup[k];
    343573                attrib(hlp[size(hlp)],"isResolved",0);
    344574                attrib(hlp[size(hlp)],"smoothC",0);
    345575              }
    346               for(k = j+1;k<=size(result);k++){
     576              kill k;
     577              for(int k = j+1;k<=size(result);k++){
    347578                hlp[size(hlp)+1]=result[k];
    348579                attrib(hlp[size(hlp)],"isResolved",attrib(result[k],"isResolved"));
     
    350581              }
    351582              result = hlp;
    352               kill hlp;
     583              kill hlp,k;
    353584              i=size(primdecPC);
    354585            }
     
    358589            kill Sl;
    359590          }
    360           kill primdecPC;
     591          kill i,primdecPC;
    361592          j=p;
    362           break;
     593          break; 
    363594        }
    364         else{
    365 // if it has smooth components, determine all the intersection points
    366 // and check whether they are snc or not
     595        else{ //if it has smooth components determine all the intersection
     596              //points and check whether they are snc or not
    367597          int count = 0;
    368598          ideal Collect = BO[2];
    369           for(i = 1;i<=size(BO[4]);i++){
     599          for(int i = 1;i<=size(BO[4]);i++){
    370600            Collect = Collect*BO[4][i];
    371601          }
    372602          list primdecSL = primdecGTZ(slocus(Collect));
    373           for(k = 1;k<=size(primdecSL);k++){
     603          for(int k = 1;k<=size(primdecSL);k++){
    374604             attrib(primdecSL[k],"isRational",1);
     605
    375606          }
     607          kill k;
    376608          if(defined(blowup)){kill blowup;}
    377609          list blowup = blowUpBO(BO,primdecSL[1][2],3);
    378610          if(attrib(primdecSL[1],"isRational")==0){
    379             for(k=1;k<=size(blowup);k++){
     611            for(int k=1;k<=size(blowup);k++){
    380612              def R2=blowup[k];
    381613              setring R2;
     
    391623              kill L,R2;
    392624            }
     625            kill k;
    393626          }
    394           kill Collect;
    395           for(i=1;i<=size(primdecSL);i++){
     627          kill Collect,i;
     628          for(int i=1;i<=size(primdecSL);i++){
    396629            list L = BO[4];
    397630            L[size(L)+1]=BO[2];
     
    404637              list blowup = blowUpBO(BO,primdecSL[i][2],3);
    405638              list hlp;
    406               for(k = 1;k<j;k++){
     639              for(int k = 1;k<j;k++){
    407640                hlp[k]=result[k];
    408641                attrib(hlp[k],"isResolved",attrib(result[k],"isResolved"));
    409642                attrib(hlp[k],"smoothC",attrib(result[k],"smoothC"));
    410643              }
    411               for(k =1;k<=size(blowup);k++){
     644              kill k;
     645              for(int k =1;k<=size(blowup);k++){
    412646                hlp[size(hlp)+1]=blowup[k];
    413647                attrib(hlp[size(hlp)],"isResolved",0);
    414648                attrib(hlp[size(hlp)],"smoothC",1);
    415649              }
    416               for(k = j+1;k<=size(result);k++){
     650              kill k;
     651              for(int k = j+1;k<=size(result);k++){
    417652                hlp[size(hlp)+1]=result[k];
    418653                attrib(hlp[size(hlp)],"isResolved",attrib(result[k],"isResolved"));
     
    420655              }
    421656              result = hlp;
    422               kill hlp;
     657              kill hlp,k;
    423658              j = p;
    424659              break;
     
    429664            kill L;
    430665          }
     666          kill i;
    431667          if(count == size(primdecSL)){
    432668            attrib(result[j],"isResolved",1);
     
    443679      break;
    444680    }
    445     kill count2,p;
     681    kill count2,j,p;
    446682    safety++;
    447683  }
    448684  return(result);
    449685}
    450 ///////////////////////////////////////////////////////////////////////////////
    451 static proc jungfib(ideal id, int noeth)
    452 "USAGE:  jungfib(ideal J, int i);
    453 @*       J = ideal
    454 @*       i = int
    455 ASSUME:  J  = two dimensional ideal
    456 RETURN:  a list l of rings
    457          l[i] is a ring containing two Ideals: QIdeal and BMap.
    458          BMap defines a birational morphism from V(QIdeal)-->V(J), such that
    459          V(QIdeal) has only quasi-ordinary singularities.
    460          If i!=0 then it's assumed that J is in noether position with respect
    461          to the last two variables.
    462          If i=0 the algorithm computes a coordinate change such that J is in
    463          noether position.
    464 EXAMPLE: none, as it is a static procedure
    465 "
    466 {
    467   int i;
    468   if(!defined(noeth)){
    469     int noeth = 0;
    470   }
    471   if(noeth <> 1){print("//WARNING: Noether normalization can make the algorithm unstable");}
    472   ideal I = std(radical(id));
    473   def A = basering;
    474   int n = nvars(A);
    475   if(deg(NF(1,groebner(slocus(id)))) == -1){
    476     list result;
    477     ideal QIdeal = I;
    478     ideal BMap = maxideal(1);
    479     export(QIdeal);
    480     export(BMap);
    481     result[1] = A;
    482     return(result);
    483   }
    484   if(char(A) <> 0){ERROR("only works for characterisitc 0");}  //dummy check
    485   if(dim(I)<> 2){ERROR("dimension is unequal 2");}  //dummy check
    486 
    487 // Noether Normalization
    488   if(noeth == 0){
    489     if(n==3){
    490       int pos = NoetherP_test(I);
    491       if(pos ==0){
    492         if(size(I) == 1){
    493           ideal noethpos = var(1)+var(3),var(2)+var(3),var(3);
    494         }
    495         else{
    496           ideal noethpos = NoetherPosition(I);
    497         }
    498         map phi = A,noethpos;
    499         kill noethpos;
    500       }
    501       else{
    502         ideal NoetherPos = var(pos);
    503         for(i = 1;i<=3;i++){
    504           if(i<>pos){
    505             NoetherPos = NoetherPos + var(i);
    506           }
    507         }
    508         map phi = A,NoetherPos;
    509         kill i,pos,NoetherPos;
    510       }
    511     }
    512     else{
    513       map phi = A,NoetherPosition(I);
    514     }
    515     ideal NoetherN = ideal(phi(I));
    516 //image of id under the NoetherN coordinate change
    517   }
    518   else{
    519     ideal NoetherN = I;
    520     map phi = A,maxideal(1);
    521   }
    522   kill I;
    523 //Critical Locus
    524   def C2 = clocus(NoetherN);
    525   setring C2;
    526 
    527 //dim of critical locus is 0 then the normalization is an resolution
    528   if(dim(Clocus) == 0){
    529     setring A;
    530     list nor = normal(NoetherN);
    531     list result;
    532     for(i = 1;i<=size(nor[1]);i++){
    533       def R = nor[1][i];
    534       setring R;
    535       ideal QIdeal = norid;
    536       ideal BMap = BMap;
    537       export(QIdeal);
    538       export(BMap);
    539       result[size(result)+1] = R;
    540       kill R;
    541     }
    542     print("This is a resolution.");
    543     return(result);
    544   }
    545 
    546 // dim of critical locus is 1, so compute embedded resolution of the discriminant curve
    547   list embRe = embR(Clocus);
    548 
    549 // build the fibreproduct
    550   setring A;
    551   list fibreP = buildFP(embRe,NoetherN,phi);
    552 // a list of lists, where fibreP[i] contains the information
    553 // concerning  the i-th chart of the fibrepoduct
    554 // fibreP[i] is the ring; QIdeal the quotientideal; BMap is the map from A
    555   return(fibreP);
    556 }
    557 ///////////////////////////////////////////////////////////////////////////////
    558 
    559 proc jungnormal(ideal id,int noeth)
    560 "USAGE:  jungnormal(ideal J, int i);
    561 @*       J = ideal
    562 @*       i = int
    563 ASSUME:  J  = two dimensional ideal
    564 RETURN:  a list l of rings
    565          l[k] is a ring containing two Ideals: QIdeal and BMap.
    566          BMap defines a birational morphism from V(QIdeal)-->V(J), such that
    567          V(QIdeal) has only singularities of Hizebuch-Jung type.
    568          If i!=0 then it's assumed that J is in noether position with respect
    569          to the last two variables.
    570          If i=0 the algorithm computes a coordinate change such that J is in
    571          noether position.
    572 EXAMPLE: example jungnormal; shows an example
    573 "
    574 {
    575   def A = basering;
    576   list fibreP = jungfib(id,noeth);
    577   list result;
    578   int i,j;
    579   for(i =1;i<=size(fibreP);i++){
    580     def R1 = fibreP[i];
    581     setring R1;
    582     map f1 = A,BMap;
    583     def nor = normal(QIdeal);
    584     for(j = 1;j<=size(nor[1]);j++){
    585       def R2 = nor[1][j];
    586       setring R2;
    587       map f2 = R1,normap;
    588       ideal BMap = ideal(f2(f1));
    589       ideal QIdeal = norid;
    590       export(BMap);
    591       export(QIdeal);
    592       result[size(result)+1] = R2;
    593       setring R1;
    594       kill R2;
    595     }
    596     kill R1;
    597   }
    598   return(result);
    599 }
    600 example
    601 {"EXAMPLE:";
    602    echo = 2;
    603    ring R=0,(x,y,z),dp;
    604    ideal J=x2+y3z3;
    605    list li=jungnormal(J,1);
    606    li;
    607    def S=li[1];
    608    setring S;
    609    QIdeal;
    610    BMap;
    611 }
    612 ///////////////////////////////////////////////////////////////////////////////
    613 
    614 proc jungresolve(ideal id,int noeth)
    615 "USAGE:  jungresolve(ideal J, int i);
    616 @*       J = ideal
    617 @*       i = int
    618 ASSUME:  J  = two dimensional ideal
    619 RETURN:  a list l of rings
    620          l[k] is a ring containing two Ideals: QIdeal and BMap.
    621          BMap defines a birational morphism from V(QIdeal)-->V(J), such that
    622          V(QIdeal) is smooth. For this the algorithm computes first
    623          a representation of V(J) with Hirzebruch-Jung singularities
    624          and then it currently uses Villamayor's algorithm to resolve
    625          these singularities.
    626          If i!=0 then it's assumed that J is in noether position with respect
    627          to the last two variables.
    628          If i=0 the algorithm computes a coordinate change such that J is in
    629          noether position.
    630 EXAMPLE: example jungresolve; shows an example
    631 "
    632 {
    633   def A = basering;
    634   list result;
    635   int i,j;
    636   list nor = jungnormal(id,noeth);
    637   for(i = 1;i<=size(nor);i++){
    638     if(defined(R)){kill R;}
    639     def R3 = nor[i];
    640     setring R3;
    641     def R = changeord("dp");
    642     setring R;
    643     ideal QIdeal = imap(R3,QIdeal);
    644     ideal BMap = imap(R3,BMap);
    645     map f = A,BMap;
    646     if(QIdeal <> 0){
    647       list res = resolve(QIdeal);
    648       for(j =1;j<=size(res[1]);j++){
    649         def R2 = res[1][j];
    650         setring R2;
    651         if(defined(QIdeal)){kill QIdeal;}
    652         if(defined(BMap)){kill BMap;}
    653         if(BO[1]<>0){ideal QIdeal = BO[1]+BO[2];}
    654         else{ideal QIdeal = BO[2];}
    655         map g = R,BO[5];
    656         ideal BMap = ideal(g(f));
    657         export(QIdeal);
    658         export(BMap);
    659         result[size(result)+1] = R2;
    660         kill R2;
    661       }
    662       kill res;
    663     }
    664     else{
    665       result[size(result)+1] = nor[i];
    666     }
    667     kill R,R3;
    668   }
    669   return(result);
    670 }
    671 example
    672 {"EXAMPLE:";
    673    echo = 2;
    674    ring R=0,(x,y,z),dp;
    675    ideal J=x2+y3z3+y2z5;
    676    list li=jungresolve(J,1);
    677    li;
    678    def S=li[1];
    679    setring S;
    680    QIdeal;
    681    BMap;
    682 }
    683 ///////////////////////////////////////////////////////////////////////////////
     686
    684687static proc NoetherP_test(ideal id){
    685688  def A = basering;
    686689  list ringA=ringlist(A);
    687   int i,j,k;
    688690  int index = 0;
    689   if(size(id)==1 && nvars(A)){  // test if V(id) = C[x,y,z]/<f>
     691  if(size(id)==1 && nvars(A)){  //test if V(id) = C[x,y,z]/<f>
    690692    list L;
    691693    intvec v = 1,1,1;
    692     L[1] = "lp";
     694    L[1] = "lp";     
    693695    L[2] = v;
    694696    kill v;
    695697    poly f = id[1];
    696     for(i = 1;i<=3;i++){
     698    int j = 0;
     699    for(int i = 1;i<=3;i++){
    697700      setring A;
    698       list l = ringA;  //change ordering to lp and var(i)>var(j) j!=i
     701      list l = ringA;  //change ordering to lp and var(i)>var(j) j<>i
    699702      list vari = ringA[2];
    700703      string h = vari[1];
     
    711714      intvec v = leadexp(I[1]);
    712715      attrib(v,"isMonic",1);
    713       for(k = 2;k<=3;k++){
    714 // checks whether f is monic in var(i)
    715         if(v[k] <> 0 || v[1] == 0){
     716      if(defined(k)){kill k;}
     717      for(int k = 2;k<=3;k++){  //checks whether f is monic in var(i)
     718        if(v[k] <> 0 || v[1] == 0){ 
    716719          attrib(v,"isMonic",0);
    717720          j++;
     
    719722        }
    720723      }
     724      kill k;
    721725      if(attrib(v,"isMonic")==1){
    722726        index = i;
     
    729733    }
    730734  }
    731   else{
    732 // not yet a test for more variables
     735  else{     //not yet a test for more variables
    733736    return(index);
    734737  }
    735738}
    736 /////////////////////////////////////////////////////////////////////////
    737 //// copied from resolve.lib, deleting parts of procedures which are  ///
    738 //// not necessary in this setting                                    ///
    739 /////////////////////////////////////////////////////////////////////////
    740 static proc normalCrossing(ideal J,list E,ideal V)
     739
     740////copied from resolve.lib/////////////////
     741static proc normalCrossing(ideal J,list E,ideal V)       
    741742"Internal procedure - no help and no example available
    742743"
     
    744745   int i,d,j;
    745746   int n=nvars(basering);
    746    list E1,E2;
     747   list E1,E2;                   
    747748   ideal K,M,Estd;
    748749   intvec v,w;
    749750
    750    for(i=1;i<=size(E);i++)
     751   for(i=1;i<=size(E);i++) 
    751752   {
    752753      Estd=std(E[i]+J);
     
    757758   }
    758759   E=E1;
    759    for(i=1;i<=size(E);i++)
     760   for(i=1;i<=size(E);i++)   
    760761   {
    761762      v=i;
     
    763764   }
    764765   list ll;
    765    int re=1;
    766 
    767    while((size(E1)>0)&&(re==1))
     766   int re=1;         
     767
     768   while((size(E1)>0)&&(re==1))   
    768769   {
    769       K=E1[1][1];
    770       v=E1[1][2];
     770      K=E1[1][1];                 
     771      v=E1[1][2];                 
    771772      attrib(K,"isSB",1);
    772773      E1=delete(E1,1);
    773       d=n-dim(K);
    774       M=minor(jacob(K),d)+K;
    775       if(deg(std(M+V)[1])>0)
     774      d=n-dim(K);               
     775      M=minor(jacob(K),d)+K;     
     776      if(deg(std(M+V)[1])>0)     
    776777      {
    777778         re=0;
     
    780781      for(i=1;i<=size(E);i++)
    781782      {
    782          for(j=1;j<=size(v);j++){if(v[j]==i){break;}}
    783          if(j<=size(v)){if(v[j]==i){i++;continue;}}
    784          Estd=std(K+E[i]);
     783         for(j=1;j<=size(v);j++){if(v[j]==i){break;}} 
     784         if(j<=size(v)){if(v[j]==i){i++;continue;}}   
     785         Estd=std(K+E[i]);                             
    785786         w=v;
    786787         if(deg(Estd[1])==0){i++;continue;}
    787          if(d==n-dim(Estd))
     788         if(d==n-dim(Estd))                           
    788789         {
    789790            if(deg(std(Estd+V)[1])>0)
     
    812813   return(re);
    813814}
    814 //////////////////////////////////////////////////////////////////////////////
    815 
    816 static proc zariski(ideal id){
    817   def A = basering;
    818   ideal QIdeal = std(id);
    819   ideal BMap= maxideal(1);
    820   export(BMap);
    821   int i,j;
    822   export(QIdeal);
    823   if(dim(QIdeal)<>2){
    824      print("wrong dimension");
    825      list result;
    826      return(result);
    827   }
    828   list result;
    829   result[1]= A;
    830   attrib(result[1],"isSmooth",0);
    831   while(1){
    832     if(defined(count)){kill count;}
    833     int count =0;
    834     for(i = 1;i<= size(result);i++){
    835       attrib(result[i],"isSmooth",1);
    836       def R = result[i];
    837       setring R;
    838       if(!defined(Slocus)){
    839         if(QIdeal[1] == 0){
    840           ideal Slocus = 1;
    841         }
    842         else{
    843           ideal Slocus = std(slocus(QIdeal));
    844         }
    845       }
    846       if(NF(1,Slocus)<>0){
    847         attrib(result[i],"isSmooth",0);
    848       }
    849       else{
    850         count++;
    851       }
    852       kill R;
    853     }
    854     if(count == size(result)){return(result);}
    855     count = 0;
    856     list hlp;
    857     for(i = 1;i<=size(result);i++){
    858       if(attrib(result[i],"isSmooth")==1){
    859         hlp[size(hlp)+1] = result[i];
    860         attrib(hlp[size(hlp)],"isSmooth",attrib(result[i],"isSmooth"));
    861         count++;
    862         i++;
    863         continue;
    864       }
    865       def R = result[i];
    866       setring R;
    867       //print(N1);
    868       list nor = normal(QIdeal);
    869       //print(N2);
    870       for(j = 1;j<= size(nor[1]);j++){
    871         def R3 = nor[1][j];
    872         setring R3;
    873         def R2 = changeord("dp");
    874         setring R2;
    875         ideal norid = imap(R3,norid);
    876         ideal normap = imap(R3,normap);
    877         kill R3;
    878         map f = R,normap;
    879         if(defined(BMap)){kill BMap;}
    880         if(defined(QIdeal)){kill QIdeal;}
    881         ideal BMap = f(BMap);
    882         ideal QIdeal = norid;
    883         export(BMap);
    884         export(QIdeal);
    885         if(QIdeal[1]<> 0){
    886           ideal Slocus = slocus(QIdeal);
    887           Slocus = std(radical(Slocus));
    888         }
    889         else{
    890           ideal Slocus = 1;
    891         }
    892         if(NF(1,Slocus)<> 0){
    893           list blowup = blowUp(norid,Slocus);
    894           for(int k = 1;k<=size(blowup);k++){
    895             def R3 = blowup[k];
    896             setring R3;
    897             ideal QIdeal = sT + aS;
    898             map f = R2,bM;
    899             ideal BMap = f(BMap);
    900             export(BMap);
    901             export(QIdeal);
    902             hlp[size(hlp)+1] = R3;
    903             attrib(hlp[size(hlp)],"isSmooth",0);
    904             kill R3;
    905           }
    906           kill k,blowup;
    907         }
    908         else{
    909           hlp[size(hlp)+1] = R2;
    910           attrib(hlp[size(hlp)],"isSmooth",1);
    911         }
    912         kill R2;
    913       }
    914       kill R,j,nor;
    915     }
    916     kill i;
    917     if(count == size(result)){
    918       return(result);
    919     }
    920     else{
    921       result = hlp;
    922       attrib(result,"isSmooth",0);
    923       kill hlp;
    924     }
    925   }
    926 }
    927 //////////////////////////////////////////////////////////////////////////////
    928 // End of copied part and edited part from resolve.lib
    929 //////////////////////////////////////////////////////////////////////////////
    930 
Note: See TracChangeset for help on using the changeset viewer.