Changeset 7d6fbd in git


Ignore:
Timestamp:
Dec 21, 2021, 4:26:26 PM (2 years ago)
Author:
Hans Schoenemann <hannes@…>
Branches:
(u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
Children:
46f3d0d3afbd8ba07ae6c5d1c137e7cda665cee8
Parents:
1edfd962c6e31ddded2bdf5875ec00ea82c7f349
git-author:
Hans Schoenemann <hannes@mathematik.uni-kl.de>2021-12-21 16:26:26+01:00
git-committer:
Hans Schoenemann <hannes@mathematik.uni-kl.de>2021-12-21 16:26:52+01:00
Message:
add new integralbasis.lib
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • Singular/LIB/integralbasis.lib

    r1edfd9 r7d6fbd  
    1 //////////////////////////////////////////////////////////////////////////////
    2 version="version integralbasis.lib 4.1.2.0 Feb_2019 "; // $Id$
     1///////////////////////////////////////////////////////////////////////////////
     2///////////////////////////////////////////////////////////////////////////////
     3///////////////////////////////////////////////////////////////////////////////
     4version="version integralbasis.lib 4.2.1.3 Dec_2021 "; // $Id$
    35category="Commutative Algebra";
    46info="
    57LIBRARY:  integralbasis.lib  Integral basis in algebraic function fields
    6 AUTHORS:  J. Boehm, j.boehm at mx.uni-saarland.de @*
    7           W. Decker, decker at mathematik.uni-kl.de> @*
    8           S. Laplagne, slaplagn at dm.uba.ar @*
    9           F. Seelisch, seelisch at mathematik.uni-kl.de
     8AUTHORS:  J. Boehm, boehm at mathematik.uni-kl.de
     9          W. Decker, decker at mathematik.uni-kl.de
     10          S. Laplagne, slaplagn at dm.uba.ar
     11          G. Pfister, pfister at mathematik.uni-kl.de
    1012
    1113OVERVIEW:
     
    1921
    2022PROCEDURES:
    21  integralBasis(f, intVar);     Integral basis of an algebraic function field
     23 integralBasis(f, intVar, list #); Integral basis of an algebraic function field
     24 polyDK(int d, int k, list #);     Polynomial with an ordinary multiple point at the origin
     25 monic(poly f);                    Makes a polynomial monic
     26 henselGlobal(poly f, poly g, poly h, int order);  Splits a polynomial using Hensel lifting
    2227";
    2328
    2429LIB "normal.lib";
     30LIB "locnormal.lib";
     31LIB "assprimeszerodim.lib";
     32LIB "puiseuxexpansions.lib";
     33LIB "classify.lib";  // For init_debug() and debug_log() procedures
     34
    2535
    2636///////////////////////////////////////////////////////////////////////////////
     
    3343        must be monic as polynomial in the intVar-th variable.@*
    3444        Optional parameters in list choose (can be entered in any order):@*
    35         Parameters for selecting the algorithm:@*
    36         - \"global\" -> computes the integral basis by computing the
    37         normalization of R/<f>, where R is the base ring.@*
     45        Strategy:@*
     46        - \"global\" -> computes the integral basis by global algorithms. This
     47        forces \"normal\" option. @*
    3848        - \"local\" -> computes the integral basis by computing the
    39         normalization of R/<f> localized at each component of the singular
    40         locus of R/<f>, and then putting everything together.
    41         This is the default option.@*
    42         Other parameters:@*
     49        local contribution at each component of the singular
     50        locus of R/<f>, and then putting everything together. (Default option.)
     51        @*Algorithm:@*
     52        - \"normal\" -> the integral bases are computed using the normalization
     53        algorithm.@*
     54        - \"hensel\" -> the integral bases are computed using a special
     55        algorithm, based on Hensel lifting. (Default option.)
     56        - \"modular\" -> uses modular algorithms for computing Groebner bases,
     57        radicals and decompositions whenever possible. Can be used together
     58        with any of the other options. The ground field must have
     59        characteristic 0. (Default option for ground fields of characteristic
     60        0.)@*
     61        - \"nonModular\" -> do not uses modular algorithms. (Default option for
     62        ground fields of positive charecteristic.)@*
     63        - \"rotation\" -> apply a rotation when there are singularities
     64        with the same X-coordinate @*
     65        - \"noRotation\" -> does not apply a rotation when there are singularities
     66        with the same X-coordinate (Default option.)@*
     67        Other options:@*
     68        - \"atOrigin\" -> will compute the local contribution at the origin
     69        to the integral basis, assuming that the curve has a singularity at
     70        the origin.@*
    4371        - \"isIrred\" -> assumes that the input polynomial f is irreducible,
    4472        and therefore will not check this. If this option is given but f is not
    4573        irreducible, the output might be wrong.@*
    4674        - list(\"inputJ\", ideal inputJ) -> takes as initial test ideal the
    47         ideal inputJ. This option is only for use in other procedures. Using
    48         this option, the result might not be the integral basis.@*
     75        ideal inputJ. This option is only for use in other procedures.
     76        Using this option, the result might not be the integral basis.
    4977        (When this option is given, the global option will be used.)@*
    5078        - list(\"inputC\", ideal inputC) -> takes as initial conductor the
    5179        ideal inputC. This option is only for use in other procedures. Using
    52         this option, the result might not be the integral basis.@*
    53         (When this option is given, the global option will be used.)@*
     80        this option, the result might not be the integral basis. (When this
     81        option is given, the global option will be used.)@*
     82        - \"locBasis\" -> when computing the integral basis at a prime or
     83        primary component, it computes a local basis, that is, a basis that is
     84        integral only over the ring localized at the component. This option
     85        is only valid when \"atOrigin\" is chosen or an initial test ideal or
     86        conductor is given.@*
    5487RETURN: a list, say l, of size 2.
    5588        l[1] is an ideal I and l[2] is a polynomial D such that the integral
     
    6194        element (indicated by intVar), f gives the integral equation and n is
    6295        the degree of f as a polynomial in y.@*
    63 
    6496THEORY:  We compute the integral basis of the integral closure of k[x] in k(x,y)
    6597         by computing the normalization of the affine ring k[x,y]/<f> and
     
    71103{
    72104  int i;
    73   ideal inputJ = 0;
    74   ideal inputC = 0;
    75   string algorithm = "local";     // The default option is "local"
    76   int checkIrred = 1;
     105
     106  ideal inputJ = 0;               // Initial test ideal (local approach)
     107  ideal inputC = 0;               // Initial conductor ideal (local approach)
     108
     109  string strategy = "local";      // The default strategy is "local"
     110  string algorithm = "hensel";    // The default algorithm is "hensel"
     111  string compType = "";
     112  ideal compo = 0;
     113
     114
     115  // Modular algorithms
     116  // The default is not using modular algorithms
     117  int modular;
     118  if(char(basering) > 0)
     119  {
     120    modular = 0;
     121  } else
     122  {
     123    modular = 0;
     124  }
     125
     126  int useRotation = 0;
     127
     128  int checkIrred = 1;   // Checks if the input polynomial is irreducible
     129
     130  int locBasis = 0;     // The default is to compute a non-local basis
     131
     132  int dbg = printlevel - voice + 2;
     133
     134  int check0 = 0;
     135  //int check0 = 1;
    77136
    78137//--------------------------- read the input options---------------------------
     
    82141    {
    83142      if (#[i]=="local"){
    84         algorithm = "local";
     143        strategy = "local";
    85144      }
    86145      if (#[i]=="global"){
    87         algorithm = "global";
     146        strategy = "global";
     147      }
     148      if (#[i]=="modular"){
     149        modular = 1;
     150      }
     151      if (#[i]=="nonModular"){
     152        modular = 0;
     153      }
     154      if (#[i]=="rotation"){
     155        useRotation = 1;
     156      }
     157      if (#[i]=="noRotation"){
     158        useRotation = 0;
     159      }
     160      if (#[i]=="normal"){
     161        algorithm = "normal";
     162      }
     163      if (#[i]=="hensel"){
     164        algorithm = "hensel";
     165      }
     166      if (#[i]=="atOrigin"){
     167        compType = "inputJ";
     168        check0 = 0;            // Do not check at the origin
     169        compo = maxideal(1);
     170        strategy = "atCompo";  // Computes only the local contribution at compo
     171      }
     172      if (#[i]=="check0"){
     173        check0 = 1;
     174      }
     175      if (#[i]=="noCheck0"){
     176        check0 = 0;
     177      }
     178      if (#[i]=="locBasis"){
     179        locBasis = 1;
    88180      }
    89181      if (#[i]=="isIrred"){
     
    91183      }
    92184    }
    93     if(typeof(#[i]) == "list"){
    94       if(size(#[i]) == 2){
    95         if (#[i][1]=="inputJ"){
    96           if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly")){
    97             inputJ = #[i][2];
    98             algorithm = "global";
     185
     186    if(typeof(#[i]) == "list")
     187    {
     188      if(size(#[i]) == 2)
     189      {
     190        if (#[i][1]=="inputJ")
     191        {
     192          if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly"))
     193          {
     194            if(!isZeroIdeal(#[i][2]))
     195            {
     196              // Computes only the local contribution at inputJ
     197              compType = "inputJ";
     198              compo = #[i][2];
     199              strategy = "atCompo";
     200              dbprint(dbg, "// Ideal J read from the input parameters.");
     201            }
    99202          }
    100203        }
    101204      }
    102       if (#[i][1]=="inputC"){
    103         if(size(#[i]) == 2){
    104           if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly")){
    105             inputC = #[i][2];
    106             algorithm = "global";
     205      if (#[i][1]=="inputC")
     206      {
     207        if(size(#[i]) == 2)
     208        {
     209          if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly"))
     210          {
     211            if(!isZeroIdeal(#[i][2]))
     212            {
     213              // Computes only the local contribution at inputC
     214              strategy = "atCompo";
     215              if(algorithm != "normal")
     216              {
     217                compType = "inputJ";
     218                compo = radical(#[i][2]);
     219                dbprint(dbg, "Ideal J read from the input parameters. (The radical of the conductor is used.)");
     220              } else
     221              {
     222                compType = "inputC";
     223                compo = #[i][2];
     224                dbprint(dbg, "Ideal C read from the input parameters.");
     225              }
     226            }
    107227          }
    108228        }
     
    136256
    137257  // The polynomial f must be irreducible.
    138   if(checkIrred == 1){
    139     if(factorize(f)[2] != [1,1]){
     258  if(checkIrred == 1)
     259  {
     260    if(factorize(f)[2] != [1,1])
     261    {
    140262        ERROR("The input polynomial must be irreducible.");
    141263    }
    142264  }
    143265
     266  // If the integral variable is the first one, we change the order of the
     267  // variables.
     268  if(intVar == 1)
     269  {
     270    def R = basering;
     271    list rl = ringlist(R);
     272    def temp = rl[2][1];
     273    rl[2][1] = rl[2][2];
     274    rl[2][2] = temp;
     275    def S = ring(rl);
     276    setring S;
     277    poly f = imap(R, f);
     278    ideal compo = imap(R, compo);
     279  }
     280
     281
     282  // We chech if the only singularity is at the origin.
     283  //check0 = 0;
     284  if(check0 == 1)
     285  {
     286    "Check at origin";
     287    int c0 = checkAt0(f, modular);
     288
     289    if(c0 == 1)
     290    {
     291      compType = "inputJ";
     292      compo = maxideal(1);
     293      strategy = "atCompo";  // Computes only the local contribution at compo
     294    } else {
     295    }
     296  }
     297
    144298//--------------------- computing the integral basis --------------------------
    145   return(cancelCF(integralBasisMain(f, algorithm, inputJ, inputC, intVar)));
     299  dbprint(dbg, "Computing the integral basis...");
     300  list ib = integralBasisMain(f, strategy, algorithm, modular, compType, compo, locBasis, useRotation);
     301
     302  ideal num = ib[1];
     303  poly den = ib[2];
     304  dbprint(dbg, "Integral basis computation finished.");
     305//--------------------- computation finished ----------------------------------
     306
     307  // We reverse the change in the order of the variables.
     308  if(intVar == 1)
     309  {
     310    setring R;
     311    ideal num = imap(S, num);
     312    poly den = imap(S, den);
     313    list ib = num, den;
     314  }
     315  return(cancelCF(ib));
    146316}
    147317example
     
    161331///////////////////////////////////////////////////////////////////////////////
    162332
    163 static proc integralBasisMain(poly f, string algorithm, ideal inputJ, ideal inputC, int intVar)
    164 // Computes the integral basis of R/<f>, from the normalizaiton of R/<f>.
    165 // inputC is the conductor ideal to be used in proc normal.
    166 // If inputC = < 0 >, then the default conductor ideal is used (the full
    167 // jacobian ideal).
    168 // inputJ is the test ideal to be used in proc normal.
    169 // If inputJ = < 0 >, then the default test ideal is used (the radical of the
    170 // conductor).
    171 {
    172   int dbg = printlevel - voice + 2;
     333static proc integralBasisMain(poly f, string strategy, string algorithm, int modular, string compType, ideal compo, int locBasis, int useRotation)
     334// Computes the integral basis of R/<f>.
     335// The integral variable is always the second variable.
     336{
     337
     338  int dbg = printlevel - voice + 3;
    173339  int i, j;
    174   int newRing = 0;    // If = 1, a new ring with dp ordering was used.
     340
     341  int norToInt = 1;   // Indicates if a conversion from normalization to
     342                      // integral basis is needed.
     343
     344  int newRing = 0;    // If newRing = 1, a new ring with dp ordering was used.
     345  list ib;
    175346  def origR = basering;
     347  ideal normalGen;
     348  poly D;
    176349
    177350//--------------------- moving to a ring with dp ordering ---------------------
    178   if(ordstr(origR) != "dp(2),C"){
     351  string s = ordstr(origR);
     352  if(s[1,2] != "dp")
     353  {
    179354    // We change to dp ordering.
    180355    list rl = ringlist(origR);
    181356    list origOrd = rl[3];
    182     list newOrd = list("dp", intvec(1:nvars(origR))), list("C", 0);
     357    int jj = attrib(origR,"maxExp");
     358
     359    list newOrd = list("dp", intvec(1:nvars(origR))), list("C", 0), list("L", jj);
    183360    rl[3] = newOrd;
    184361    def R = ring(rl);
    185362    setring R;
    186363    poly f = fetch(origR, f);
    187     ideal inputJ = fetch(origR, inputJ);
    188     ideal inputC = fetch(origR, inputC);
     364    ideal compo = fetch(origR, compo);
     365    ideal normalGen;
     366    poly D;
    189367    newRing = 1;
    190   } else {
     368  } else
     369  {
    191370    def R = basering;
    192371  }
     
    194373//-------------------------------- basic data ---------------------------------
    195374  // The degree of f with respect to the variable intVar
    196   ideal I = f;
    197   int n = size(coeffs(f, var(intVar))) - 1;
     375  int n = size(coeffs(f, var(2))) - 1;
    198376
    199377  // If the integral variable is the first, then the universal denominator
    200378  // must be a polynomial in the second variable (and viceversa).
    201   string conduStr;
    202   if(intVar == 1){
    203     conduStr = "var2";
    204   } else {
    205     conduStr = "var1";
    206   }
     379  // In this proc, the integral variables is always the second one.
     380  string conduStr = "var1";
    207381  list opts = conduStr;
    208382
    209 //-------------------------- computes the normalization -----------------------
    210   if(algorithm == "local"){
    211     list nor = integralLocal(I, opts);
    212   } else {
    213     if(inputJ != 0){
    214       opts = insert(opts, list("inputJ", inputJ));
    215     }
    216     if(inputC != 0){
    217       opts = insert(opts, list("inputC", inputC));
    218     }
    219     list nor = normal(I, opts);
    220   }
    221   ideal normalGen = nor[2][1];
    222   poly D = normalGen[size(normalGen)];  // The universal denominator
     383//------------------------- computes the integral basis -----------------------
     384  ideal I = f;
     385  int needRed = 1;
     386  if(strategy == "atCompo")
     387  {
     388    norToInt = 0;
     389    if(algorithm == "normal")
     390    {
     391      // Computes the integral basis at the component via normalization
     392      opts = insert(opts, list(compType, compo));
     393      if(locBasis == 1)
     394      {
     395        "Warning: local basis are not implemented for the normalization algorithm. The output will be a global basis.
     396        Use Hensel algorithm instead for computing local basis.";
     397      }
     398      ib = normal(I, opts)[2];
     399      if(size(ib) > 1){
     400        ERROR("The input polynomial is not irreducible.");
     401      }
     402      normalGen = ib[1];
     403      D = normalGen[size(normalGen)];
     404    } else
     405    {
     406      // Computes the integral basis at the component via puiseux expansions
     407      ib = ibLocal(f, compo, locBasis, useRotation);
     408      normalGen = ib[1];
     409      D = ib[2];
     410    }
     411  } else
     412  {
     413    if(strategy == "local")
     414    {
     415      // Computes the integral basis my glueing together the local
     416      // contrubutions
     417      //"_DEBUG_ integralLocal";
     418      ib = integralLocal(I, modular, algorithm, useRotation, opts);
     419      normalGen = ib[1];
     420      D = ib[2];  // The universal denominator
     421      norToInt = ib[3];
     422      needRed = ib[4];
     423    } else
     424    {
     425      // Computes the global integral basis from the global normalization
     426      // This can be changed to locNormal if "var1" is implemented in locNormal
     427      ib = normal(I, opts)[2];
     428      normalGen = ib[1];
     429      D = normalGen[size(normalGen)];
     430    }
     431  }
    223432
    224433  //Debug information
    225   if(dbg >= 2){
    226     "The universal denominator is: ", D;
     434  if(dbg >= 10)
     435  {
     436    "--Generators of the normalization.";
     437    "----Numerator:"; normalGen;
     438    "----Denominator: ", D;
    227439  }
    228440
    229441//--------------- computes the integral basis from the normalization ----------
     442
     443  int ttt = timer;
     444
     445  // Merging the components
     446  debug_log_intbas(5, "norToInt: ", norToInt);
     447  if(norToInt == 1)
     448  {
     449    // We define a new ring where the integral variable is the first (needed for
     450    // reduction) and has the appropiate ordering.
     451    dbprint(dbg, "--Computing the integral basis from the normalization...");
     452    int needGroeb = 0;  // When all the components are already integral basis, no full groebner basis is needed.
     453
     454    list outp = normToInt(f, normalGen, D, needGroeb);
     455  } else
     456  {
     457    list outp = normalGen, normalGen[1];
     458  }
     459  debug_log_intbas(2, "----Time for merging: ", timer-ttt);
     460
     461  // Back to the original ring if needed
     462
     463  if(newRing == 1)
     464  {
     465    setring origR;
     466    list outp;
     467    outp[1] = fetch(R, normalGen);
     468    outp[2] = outp[1][1];
     469  }
     470  return(outp);
     471}
     472
     473///////////////////////////////////////////////////////////////////////////////
     474
     475// Computes the integral basis  by localizing at the different components of
     476// the singular locus.
     477// The main procedure for the computation of the local approach is ibLocal
     478
     479static proc integralLocal(ideal I, int modular, string algorithm, int useRotation, list #)
     480{
     481  int i, ii;
     482  int dbg = printlevel - voice + 4;
     483  int locBasis = 0;   // This is a global procedure.
     484  def R = basering;
     485
     486  poly f = I[1];
     487
     488  list norOut;    // Output of proc normal
     489  ideal norT;     // Temporary data.
     490  ideal norT0;
     491  poly denomT;    // Temporary data.
     492  poly condu;
     493  poly conduT;    // Temporary data
     494
     495  ideal nor;      // Output of normal with the denominator changed to the
     496                  // common denominator.
     497  ideal res;      // The full integral basis
     498
     499  int good;
     500
     501//--------------------------- read the input options---------------------------
     502  int denomOption = 0;
     503  for ( i=1; i <= size(#); i++ )
     504  {
     505    if ( typeof(#[i]) == "string" )
     506    {
     507      if (#[i]=="var1")
     508      {denomOption = 1;}
     509      if (#[i]=="var2")
     510      {denomOption = 2;}
     511    }
     512  }
     513
     514//------------------------ singular locus computation -------------------------
     515  ideal J = f, diff(f, var(1)), diff(f, var(2));
     516
     517  if(dbg >= 4){
     518    "The original singular locus is";
     519    J;
     520  }
     521
     522  if(isOneIdeal(J))
     523  {
     524    list out = trivialBasis(f);
     525    "out";
     526    out;
     527    return(list(out[1], out[2], 0, 0));
     528  }
     529
     530//------------------- components of the singular locus------------------------
     531  int t = timer;
     532  //if(algorithm == "normal")
     533  //{
     534  //  dbprint(dbg, "--Computing the primary decomposition of the singular locus...");
     535  //  list pd = primdecGTZ(J);
     536  //} else {
     537    dbprint(dbg, "--Computing the associated primes of the singular locus...");
     538    if(modular == 1)
     539    {
     540      dbprint(dbg, "  (Using modular algorithm.)");
     541      list pd = assPrimes(J);
     542    } else
     543    {
     544      dbprint(dbg, "  (Using non-modular algorithm.)");
     545      list pd = minAssGTZ(J);
     546    }
     547  //}
     548  //"Time assoc primes: ", timer - t;
     549  debug_log_intbas(2, "----Decomposition time:", timer - t);
     550
     551  dbprint(dbg-2, "----The number of components of the Singular Locus is ", size(pd));
     552  dbprint(dbg-4, "--Components of the Singular Locus:", pd);
     553
     554
     555  // The following commented lines are not needed for integral basis, since
     556  // all components are maximal.
     557  // Computes the maximal components and the components included in them
     558  //list comps = maxComps(pd);
     559  // For each maximal component, it intersects all the components included in it
     560  //list locs = intersectList(comps);
     561
     562//------------------- normalization of each component--------------------------
     563  ideal compo;
     564  poly cofactD, cofactC;
     565  string compType;
     566  dbprint(dbg, "--Computing the integral basis at each component...");
     567  for(i = 1; i <= size(pd); i++){
     568    if(debug_lvl() >= 2){
     569      t = timer;
     570    }
     571    if(dbg >= 2){
     572      t = timer;
     573    }
     574    good = 0;
     575    // If algorithm == "new", we try to use the new algorithm.
     576    //if((algorithm == "hensel") or (algorithm == "hoeij"))
     577    //{
     578      // We localize at the prime components.
     579      compType = "inputJ";
     580      compo = pd[i];
     581    //} else
     582    //{
     583      // We use the primary components given by primdecGTZ as conductor in the
     584      // normalization.
     585      // We need to have the denominator in the transcendental variable. This
     586      // is indicated in #.
     587    //  compType = "inputC";
     588    //  compo = pd[i][1];
     589    //}
     590    dbprint(dbg, "----Computing the integral basis of component ", i);
     591    dbprint(dbg, "----Component: ");
     592    if(dbg>=1){compo;}
     593
     594    norOut = intBasisComp(f, compType, compo, algorithm, locBasis, useRotation, #);
     595    norT = norOut[1];
     596    denomT = norOut[2];
     597    // If the denominator is not a polynomial in x we change it.
     598    if(deg(denomT, intvec(0,1)) > 0)
     599    {
     600      ideal PLex = yInTermOfx(compo);
     601      poly px = PLex[1];
     602      poly newCondu = xCondu(px, norOut, I);
     603      //"Old conductor: ", denomT;
     604      //"New conductor: ", newCondu;
     605      ideal norOutF = changeDenominatorFast(norOut[1], norOut[2], newCondu, I);
     606      norOut[1] = norOutF;
     607      norOut[2] = newCondu;
     608
     609      norT = norOut[1];
     610      denomT = norOut[2];
     611    }
     612    if(size(pd)>1)
     613    {
     614      // We can remove redudant elements considering the generators as an ideal
     615      // because the powers of Y will be added again later for merging
     616      // the bases for the different components.
     617      for(ii = 2; ii <= ncols(norT); ii++)
     618      {
     619        norT[ii] = reduce(norT[ii], groebner(denomT));
     620      }
     621      //norT = groebner(norT);
     622      norT = norT + 0; // Eliminate 0's in the ideal
     623    }
     624    //dbprint(dbg - 3, "------Normalization of component ", i, " output: ", norOut[1]);
     625    dbprint(dbg - 3, "------Normalization of component ", i, " output: ", norT);
     626    dbprint(dbg - 3, "------Denominator: ", denomT);
     627
     628    debug_log_intbas(2, "----Normalization of component ", i, " time: ", timer - t);
     629
     630
     631    // We add up the normalizations at each localization, to construct the
     632    // normalization of the whole ideal.
     633
     634    // We change the denominator of the normalization of the localized ring,
     635    // to have the same denominator for all the normalizations.
     636    //"The denominator is ", denomT;
     637    //"The denominator is changed to ", condu;
     638
     639    // We compute the denominator as the lcm of the denominators.
     640    conduT = condu;
     641    if(condu != 0)
     642    {
     643      condu = lcm(condu, denomT);
     644      cofactD = condu / denomT;
     645      cofactC = condu / conduT;
     646
     647      if(dbg >= 2)
     648      {
     649        "----Changing the denominator...";
     650        if(dbg >= 4)
     651        {
     652          "    from ", denomT, " to ", condu;
     653        }
     654      }
     655      nor = norT * cofactD;
     656      res = res * cofactC;
     657//    We can also use changeDenominator, but it is slower.
     658//      nor = changeDenominator(norT, denomT, condu, I);
     659//      res = changeDenominator(res, conduT, condu, I);
     660    } else
     661    {
     662      condu = denomT;
     663      nor = norT;
     664    }
     665
     666    // We sum the result to the previous results.
     667    if(size(res)>0)
     668    {
     669      res = res, nor;
     670    } else
     671    {
     672      res = nor;
     673    }
     674  }
     675
     676  // needRed indicates if reduction is needed to compute the full integral basis.
     677  // When the local basis are already local integral basis, no reduction is needed.
     678  int needRed;
     679  if(algorithm == "normal")
     680  {
     681    needRed = 1;
     682  } else
     683  {
     684    needRed = 0;
     685  }
     686
     687  if((size(pd) == 1) and (algorithm != "normal"))
     688  {
     689    // Only one prime component in the singular locus, no need to
     690    // merge the compontens together.
     691    int norToInt = 0;
     692    ideal num = norT;
     693    poly den = denomT;
     694  } else
     695  {
     696    dbprint(dbg, "--Putting all the components together...");
     697    ideal num = res;
     698    poly den = condu;
     699    int norToInt = 1;
     700  }
     701  // The output follows the output of proc normal, but we don't return the
     702  // ring structure, only the generators. (We return 0 instead of the ring.)
     703
     704  return(list(num, den, norToInt, needRed));
     705}
     706
     707///////////////////////////////////////////////////////////////////////////////
     708
     709// Integral basis localized at a component.
     710static proc intBasisComp(poly f, string compType, ideal compo, string algorithm, int locBasis, int useRotation, list #)
     711{
     712  int dbg = printlevel - voice + 4;
     713  int good = 0;
     714  list nor;
     715  ideal norT;
     716  poly denomT;
     717
     718  // If algorithm == "hensel", we use the new algorithm.
     719  if(algorithm == "hensel"){
     720    nor = ibLocal(f, compo, locBasis, useRotation);
     721    if(size(nor) != 0){
     722      norT = nor[1];
     723      denomT = nor[2];
     724      good = 1;
     725    } else {
     726      dbprint(dbg, "Using the normalization algorithm.");
     727    }
     728  }
     729  // If not, or if the new algorithm did not succeed, we use normal.
     730  if(good == 0){
     731    // # indicate which is the transcendental variable.
     732    list opts = insert(#, list(compType, compo));
     733    ideal I = f;
     734    nor = normal(I, opts)[2];
     735    if(size(nor) > 1){
     736      ERROR("The input polynomial is not irreducible.");
     737    }
     738    norT = nor[1];
     739    denomT = norT[size(norT)];
     740  }
     741  return(list(norT, denomT));
     742}
     743
     744//////////////////////////////////////////////////////////////////////
     745
     746// Converts generators for the normalization into integral basis shape
     747// The third parameter indicates the variable for the integral basis
     748// It computes an element in the conductor in that variable.
     749static proc normToIntJacob(ideal U, poly den, poly v, poly f)
     750{
     751  ideal jac = jacob(f);
     752  ideal elimJ = elim(jac, v);
     753  poly dJ = elimJ[1];
     754  option("redSB");
     755
     756  ideal PP = changeDenominatorFast(U, den, dJ, f);
     757  list l = normToInt(f, PP, dJ, 1);
     758  return(l);
     759}
     760
     761///////////////////////////////////////////////////////////////////////////////
     762
     763static proc cancelCF(list IB)
     764"USAGE:  cancelCF(IB); IB list of type returned by integralBasis
     765RETURN:  list of same type with common factor cancelled.
     766KEYWORDS: greatest common divisor.
     767"
     768{
     769  int l = size(IB[1]);
     770  poly GrCoDi = IB[2];
     771  int k = l;
     772  while((GrCoDi != 1) && (k >=1))
     773      {
     774        GrCoDi = gcd(GrCoDi,IB[1][k]);
     775        k = k-1;
     776      }
     777  if(GrCoDi != 1)
     778    {
     779      for(k = 1; k <= l; k++)
     780         {
     781           IB[1][k] = IB[1][k]/GrCoDi;
     782         }
     783      IB[2] = IB[2]/GrCoDi;
     784    }
     785  return(IB);
     786}
     787
     788///////////////////////////////////////////////////////////////////////////////
     789
     790// Converts generators for the normalization into integral basis shape
     791static proc normToInt(poly f, ideal normalGen, poly D, int needGroeb)
     792{
     793  int dbg = printlevel - voice + 4;
     794  option("redSB");
     795  f = reduce(f, groebner(D));
     796
     797  dbprint(dbg, "--Computing the integral basis from the normalization...");
     798  int needRed = 1;
     799  int i, j;
     800  intvec vy = (0, 1);
     801  int n = deg(f, vy);
     802  int t;
     803
    230804  // We define a new ring where the integral variable is the first (needed for
    231   // reduction) and has the appropriate ordering.
     805  // reduction) and has the appropiate ordering.
     806  def R = basering;
    232807  list rl = ringlist(R);
    233   rl[2] = list(var(intVar), var(3-intVar));
     808  rl[2] = list(var(2), var(1));
    234809  rl[3] = list(list("C", 0), list("lp", intvec(1,1)));
    235810  def S = ring(rl);
    236811  setring S;
     812  intvec vyS = (1, 0);
    237813
    238814  // We map the elements in the previous ring to the new one
    239815  poly f = imap(R, f);
     816  poly D = imap(R, D);
     817
    240818  ideal normalGen = imap(R, normalGen);
     819
     820  //needGroeb = 1;
     821
     822  if(needGroeb == 1)
     823  {
     824    t = timer;
     825    ideal ID2 = normalGen, f, D;
     826    normalGen= groebner(ID2);
     827    debug_log_intbas(3, "----Time for groebner base of generators: ", timer - t);
     828  }
     829
     830  t = timer;
    241831
    242832  // We create the system of generatos y^i*f_j.
    243833  list l;
    244   ideal red = groebner(f);
    245   for(j = 1; j <= size(normalGen); j++){
    246     l[j] = reduce(normalGen[j], red);
    247   }
    248   for(i = 1; i <= n-1; i++){
    249     for(j = 1; j <= size(normalGen); j++){
    250       l[size(l)+1] = reduce(var(1)^i*normalGen[j], red);
    251     }
    252   }
     834  poly p;
     835
     836  if(needRed == 1)
     837  {
     838    dbprint(dbg - 1, "----Reduction...");
     839    ideal red = groebner(f);
     840    poly pRed;
     841    for(j = 1; j <= ncols(normalGen); j++)
     842    {
     843      l[j] = reduce(normalGen[j], red);
     844      // REDUCTION NEEDED?
     845      if(size(D) == 1)
     846      {
     847        pRed = reduce(l[j], groebner(D));
     848        if(deg(l[j], vyS) == deg(pRed, vyS))
     849        {
     850          l[j] = pRed;
     851        }
     852      }
     853    }
     854    int sl = size(l);
     855    poly pc;
     856
     857    for(j = 1; j <= sl; j++)
     858    {
     859      p = l[j];
     860      if(p != 0)
     861      {
     862        for(i = 1; i < n-deg(l[j], vyS); i++)
     863        {
     864          p = p * var(1);
     865
     866          // REDUCTION NEEDED?
     867          if(size(D) == 1)
     868          {
     869            pRed = reduce(p, groebner(D));
     870            if(deg(p, vyS) == deg(pRed, vyS))
     871            {
     872              p = pRed;
     873            }
     874
     875          }
     876          l[size(l)+1] = p;
     877        }
     878      }
     879    }
     880  } else
     881  {
     882    dbprint(dbg - 1, "----No reduction needed.");
     883    ideal red = groebner(f);
     884    for(j = 1; j <= ncols(normalGen); j++)
     885    {
     886      l[j] = reduce(normalGen[j], red);
     887    }
     888  }
     889
     890  debug_log_intbas(2, "------Time for reduction: ", timer - t);
    253891
    254892  // To eliminate the redundant elements, we look at the polynomials as
     
    260898  matrix coeffi[n + 1][2];
    261899
    262   for(i = 1; i<= size(l); i++){
     900  for(i = 1; i<= size(l); i++)
     901  {
    263902    coeffi = coeffs(l[i], var(1));
    264903    vecs[1..nrows(coeffi), i] = coeffi[1..nrows(coeffi), 1];
    265904  }
    266905  module M = vecs;
     906  dbprint(dbg - 1, "----Triangulating...");
     907
     908  int tt = timer;
    267909  M = std(M);
    268910
     911  debug_log_intbas(2, "------Time for std(M): ", timer - tt);
     912
    269913  // We go back to the original ring.
    270   setring origR;
     914  setring R;
    271915  module M = imap(S, M);
    272   if(newRing == 1){
    273     poly D = fetch(R, D);
    274   }
    275 
     916
     917  tt = timer;
    276918  // We go back from the module to the ring in two variables
    277   ideal G;
    278   poly g;
    279   for(i = 1; i <= size(M); i++){
    280     g = 0;
    281     for(j = 0; j <= n; j++){
    282       g = g + M[i][j+1] * var(intVar)^j;
    283     }
    284     G[i] = g;
    285   }
     919  matrix YY[1][n+1];
     920  for(j = 0; j <= n; j++)
     921  {
     922    YY[1, j+1] = var(2)^j;
     923  }
     924  ideal G = YY * M;
     925
     926  tt = timer;
     927  // Clear common x factor
     928  poly ggcd = D;
     929  for(i = 1; i <= size(M); i++)
     930  {
     931    ggcd = gcd(ggcd, G[i]);
     932  }
     933  G = G / ggcd;
     934  D = D / ggcd;
    286935
    287936  // The first element in the output is the ideal of numerators.
     
    289938  list outp = G, D;
    290939
     940  debug_log_intbas(2, "------Time for triangulation: ", timer - tt);
     941
    291942  return(outp);
    292943}
    293944
     945
     946///////////////////////////////////////////////////////////////////////
     947//
     948//                             The new algorithm
     949//
     950///////////////////////////////////////////////////////////////////////
     951
     952// Computes the integral basis of R[y]/f, with R = k[x] localized at
     953// the x coordinates of the points in P.
     954// It uses the algorithm by Boehm, Decker, Laplagne, Pfister.
     955// If locBasis = 1, it doesnt take into account the the unit from f
     956// after localization
     957
     958static proc ibLocal(poly f, ideal P, int locBasis, int useRotation){
     959  int dbg = printlevel - voice + 2;
     960  P  = groebner(P);
     961  if(dbg - 1 > 0)
     962  {
     963    "Computing the integral basis at P = "; P;
     964  }
     965
     966  int i,j;
     967  int li;
     968  int moved;
     969  poly fT;
     970  def R = basering;
     971  poly x = var(1);
     972  poly y = var(2);
     973  intvec vy = (0,1);
     974  intvec vx = (1,0);
     975
     976  ideal PLex = yInTermOfx(P);
     977  poly px = PLex[1];
     978  poly py = PLex[size(PLex)];
     979  py = monic(py);
     980
     981  // This special case implements the Remark on the paper
     982  // on an alternative approach without coordinate change
     983
     984  useRotation = 0;
     985  //"useRotation: ", useRotation;
     986
     987  if(useRotation == 0)
     988  {
     989    // Case: rational x-coordinate and non-rational y-coordinate.
     990    // We treat this as a special case, so that no coordinate change is used.
     991    if((deg(py, vy) > 1) and (deg(px) <= 1))
     992    {
     993      dbprint(dbg, "Case: non-rational y-coordinate.");
     994
     995      // We move the singularities to x = 0.
     996      fT = moveToVar(f, px, x);
     997
     998      // We compute the integral basis.
     999      list ib = ibNonRatY(fT, py, locBasis);
     1000
     1001      //"ib: ", ib;
     1002
     1003      // If the integral basis was not computed, we return an empty list.
     1004      // Else, we map back the output to the original x coordinate.
     1005      if(size(ib) == 0)
     1006      {
     1007        return(list());
     1008      } else
     1009      {
     1010        for(i = 1; i <= size(ib[1]); i++)
     1011        {
     1012          ib[1][i] = moveFromVar(ib[1][i], px, x);
     1013        }
     1014        ib[2] = moveFromVar(ib[2], px, x);
     1015        return(ib);
     1016      }
     1017    }
     1018  }
     1019
     1020  // This is the general case of non-rational coordinates.
     1021  if((deg(px) > 1) or (deg(py, vy) > 1))
     1022  {
     1023    dbprint(dbg, "Case: non-rational xy-coordinates.");
     1024    // If needed, we make a coord change so that y in terms of x has
     1025    // degree 1.
     1026
     1027    poly fCh = f;
     1028
     1029    if(deg(py,vy) > 1)
     1030    {
     1031      // The degree in y is > 1, hence there are singularities with
     1032      // the same x-coordinate.
     1033      dbprint(dbg, "Conjugated singularities with same x-coordinate.");
     1034      dbprint(dbg, "Linear coordinate change needed.");
     1035
     1036      li = 1;
     1037      poly linCh = x;
     1038      poly invCh = x;
     1039      ideal PCh = P;
     1040      while(((li < 20) and (deg(py,vy) > 1)) or (isXMonic(f)==0)){
     1041        linCh = linCh + y;
     1042        invCh = invCh - y;
     1043        fCh = subst(f, x, x + y);
     1044        PCh = subst(PCh, x, x + y);
     1045        PLex = yInTermOfx(PCh);
     1046        px = PLex[1];
     1047        py = PLex[size(PLex)];
     1048        li++;
     1049      }
     1050
     1051      if(li == 20){
     1052        // No appropiate coordinate change was found. We return an empty
     1053        // list.
     1054        "No appropiate coordinate change found. Procedure failed.";
     1055        return(list());
     1056      } else
     1057      {
     1058        dbprint(dbg, "Coordinate change applied: x ->", linCh);
     1059      }
     1060      fCh = monic(fCh);
     1061      py = monic(py);
     1062    } else
     1063    {
     1064      dbprint(dbg, "No conjugated singularities with same x-coordinate.");
     1065      dbprint(dbg, "No coordinate change needed.");
     1066    }
     1067    dbprint(dbg, "");
     1068
     1069    // We compute the integral basis.
     1070    list ib = ibNonRatXY(fCh, px, py, locBasis);
     1071
     1072    if(li > 0)
     1073    {
     1074      dbprint(dbg, "Integral basis for the transformed polynomial: ");
     1075      dbprint(dbg, ib);
     1076      dbprint(dbg, "px: ", px);
     1077      dbprint(dbg, "py: ", py);
     1078      dbprint(dbg, "invch: ", invCh);
     1079    }
     1080
     1081    // If we applied a linar coordinate change, we apply the inverse
     1082    // transformation
     1083    if(li > 0)
     1084    {
     1085      for(i = 1; i <= size(ib); i++){
     1086        ib[i][1] = subst(ib[i][1], x, invCh);
     1087      }
     1088      px = subst(px, x, invCh);
     1089
     1090    }
     1091
     1092    dbprint(dbg, "ibLocal - Convert to integral basis shape: ", ib, px);
     1093
     1094    ib = convertIB(ib, px);
     1095
     1096
     1097    if(li > 0)
     1098    {
     1099      ib = normToIntJacob(ib[1], ib[2], y, f);
     1100    }
     1101
     1102    dbprint(dbg, "ibLocal - Output of convertIB: ", ib, px);
     1103
     1104    return(ib);
     1105  }
     1106
     1107  // Case of rational coordinates.
     1108  if(deg(py)*deg(px) == 1){
     1109    dbprint(dbg, "Case: rational coordinates.");
     1110
     1111    // Hensel algorithm is used in this case.
     1112    moved = 0;
     1113    if((px != x) || (py != y))
     1114    {
     1115      fT = moveTo(f, px, py);
     1116      moved = 1;
     1117    } else
     1118    {
     1119      fT = f;
     1120    }
     1121
     1122    ideal ibN = ibAt0(fT, locBasis);
     1123
     1124    if(size(ibN) == 0){
     1125      return(list());
     1126    } else {
     1127      if(moved == 1)
     1128      {
     1129        for(i = 1; i <= size(ibN); i++){
     1130          ibN[i] = moveFrom(ibN[i], px, py);
     1131        }
     1132      }
     1133      list ib = list(ibN, ibN[1]);
     1134      return(ib);
     1135    }
     1136  }
     1137}
     1138
     1139////////////////////////////////////////////////////////////////////////
     1140//
     1141//     Procs for handling different kind of singularities
     1142//
     1143////////////////////////////////////////////////////////////////////////
     1144
     1145// Computes the integral basis of R[y]/f, with R = k[x] localized at x=0.
     1146// It uses the algorithm by Boehm, Decker, Laplagne, Pfister.
     1147// If locBasis = 1, it doesnt take into account the the unit from f
     1148// after localization
     1149static proc ibAt0(poly f, int locBasis)
     1150{
     1151  int t;
     1152  int dbg = printlevel - voice + 4;
     1153
     1154  int tt = timer;
     1155
     1156  poly outComp;     // The component outside the origin.
     1157  list b;
     1158
     1159  def R = basering;
     1160  int slN, slD, bestSl;
     1161  int i, j, k;
     1162
     1163  intvec vy = (0,1);
     1164  intvec vx = (1,0);
     1165  poly x = var(1);
     1166  poly y = var(2);
     1167  int n = deg(f, vy);
     1168
     1169  // Degree of the component outside the origin
     1170  poly f0 = subst(f, var(1), 0);
     1171  int d0 = divideBy(f0, var(2))[2];
     1172  int d1 = n - d0;
     1173
     1174  debug_log_intbas(3, "------Time preliminars: ", timer - tt);
     1175  tt = timer;
     1176
     1177  // Starting exponents and minimal polynomials of the Puiseux expansions
     1178
     1179  // Puiseux expansions at the origin
     1180  dbprint(dbg, "--Computing Puiseux expansions at the origin...");
     1181
     1182
     1183
     1184  // puiseux(poly f, int maxDeg, int atOrigin)
     1185  list l = puiseux(f, -1, 1);
     1186  //"puiseux expansion: ", l;
     1187  //~;
     1188
     1189  debug_log_intbas(3, "------Time puiseux expansions: ", timer - tt);
     1190  tt = timer;
     1191
     1192  int totDeg = getTotalDeg(l);
     1193  list classes = getClasses(l);
     1194
     1195  //if(dbg > 5)
     1196  //{
     1197  //  "Puiseux branches: "; classes;
     1198  //}
     1199
     1200  // We compute the building blocks of the basis elements
     1201  dbprint(dbg, "--Building factors of different degrees...");
     1202  list bF = buildFactors(classes);
     1203  //"Factors: "; bF;
     1204
     1205  debug_log_intbas(3, "------Time for the factors: ", timer - tt);
     1206  tt = timer;
     1207
     1208  list slopes = getSlopes(classes);
     1209  intvec md = getDegs(classes);
     1210
     1211  // Tables of vanishing order of diferences of puiseux expansions
     1212  dbprint(dbg, "--Computing vanishing orders...");
     1213  matrix M = valIK(classes);
     1214  list vS = valIKSelf(bF, md);
     1215  list MSelf = vS[1];
     1216
     1217  list bestElem = vS[2];
     1218
     1219  // The highest exponent of the denominator
     1220  if(size(classes) > 1)
     1221  {
     1222    b = ibElement(M, MSelf, d0 - 1, md);
     1223    number maxExp = b[1];
     1224    intvec elem = b[2];
     1225  } else
     1226  {
     1227    if(d0 > 1)
     1228    {
     1229      number maxExp = MSelf[1][size(MSelf[1])];
     1230      intvec elem = d0-1;
     1231    } else {
     1232      // This should never happen, unless we have a non-singular point?
     1233      number maxExp = 0;
     1234      intvec elem = 0;
     1235    }
     1236  }
     1237
     1238  debug_log_intbas(3, "------Time for factors info: ", timer - tt);
     1239  tt = timer;
     1240
     1241  dbprint(dbg, "--Building HenselBlocks...");
     1242  int degExpand = int(maxExp);
     1243  dbprint(dbg, "---- Degree of expansions: ", degExpand);
     1244
     1245
     1246  // Computing hensel blocks...
     1247  list I2Lifted = henselBlocks(f, degExpand, 1);
     1248  debug_log_intbas(3, "------Time Hensel Blocks: ", timer - tt);
     1249  tt = timer;
     1250
     1251
     1252////////////////////////////////////////////////////////////////////////
     1253// RECOMPUTE CLASSES USING HENSEL BLOCKS
     1254// SO THAT THEY ARE COMPUTED IN THE SAME ORDER
     1255
     1256// FIX THIS SO THAT THEY ARE ALWAYS COMPUTED IN THE SAME ORDER AS
     1257// THE HENSEL BLOCKS
     1258
     1259//  if((size(classes) > 1) && (1==0))
     1260  if((size(classes) > 1))
     1261  {
     1262    list classesNew;
     1263    list classesTemp;
     1264    for(i = 1; i <= size(I2Lifted)-1; i++)
     1265    {
     1266      //l = puiseux(I2Lifted[i+1], -1, 1);
     1267      // This is slower, many unneeded terms, we should develop only
     1268      // until they become different. FIX!
     1269      // (or even better, dont recompute but correct blocks in the correct order!)
     1270      //l = puiseux(I2Lifted[i+1], degExpand, 1);
     1271      l = puiseux(I2Lifted[i+1], -1, 1);
     1272      classesTemp = getClasses(l);
     1273      classesNew = classesNew + classesTemp;
     1274    }
     1275
     1276    classes = classesNew;
     1277
     1278    dbprint(dbg, "Building factors of different degrees...");
     1279    bF = buildFactors(classes);
     1280
     1281    slopes = getSlopes(classes);
     1282    md = getDegs(classes);
     1283
     1284    // Tables of vanishing order of diferences of puiseux expansions
     1285    dbprint(dbg, "Computing vanishing orders...");
     1286    M = valIK(classes);
     1287
     1288    vS = valIKSelf(bF, md);
     1289    MSelf = vS[1];
     1290
     1291    bestElem = vS[2];
     1292
     1293    debug_log_intbas(3, "------Time for recomputation: ", timer - tt);
     1294    tt = timer;
     1295  }
     1296
     1297// RECOMPUTATION FINISHED
     1298///////////////////////////////////////////////////////////////////////
     1299
     1300  //dbprint(dbg, "Output of Hensel Blocks: ");
     1301  //dbprint(dbg, I2Lifted);
     1302
     1303  int cl;
     1304
     1305  int nClasses;
     1306  nClasses = size(classes);
     1307
     1308  // ordsFull gives the order of each polynomial in I2Lifted at the other conjugacy classes.
     1309  matrix ordsFull[size(I2Lifted) -1][nClasses];
     1310
     1311  for(i = 1; i <= size(I2Lifted) - 1; i++)
     1312  {
     1313    for(cl = 1; cl <= nClasses; cl++)
     1314    {
     1315      if(i != cl)
     1316      {
     1317        ordsFull[i, cl] = ordAtPol(I2Lifted[i+1], classes[cl][1]);
     1318      }
     1319    }
     1320  }
     1321
     1322  debug_log_intbas(3, "------Time for ordFull: ", timer - tt);
     1323  tt = timer;
     1324
     1325  list ordsBest;
     1326  list ordsTemp;
     1327  for(cl = 1; cl <= nClasses; cl++)
     1328  {
     1329    ordsBest[cl] = list();
     1330    for(i = 1; i <= size(bestElem); i++)
     1331    {
     1332      ordsTemp = list();
     1333      for(j = 1; j <= size(bestElem[i]); j++)
     1334      {
     1335        ordsTemp[j] = ordAtPol(bestElem[i][j], classes[cl][1]);
     1336      }
     1337      ordsBest[cl][i] = ordsTemp;
     1338    }
     1339  }
     1340
     1341  debug_log_intbas(3, "------Time for ordsBest: ", timer - tt);
     1342
     1343  tt = timer;
     1344
     1345  int mdm = 0;
     1346  int mdmTemp;
     1347
     1348  for(i = 1; i <= nClasses; i++)
     1349  {
     1350    mdmTemp = maxDegMerge(n, i, locBasis, d0, M, MSelf, md, classes, I2Lifted, bestElem, ordsFull, ordsBest);
     1351    //"mdmTemp = ", mdmTemp;
     1352    mdm = maxInt(mdm, mdmTemp);
     1353  }
     1354  tt = timer;
     1355
     1356  if(printlevel - voice > 0)
     1357  {
     1358    "Maximum degree required for merging: ", mdm;
     1359  }
     1360
     1361  list ifOut = irreducibleFactors(f, classes, mdm);
     1362  list I2LiftedFull = ifOut[1];
     1363
     1364  if((ifOut[4] == 1))  // Wrong number of factors, recompute orders
     1365  {
     1366    kill ordsFull;
     1367    kill ordsBest;
     1368    kill ordsTemp;
     1369
     1370    matrix ordsFull[size(I2LiftedFull) -1][nClasses];
     1371
     1372    for(i = 1; i <= size(I2LiftedFull) - 1; i++)
     1373    {
     1374      for(cl = 1; cl <= nClasses; cl++)
     1375      {
     1376        if(i != cl)
     1377        {
     1378          ordsFull[i, cl] = ordAtPol(I2LiftedFull[i+1], classes[cl][1]);
     1379        }
     1380      }
     1381    }
     1382
     1383    debug_log_intbas(3, "------Time for ordFull: ", timer - tt);
     1384    tt = timer;
     1385
     1386    list ordsBest;
     1387    list ordsTemp;
     1388    for(cl = 1; cl <= nClasses; cl++)
     1389    {
     1390      ordsBest[cl] = list();
     1391      for(i = 1; i <= size(bestElem); i++)
     1392      {
     1393        ordsTemp = list();
     1394        for(j = 1; j <= size(bestElem[i]); j++)
     1395        {
     1396          ordsTemp[j] = ordAtPol(bestElem[i][j], classes[cl][1]);
     1397        }
     1398        ordsBest[cl][i] = ordsTemp;
     1399      }
     1400    }
     1401  }
     1402
     1403  if(ifOut[3] == 0)
     1404  {
     1405    "Classes are wrongly computed. We need to recompute!";
     1406
     1407    list mergeCl = mergeClassesIF(f, classes, ifOut, mdm);
     1408    classes = mergeCl[1];
     1409    ifOut = mergeCl[2];
     1410
     1411    slopes = getSlopes(classes);
     1412    md = getDegs(classes);
     1413
     1414    ifOut = irreducibleFactors(f, classes, mdm);
     1415    if(ifOut[3] == 0)
     1416    {
     1417      "Recomputation unsuccesfull. Output may be wrong.";
     1418    } else
     1419    {
     1420      "Recomputation succesfull. ";
     1421    }
     1422    I2LiftedFull = ifOut[1];
     1423
     1424    // Check if needed or can be obtained from I2LiftedFull
     1425    bF = buildFactors(classes);
     1426
     1427    // Recomputation of classes info
     1428    // Code should be reused
     1429
     1430    // Tables of vanishing order of diferences of puiseux expansions
     1431    dbprint(dbg, "Computing vanishing orders...");
     1432    M = valIK(classes);
     1433    vS = valIKSelf(bF, md);
     1434    MSelf = vS[1];
     1435
     1436    bestElem = vS[2];
     1437
     1438    nClasses = size(classes);
     1439
     1440    kill ordsFull, ordsBest, ordsTemp;
     1441
     1442    matrix ordsFull[size(I2Lifted) -1][nClasses];
     1443    list ordsBest;
     1444    list ordsTemp;
     1445
     1446    for(i = 1; i <= size(I2LiftedFull) - 1; i++)
     1447    {
     1448      for(cl = 1; cl <= nClasses; cl++)
     1449      {
     1450        if(i != cl)
     1451        {
     1452          ordsFull[i, cl] = ordAtPol(I2LiftedFull[i+1], classes[cl][1]);
     1453        }
     1454      }
     1455    }
     1456
     1457    for(cl = 1; cl <= nClasses; cl++)
     1458    {
     1459      ordsBest[cl] = list();
     1460      for(i = 1; i <= size(bestElem); i++)
     1461      {
     1462        ordsTemp = list();
     1463        for(j = 1; j <= size(bestElem[i]); j++)
     1464        {
     1465          ordsTemp[j] = ordAtPol(bestElem[i][j], classes[cl][1]);
     1466        }
     1467        ordsBest[cl][i] = ordsTemp;
     1468      }
     1469    }
     1470
     1471    //debug_log_intbas(3, "------Time for recomputation: ", timer - tt);
     1472  }
     1473
     1474  for(i = 1; i <= size(I2LiftedFull); i++)
     1475  {
     1476    I2LiftedFull[i] = reduce(I2LiftedFull[i], groebner(var(1)^mdm));
     1477  }
     1478
     1479  ideal IOut;
     1480  list outNormal;
     1481  list bases;
     1482
     1483  list IdOut;
     1484
     1485  list l1, l2;
     1486
     1487  tt = timer;
     1488
     1489  for(i = 1; i <= nClasses; i++)
     1490  {
     1491    // Computing ~A(i)_new... (using modified chinese remainder)
     1492    IdOut[i] = locLocAlgorithm(n, i, locBasis, d0, M, MSelf, md, classes, I2LiftedFull, mdm, bestElem, ordsFull, ordsBest);
     1493    bases = bases + list(IdOut[i]);
     1494  }
     1495  debug_log_intbas(3, "------Time integral basis for all branches: ", timer - tt);
     1496
     1497  if(nClasses > 1)
     1498  {
     1499    // We add some extra polynomials to the integral basis
     1500    // which will simplify the computations
     1501    list enzNum;
     1502    list enzDen;
     1503    poly elemNum;
     1504    number euNum;
     1505    int eu;
     1506    intvec classesInd = 1:nClasses;
     1507    number ordY = ordAtClassesPol(var(2), classes, classesInd);
     1508    for(k = 0; k < n - deg(I2Lifted[1], vy); k++)
     1509    {
     1510      elemNum = var(2)^k;
     1511      euNum = ordY * k;
     1512      eu = int(euNum);
     1513      enzNum = enzNum + list(elemNum);
     1514      enzDen = enzDen + list(var(1)^(eu));
     1515    }
     1516    list enzOut = comDen(enzNum, enzDen);
     1517    ideal enzId = enzOut[2];
     1518    for(k=1; k <=size(enzOut[1]); k++)
     1519    {
     1520      enzId[k+1] = enzOut[1][k];
     1521    }
     1522    list enzOutList = enzId, enzId[1];
     1523    bases = bases + list(enzOutList);
     1524  }
     1525
     1526
     1527  tt = timer;
     1528  if(size(bases) > 1)
     1529  {
     1530    // We compute the local integral basis at the origin
     1531    dbprint(dbg, "--Merging the integral bases for the branches...");
     1532    outNormal = mergeBases(bases);
     1533
     1534    // Check the correct degree for reduction
     1535    //outNormal[1] = reduce(outNormal[1], groebner(x^mdm));
     1536
     1537
     1538    //dbprint(dbg, "----Computing the groebner basis...", outNormal[1]);
     1539    //dbprint(dbg, "----Denominator:", outNormal[2]);
     1540    outNormal[1] = groebner(outNormal[1]);
     1541    dbprint(dbg, "----Merging finished");
     1542    poly fLoc = 1;
     1543    for(k = 2; k <= size(I2LiftedFull); k++)
     1544    {
     1545      fLoc = reduce(fLoc * reduce(I2LiftedFull[k], groebner(x^mdm)), groebner(x^mdm));
     1546    }
     1547    int needGroeb = 1;
     1548    list intBas = normToInt(fLoc, outNormal[1], outNormal[2], needGroeb);
     1549  } else
     1550  {
     1551    list intBas;
     1552    intBas[1] = bases[1][1];
     1553    intBas[2] = bases[1][2];
     1554  }
     1555  debug_log_intbas(3, "------Time for merging bases: ", timer - tt);
     1556
     1557
     1558  // We add the unit outside the origin
     1559  for(k = 0; k < deg(I2LiftedFull[1], vy); k++)
     1560  {
     1561    IOut[k+1] = intBas[2]*var(2)^(k);
     1562  }
     1563  for(k = 1; k <= size(intBas[1]); k++)
     1564  {
     1565    IOut[size(IOut)+1] = intBas[1][k]  * I2Lifted[1];
     1566  }
     1567
     1568  return(IOut);
     1569}
     1570
     1571////////////////////////////////////////////////////////////////////////
     1572
     1573// Computation of the local integral basis at a point with non-rational
     1574// coordinates. We assume that the singularities have no repeated x-coordinate.
     1575// px is a polynomial in the first variable. The roots of px are the
     1576// x-coordinates of the singularities.
     1577// py is a polynomial of degree 1 in y, giving the y-coordinate of the
     1578// singularities.
     1579// locBasis indicates if a local basis is needed.
     1580static proc ibNonRatXY(poly f, poly px, poly py, int locBasis)
     1581{
     1582  int i;
     1583  def R = basering;
     1584
     1585  // We add a root of px to the basering.
     1586  // It will be the x-coordinate of the singularity.
     1587
     1588  def S = splitRingAt(px);
     1589  setring S;
     1590  poly x = var(1);
     1591  poly y = var(2);
     1592  poly f = imap(R, f);
     1593  poly px = imap(R, px);
     1594  poly py = imap(R, py);
     1595
     1596  // We compute the y-coordinate of the singularity
     1597  poly pya = subst(py,x,par(1));
     1598
     1599  // We move the singularity to the origin and compute the integral basis
     1600  poly fT = moveTo(f, var(1) - par(1), pya);
     1601
     1602  //ideal IOut = ibOrigin(fT, locBasis);
     1603  ideal IOut = ibAt0(fT, locBasis);
     1604
     1605  list ib = intBasIdealToList(IOut);
     1606
     1607  dbprint(dbg, "ibNonRatXY - Integral basis at the origin: ", ib);
     1608
     1609
     1610  // The output might contain the root added, and we have to remove it.
     1611  for(i = 1; i <= size(ib); i++){
     1612    // We move back the singularity to original position.
     1613    ib[i][1] = moveFrom(ib[i][1], var(1) - par(1), pya);
     1614
     1615    // We remove the parameter from the denominator.
     1616    // To achieve this, we reduce the polynomial modulo the generators
     1617    // of smaller degree.
     1618    // Note that the simple version ib[i][1] = subst(ib[i][1], par(1), x)
     1619    // does not work in general.
     1620    if(ib[i][2] > 0)
     1621    {
     1622//      "Call to elimPar";
     1623//      ib;
     1624//      ~;
     1625      ib[i][1] = elimPar(ib, i);
     1626    } else
     1627    {
     1628      // When there is no denominator we can simply replace the parameter by 0.
     1629      ib[i][1] = subst(ib[i][1], par(1), 0);
     1630    }
     1631  }
     1632
     1633  dbprint(dbg, "ibNonRatXY - Integral basis after moving back to the original singularity: ", ib);
     1634
     1635  // We map back the output to the original ring.
     1636  setring R;
     1637  list ib = imap(S, ib);
     1638  return(ib);
     1639}
     1640
     1641////////////////////////////////////////////////////////////////////////
     1642
     1643// Input:  a list of different normalization bases, where the first
     1644//         element of each basis is the denominator
     1645// Output: it computes a common denominator for all the bases, and
     1646//         returns a Groebner basis of the ideal generated by all the
     1647//         numerators with this common denominator.
     1648static proc mergeBases(list bases)
     1649{
     1650  int i;
     1651  poly den = 1;
     1652  ideal I;
     1653  ideal IT;
     1654  for(i = 1; i <= size(bases); i++)
     1655  {
     1656    den = lcm(den, bases[i][2]);
     1657  }
     1658  for(i = 1; i <= size(bases); i++)
     1659  {
     1660    IT = bases[i][1] * (den / bases[i][2]);
     1661    I = I + IT;
     1662  }
     1663  list out = I, den;
     1664  return(out);
     1665}
     1666
     1667////////////////////////////////////////////////////////////////////////
     1668
     1669////////////////////////////////////////////////////////////////////////
     1670//
     1671//    MAIN PROCEDURE OF THE NEW APPROACH AS EXPLAINED IN THE
     1672//    PAPER by Boehm, Decker, Laplagne & Pfister
     1673//
     1674////////////////////////////////////////////////////////////////////////
     1675
     1676// Input:  n is the degree of f
     1677//         cl is the index of the class for which the loc basis is computed.
     1678// Output: integral basis for the branches at the origin
     1679// Algorithm: combines the integral basis of each conjugacy class of expansions.
     1680static proc locLocAlgorithm(int n, int cl, int locBasis, int d0, matrix M, list MSelf, intvec md, list classes, list I2Lifted, int mdm, list bestElem, matrix ordsFull, list ordsBest);
     1681{
     1682  if(printlevel - voice > 0)
     1683  {
     1684    "";
     1685    "-- Starting computation of lifted integral basis for class ", cl;
     1686  }
     1687
     1688  int tim = timer;
     1689  def R = basering;
     1690
     1691  int i, j, k;
     1692  list ibNum, ibDen;
     1693  number expUnit;  // The integrality exponent of the local unit
     1694  poly polyUnit;
     1695
     1696  intvec vy = (0,1);
     1697  intvec vx = (1,0);
     1698
     1699  // The elements containing the expansions that vanish outside the origin,
     1700  // but not the locloc unit
     1701  for(k = 0; k < (n - md[cl] - deg(I2Lifted[1], vy)); k++)
     1702  {
     1703    ibNum = ibNum + list(var(2)^k);
     1704    ibDen = ibDen + list(1);
     1705  }
     1706
     1707  poly baseFactor;
     1708  number expBaseFactor;
     1709  poly locLocFactor = 1;
     1710  expUnit = 0;
     1711
     1712  def SS = classes[cl][1];
     1713
     1714  // This corrects for some wrongly computed number of classes
     1715  int nClasses;
     1716//  if(size(classes) > size(I2Lifted) - 1)
     1717//  {
     1718//    nClasses = size(I2Lifted) - 1;
     1719//  } else
     1720//  {
     1721//    nClasses = size(classes);
     1722//  }
     1723  nClasses = size(classes);
     1724
     1725  // We add factors to merge the integral bases for the branches
     1726  // applying Algorithm "Merge Coefficients"
     1727  if(nClasses > 1)
     1728  {
     1729    for(j = 1; j <= size(I2Lifted)-1; j++)
     1730    {
     1731      if(j != cl)
     1732      {
     1733        expUnit = expUnit + number(ordsFull[j, cl]);
     1734        locLocFactor = prodMod(locLocFactor, I2Lifted[1 + j], mdm+1);
     1735      }
     1736    }
     1737    // The first term containing the locloc unit
     1738    expBaseFactor = expUnit;
     1739
     1740    // If the order of hi is not integer, we add a factor.
     1741    // The order of hi is expBaseFactor
     1742    // The order of y is MSelf[cl][1]
     1743    if(int(denominator(expBaseFactor)) > 1)
     1744    {
     1745      // We add the factor corresponding to the full expansions
     1746      list fullPoly;
     1747      for(j = 1; j <= nClasses; j++)
     1748      {
     1749        fullPoly[j] = I2Lifted[j+1];
     1750      }
     1751
     1752      int whichElem = 0;
     1753      int den1;
     1754      int den2;
     1755
     1756      intvec degsCl;
     1757      for(i = 1; i <= size(MSelf); i++)
     1758      {
     1759        degsCl[i] = size(MSelf[i]) + 1;
     1760      }
     1761      intvec chVec = 0:size(MSelf);
     1762
     1763      den1 = 1;
     1764      den2 = int(denominator(expBaseFactor));
     1765
     1766      number ordNewFactor;
     1767
     1768      number oAP;
     1769      number oAPTemp;
     1770
     1771      while(den1 mod den2 != 0)
     1772      {
     1773        chVec = nextSummand(degsCl, chVec, cl);
     1774
     1775        ordNewFactor = 0;
     1776        for(i = 1; i <= nClasses; i++)
     1777        {
     1778          if(i != cl)
     1779          {
     1780            k = chVec[i];
     1781            if(k > 0)
     1782            {
     1783              if(k <= size(bestElem[i]))
     1784              {
     1785                oAP = number(ordsBest[cl][i][k]);
     1786                ordNewFactor = ordNewFactor + oAP;
     1787              } else
     1788              {
     1789                oAP = number(ordsFull[i, cl]);
     1790                ordNewFactor = ordNewFactor + oAP;
     1791              }
     1792            }
     1793          }
     1794        }
     1795        den1 = int(denominator(ordNewFactor));
     1796      }
     1797
     1798      poly newFactor = 1;
     1799      int denNewFactor = den1;
     1800      int powFactor = 0;
     1801
     1802      for(i = 1; i <= size(MSelf); i++)
     1803      {
     1804        k = chVec[i];
     1805        if(k > 0)
     1806        {
     1807          if(k <= size(bestElem[i]))
     1808          {
     1809            newFactor = prodMod(newFactor, bestElem[i][k], mdm);
     1810          } else
     1811          {
     1812            newFactor = prodMod(newFactor, fullPoly[i], mdm);
     1813          }
     1814        }
     1815      }
     1816
     1817      int nnE = int(numerator(expBaseFactor));
     1818      int ddE = int(denominator(expBaseFactor));
     1819      int nnY = int(numerator(ordNewFactor));
     1820
     1821      while(ddE > 1)
     1822      {
     1823        powFactor = powFactor + 1;
     1824        expBaseFactor = expUnit + powFactor * ordNewFactor;
     1825        ddE = int(denominator(expBaseFactor));
     1826      }
     1827      baseFactor = prodMod(locLocFactor, newFactor^powFactor, mdm);
     1828
     1829      if(printlevel - voice >= 0)
     1830      {
     1831        "----Coefficient for merging for class i = ", cl, " (as in Algorithm 7) developed up to order X^" , mdm;
     1832        "------beta_i = ", newFactor, "^", powFactor;
     1833        "------h_i = ", locLocFactor;
     1834        "------c_i = ", expBaseFactor;
     1835      }
     1836    } else
     1837    {
     1838      baseFactor = locLocFactor;
     1839      if(printlevel - voice >= 0)
     1840      {
     1841        "----Coefficient for merging for class i = ", cl, " (as in Algorithm 7) developed up to order X^" , mdm;
     1842        "------beta_i = ", 1;
     1843        "------h_i = ", locLocFactor;
     1844        "------c_i = ", expBaseFactor;
     1845      }
     1846
     1847    }
     1848  } else
     1849  {
     1850    baseFactor = 1;
     1851    expBaseFactor = 0;
     1852  }
     1853  // The initial element
     1854  ibNum = ibNum + list(baseFactor);
     1855  ibDen = ibDen + list(var(1)^int(expBaseFactor));
     1856
     1857  // We put everything together in integral basis shape
     1858  poly elemNum;
     1859  int eu;
     1860  number euNum;
     1861  for(k = (n - md[cl] + 2); k <= n; k++)
     1862  {
     1863    euNum = expBaseFactor + MSelf[cl][k - (n-md[cl]+1)];
     1864    eu = int(euNum);
     1865    elemNum = prodMod(baseFactor, bestElem[cl][k - (n-md[cl]+1)], mdm);
     1866    ibNum = ibNum + list(elemNum);
     1867    ibDen = ibDen + list(var(1)^(eu));
     1868  }
     1869
     1870  ideal IOut;
     1871  for(i = 1; i<=size(ibNum); i++)
     1872  {
     1873    IOut[i] = (ibNum[i] * ibDen[size(ibDen)]) / ibDen[i];
     1874  }
     1875
     1876  list outp = IOut, ibDen[size(ibDen)];
     1877
     1878  // We can reduce modulo the denominator
     1879  //outp[1] = reduce(outp[1], groebner(outp[2]));
     1880
     1881//  if(printlevel - voice >= 0)
     1882//  {
     1883//    "---- Output: "; outp;
     1884//    //~;
     1885//    "";
     1886//  }
     1887
     1888
     1889  return(outp);
     1890}
     1891
     1892////////////////////////////////////////////////////////////////////////
     1893
     1894// Computes the smallest slope of the list of slopes.
     1895static proc getSlope(list slopes)
     1896{
     1897  int i;
     1898  int slN = 1;
     1899  int slD = 0;
     1900  int bestI;
     1901  for(i = 1; i <= size(slopes); i++)
     1902  {
     1903    if(slopes[i][1]*slD < slN * slopes[i][2])
     1904    {
     1905      slN = slopes[i][1];
     1906      slD = slopes[i][2];
     1907      bestI = i;
     1908    }
     1909  }
     1910  return(list(slN, slD, bestI));
     1911}
     1912
     1913////////////////////////////////////////////////////////////////////////
     1914
     1915
     1916// Local factors at the origin of the original polynomial f.
     1917// Input:  a list whose elements are classes of conjugate Puiseux
     1918//         expansions, as returned by proc getClasses.
     1919// Output: a list of lists of three elements.
     1920//         The first element in the i-th list is a list of the factors
     1921//         corresponding to the i-th conjugacy class developed up to the
     1922//         different degrees corresponding to the different possible
     1923//         truncations of the puiseux expansions.
     1924//         The second element is a list of the orders of the corresponding
     1925//         factors.
     1926//         The third element is a list of the degrees of the corresponding
     1927//         factors.
     1928static proc buildFactors(list classes)
     1929{
     1930  int i, j;
     1931  int d = -1;
     1932  int ind;
     1933  int first;
     1934  int k;
     1935  int stop1;
     1936
     1937  int dbg = printlevel - voice + 4;
     1938
     1939  intvec exps;
     1940  intvec expsT;
     1941
     1942  int t;    // Timings
     1943
     1944  intvec vx = (1,0);
     1945  intvec vy = (0,1);
     1946
     1947  def R = basering;
     1948  list facs;
     1949  list ords;
     1950  list degs;
     1951  list gfChecks;
     1952  int den;
     1953  list fFrac;
     1954  poly fGround;
     1955  def S;
     1956
     1957  list polyGround;
     1958
     1959  int isGround = 1;
     1960
     1961  for(i = 1; i <= size(classes); i++)
     1962  {
     1963    facs[i] = list();
     1964    ords[i] = list();
     1965    degs[i] = list();
     1966    gfChecks[i] = list();
     1967
     1968    ind = 1;
     1969    first = 1;
     1970    stop1 = 0;
     1971
     1972    // If there is only one expansion in the class, there is nothing to do
     1973    if((typeof(classes[i][1]) == "ring") or (size(classes[i]) > 1))
     1974    {
     1975      for(j = 1; j <= size(classes[i]); j++)
     1976      {
     1977        if(typeof(classes[i][j]) == "ring")
     1978        {
     1979          S = classes[i][j];
     1980          setring S;
     1981          if(typeof(PE[1][7])!= "none")
     1982          {
     1983
     1984            debug_log_intbas(6, "Computation of the characterisitic exponents from the integral basis. Check if correct or characteristic orders are needed.");
     1985
     1986            //expsT = poly2intvec(PE[1][1]);
     1987            //"Check expsT 1: ", expsT;
     1988            expsT = list2intvec(PE[1][7]);
     1989            //"Check expsT 2: ", expsT;
     1990            //"Compare exps: ";
     1991            //poly2intvec(PE[1][1]);
     1992            //charExp(poly2intvec(PE[1][1]), PE[1][2]);
     1993            //expsT;
     1994          } else
     1995          {
     1996            expsT = deg(PE[1][1]);
     1997          }
     1998          if(j == 1)
     1999          {
     2000            den = PE[1][2];
     2001          }
     2002          setring R;
     2003        } else
     2004        {
     2005          if(typeof(classes[i][j][7]) != "none")
     2006          {
     2007            expsT = list2intvec(classes[i][j][7]);
     2008          } else
     2009          {
     2010            expsT = deg(classes[i][j][1]);
     2011          }
     2012          if(j == 1)
     2013          {
     2014            den = classes[i][1][2];
     2015          }
     2016        }
     2017        if(j > 1)
     2018        {
     2019          exps = appendIntvecs(exps, expsT);
     2020        } else
     2021        {
     2022          exps = expsT;
     2023        }
     2024      }
     2025
     2026      for(k = 1; k <= size(exps); k++)
     2027      {
     2028        d = exps[k];
     2029        if(dbg >= 2)
     2030        {
     2031          "----Building factor of degree < d = ", d;
     2032        }
     2033        t = timer;
     2034        for(j = 1; j <= size(classes[i]); j++)
     2035        {
     2036          if(typeof(classes[i][j]) == "ring")
     2037          {
     2038            if(!defined(dMP))
     2039            {
     2040              int dMP;
     2041            }
     2042            dMP = pardeg(minpoly);
     2043            S = classes[i][j];
     2044
     2045            setring S;
     2046            // d = -1 for computing polynomial of full degree
     2047            if(d >= 0){
     2048              poly fF = jet(PE[1][1], d-1, vx);
     2049            } else
     2050            {
     2051              poly fF = PE[1][1];
     2052            }
     2053            if(dMP > 1)
     2054            {
     2055              poly mp = composePolys(minPolys);
     2056              poly mpX = subst(mp, var(2), var(1));
     2057              poly fFB = buildPolyFracNew(fF, mpX);
     2058              ideal rel = extendBack(fFB, erg[1], dMP);
     2059              matrix CC = coef(fFB, var(1)*var(2));
     2060            } else
     2061            {
     2062              poly fFB = buildPolyFrac(fF);
     2063            }
     2064            setring R;
     2065
     2066            if(dMP > 1)
     2067            {
     2068              ideal rel = imap(S, rel);
     2069              matrix CC = imap(S, CC);
     2070              int kk;
     2071              fFrac[j] = 0;
     2072              for(kk = 1; kk <= ncols(CC); kk++)
     2073              {
     2074                fFrac[j] = fFrac[j] + subst(rel[kk], var(1), par(1)) * CC[1, kk];
     2075              }
     2076            } else
     2077            {
     2078              fFrac[j] = imap(S, fFB);
     2079            }
     2080
     2081            // Cleaning
     2082            setring S;
     2083            kill fF;
     2084            kill fFB;
     2085            setring R;
     2086          } else
     2087          {
     2088            if(d>=0){
     2089              fFrac[j] = var(2) - jet(classes[i][j][1], d-1, vx);
     2090            } else
     2091            {
     2092              fFrac[j] = var(2) - classes[i][j][1];
     2093            }
     2094
     2095          }
     2096        }
     2097
     2098        polyGround = buildPolyGround(fFrac, den);
     2099
     2100        fGround = squarefree(polyGround[1]);
     2101        if (polyGround[2] == 0)
     2102        {
     2103          // "Error. Conjugation classes are wrongly computed. The polynomial obtained is not over the ground field. ";
     2104          ind++;
     2105          isGround = 0;
     2106        } else {
     2107
     2108          debug_log_intbas(4, "------Time for this factor: ", timer - t);
     2109          if(dbg - 1 > 0)
     2110          {
     2111            "------Factor: ", fGround;
     2112          }
     2113
     2114          fFrac = list();
     2115
     2116          // If the degree has not increased, we replaced the previous one.
     2117          // Else, we add it to the list.
     2118          if(first != 1)
     2119          {
     2120            if(deg(fGround, vy) > degs[i][ind])
     2121            {
     2122            ind++;
     2123            } else
     2124            {
     2125            dbprint(dbg - 1, "Factor discarded");
     2126            }
     2127          } else
     2128          {
     2129            first = 0;
     2130          }
     2131        }
     2132        facs[i][ind] = fGround;
     2133        if(d>=0){
     2134          ords[i][ind] = number(d) / number(den);
     2135        } else {
     2136          ords[i][ind] = number(deg(facs[i][ind],vx)) / number(den);
     2137        }
     2138        degs[i][ind] = deg(fGround, vy);
     2139        gfChecks[i][ind] = polyGround[2];
     2140
     2141      }
     2142    }
     2143  }
     2144  return(list(facs, ords, degs, gfChecks, isGround));
     2145}
     2146
     2147////////////////////////////////////////////////////////////////////////
     2148
     2149// Product of conjugate factors
     2150// Input:  a polynomial f over an algebraic extension of the base ring.
     2151//         the minimal polynomial mp as a polynomial in the first variable
     2152//         (it can be different from the minpoly of the ring, since we can be
     2153//         working on an extension of an extension)
     2154// Output: polynomial = the product of (y-f_i) for all conjugate polynomials
     2155//         f_i of f.
     2156static proc buildPolyFracNew(poly f, poly mp)
     2157{
     2158  int i;
     2159  def R = basering;
     2160  int d = deg(mp, intvec(1,0));
     2161  def Q = ring(0, (var(1), var(2), @a, T(1..d)), lp);
     2162  ring S = 0, (var(1), @a), dp;
     2163  poly f = imap(R, f);
     2164  intvec da = (0,1);
     2165  if(deg(f, da) > 0)
     2166  {
     2167    //poly mp = imap(R, mp);
     2168    //mp = subst(mp,var(1),@a);
     2169    setring Q;
     2170    poly f = imap(R, f);
     2171    poly mp = imap(R, mp);
     2172    mp = mp / leadcoef(mp);
     2173    poly fNew;
     2174    poly fNewTemp = 1;
     2175    poly rels = 1;
     2176    ideal I;
     2177    for(i = 1; i <= d; i++)
     2178    {
     2179      rels = rels * (var(1) - T(i));
     2180    }
     2181    matrix c1 = coeffs(rels, var(1));
     2182    matrix c2 = coeffs(mp, var(1));
     2183    for(i = 1; i<=d; i++)
     2184    {
     2185      I[i] = c1[i,1] - c2[i,1];
     2186    }
     2187    I = groebner(I);
     2188
     2189    int t = timer;
     2190    poly fTemp;
     2191    for(i = 1; i<=d; i++)
     2192    {
     2193      fTemp = subst(f, var(3), T(i));
     2194      fNewTemp = fNewTemp * (var(2) - fTemp);
     2195      fNew = reduce(fNewTemp, I);
     2196    }
     2197    setring R;
     2198    poly fNew = imap(Q, fNew);
     2199  } else
     2200  {
     2201    setring R;
     2202    poly fNew = (var(2) - f)^d;
     2203  }
     2204  return(fNew);
     2205}
     2206
     2207////////////////////////////////////////////////////////////////////////
     2208
     2209// Product of conjugate factors
     2210// Input:  a polynomial f over an algebraic extension of the base ring.
     2211// Output: polynomial = the product of (y-f_i) for all conjugate polynomials
     2212//         f_i of f.
     2213static proc buildPolyFrac(poly f)
     2214{
     2215  int i;
     2216  def R = basering;
     2217
     2218  intvec dx = (1,0);
     2219  int degX = deg(f, dx);
     2220
     2221  poly mp = minpoly;
     2222
     2223
     2224  mp = subst(minpoly, @a, var(1));
     2225  int d = pardeg(minpoly);
     2226  def Q = ring(0, (var(1), var(2), @a, T(1..d)), lp);
     2227  ring S = 0, (var(1), @a), dp;
     2228  poly f = imap(R, f);
     2229  intvec da = (0,1);
     2230
     2231  if(deg(f, da) > 0)
     2232  {
     2233    poly mp = imap(R, mp);
     2234    mp = subst(mp,var(1),@a);
     2235    setring Q;
     2236    poly f = imap(S, f);
     2237    poly mp = imap(S, mp);
     2238    mp = mp / leadcoef(mp);
     2239    poly fNew = 1;
     2240    poly rels = 1;
     2241    //ideal I = var(1)^(degX + 1);  // We use this to reduce modulo x^maxDeg
     2242    ideal I;  // We use this to reduce modulo x^maxDeg
     2243    for(i = 1; i <= d; i++)
     2244    {
     2245      rels = rels * (var(1) - T(i));
     2246    }
     2247    matrix c1 = coeffs(rels, var(1));
     2248    matrix c2 = coeffs(mp, @a);
     2249    for(i = 1; i<=d; i++)
     2250    {
     2251      I[i] = c1[i,1] - c2[i,1];
     2252    }
     2253    I = groebner(I);
     2254
     2255    int t = timer;
     2256    poly fTemp;
     2257    for(i = 1; i<=d; i++)
     2258    {
     2259      fTemp = subst(f, @a, T(i));
     2260      fNew = fNew * (var(2) - fTemp);
     2261      fNew = reduce(fNew, I);
     2262    }
     2263    debug_log_intbas(4,"--------Time for product reduction: ", timer - t);
     2264
     2265    setring R;
     2266    poly fNew = imap(Q, fNew);
     2267
     2268  } else
     2269  {
     2270    setring R;
     2271    poly fNew = (var(2) - f)^d;
     2272  }
     2273  return(fNew);
     2274}
     2275
     2276////////////////////////////////////////////////////////////////////////
     2277
     2278// Polynomail over the ground field.
     2279// Input:  a list of polynomials representing Puiseux expansions and
     2280//         an integer sD representing the denominator of the exponents in
     2281//         all the expansions.
     2282// Output: polynomial = the product of all the expansions in the input list.
     2283//         The common denominator is now cancelled with the numerators.
     2284static proc buildPolyGround(list fFrac, int sD)
     2285{
     2286  int i;
     2287  int gfCheck = 1;  // The polynomial computed is over the ground field.
     2288                    // This means the conjugacy  is computed correctly.
     2289  def R = basering;
     2290  poly f = 1;
     2291  intvec vx = (1, 0);
     2292  for(i = 1; i <= size(fFrac); i++)
     2293  {
     2294    f = f * fFrac[i];
     2295  }
     2296  ring P = (0, @a), (@x, @y, @X), dp;
     2297  poly fNew = fetch(R, f);
     2298  poly f2 = reduce(fNew, groebner(@X-@x^sD));
     2299  if(deg(f2, (1,0,0)) > 0)
     2300  {
     2301    "f2", f2;
     2302    "Polynomial is not over the ground field";
     2303    ~;
     2304    gfCheck = 0;
     2305  }
     2306  f2 = subst(f2, @X, @x);
     2307  setring R;
     2308  poly fNew = fetch(P, f2);
     2309  return(list(fNew, gfCheck));
     2310}
     2311
     2312////////////////////////////////////////////////////////////////////////
     2313
     2314// Valuations of products of expansions with respect to expansions of the
     2315// same class.
     2316// Input:  a list bF of lists of polynomials, as given by proc buildFactors.
     2317//         an intvec md representing the degrees of the minimal polynomials
     2318//         of the extension used for each expansion.
     2319// Output: two lists. The i-th element of the first list is a list of
     2320//         numbers, representing the valutations of taking 1 to d-1 expansions
     2321//         in the i-th conjugacy class given in bF, with respect to an
     2322//         expansion of that same class
     2323// [Example 1]
     2324static proc valIKSelf(list bF, intvec md)
     2325{
     2326  int i, k;
     2327  list facs = bF[1];
     2328  list ords = bF[2];    // The order of the factors
     2329  list degs = bF[3];    // The degree of the factors in y
     2330  int b = size(ords);    // Number of blocks
     2331  list MSelf;
     2332  list bestElem;
     2333  number o;
     2334  int d, dT;
     2335  poly p;
     2336  for(i = 1; i <= b; i++)
     2337  {
     2338    MSelf[i] = list();
     2339    bestElem[i] = list();
     2340    for(d = 1; d < md[i]; d++)
     2341    {
     2342      o = d * number(ords[i][1]);
     2343      for(k = 2; k <= size(degs[i]); k++)
     2344      {
     2345        o = o + number(int(d div degs[i][k])) * (number(ords[i][k]) - number(ords[i][k-1]));
     2346      }
     2347      MSelf[i][d] = o;
     2348
     2349      p = 1;
     2350      // fa[3] are the degrees of the polynomials
     2351      dT = d;
     2352      for(k = size(degs[i]); k >= 1; k--)
     2353      {
     2354        p = p * facs[i][k]^(int(dT div degs[i][k]));
     2355        dT = dT mod degs[i][k];
     2356      }
     2357      bestElem[i][d] = p;
     2358    }
     2359  }
     2360
     2361  return(list(MSelf, bestElem));
     2362}
     2363
     2364////////////////////////////////////////////////////////////////////////
     2365
     2366// Valuations of differences of non-conjugate expansions.
     2367// Input:  a list classes of classes of conjugate expansions, as given by
     2368//         proc getClasses
     2369// Output: a matrix M of number, where M[i, j] is the valuation
     2370//         of gamma_i - gamma_j, expansions of the i-th and j-th conjugacy
     2371//         class respectively.
     2372static proc valIK(list classes)
     2373{
     2374  int i, j;
     2375  def R = basering;
     2376  matrix M[size(classes)][size(classes)];
     2377  for(i = 1; i <= size(classes); i++)
     2378  {
     2379    if(typeof(classes[i][1]) == "ring")
     2380    {
     2381      def S = classes[i][1];
     2382      setring S;
     2383      poly f = subst(PE[1][1], @a, 0);
     2384      int den(i) = PE[1][2];
     2385      number o = number(ratDeg(PE[1][1])) / number(den(i));
     2386      setring R;
     2387      poly f(i) = imap(S, f);
     2388      number o(i) = number(imap(S, o));
     2389      int nonRat(i) = 1;
     2390      setring S;
     2391      kill f;
     2392      kill o;
     2393      setring R;
     2394      kill S;
     2395    } else
     2396    {
     2397      poly f(i) = classes[i][1][1];
     2398      int den(i) =  classes[i][1][2];
     2399      number o(i) = number(orderExp(f(i))) / number(den(i));
     2400      int nonRat(i) = 0;
     2401    }
     2402  }
     2403
     2404  int k;
     2405  poly differ;
     2406  number ordDiff;
     2407  for(i = 1; i <= size(classes); i++)
     2408  {
     2409    M[i, i] = o(i);
     2410    for(j = 1; j < i; j++)
     2411    {
     2412      differ = subst(f(i), var(1), var(1)^den(j)) - subst(f(j), var(1), var(1)^den(i));
     2413      if(differ != 0){
     2414        k = orderExp(differ);
     2415        ordDiff = number(k) / number(den(i)*den(j));
     2416        // The order of the difference cannot be greater than the o(i) when
     2417        // the i-th expansion is non-rational when all the expansions in the
     2418        // block are in the same class.
     2419        if((nonRat(i) == 1) and (ordDiff > o(i)))
     2420        {
     2421          ordDiff = o(i);
     2422        }
     2423        if((nonRat(j) == 1) and (ordDiff > o(j)))
     2424        {
     2425          ordDiff = o(j);
     2426        }
     2427        M[i, j] = ordDiff;
     2428        M[j, i] = ordDiff;
     2429      } else
     2430      {
     2431        M[i, j] = o(i);
     2432        if(o(j) < o(i))
     2433        {
     2434          M[i, j] = o(j);
     2435        }
     2436        M[j, i] = M[i, j];
     2437      }
     2438    }
     2439  }
     2440  return(M);
     2441}
     2442
     2443////////////////////////////////////////////////////////////////////////
     2444
     2445// Input:  a polynomial f.
     2446// Output: an integer k = the order of f (that is, the smallest exponent of f
     2447//         as poly in the first variable).
     2448static proc orderExp(poly f){
     2449  if(f == 0)
     2450  {
     2451    return(-1);
     2452  } else
     2453  {
     2454    matrix co = coeffs(f, var(1));
     2455    int k = 1;
     2456    while(co[k, 1] == 0){
     2457      k++;
     2458    }
     2459    k--;
     2460  }
     2461  return(k);
     2462}
     2463
     2464// Input:  a list l of puiseux expansions
     2465// Output: a set of polynomials = the rational part of each expansion in l
     2466//static proc truncPoly(list l)
     2467//{
     2468//  int i, j;
     2469//  def R = basering;
     2470//  ring P = 0, (x,y,X), dp;
     2471//  poly fNew;
     2472//  poly f2;
     2473//  setring R;
     2474//
     2475//  for(i = 1; i <= size(l); i++)
     2476//  {
     2477//    if(typeof(l[i]) == "ring")
     2478//    {
     2479//      def S = l[i];
     2480//      setring S;
     2481//      poly f = subst(PE[1][1], @a, 0);
     2482//      int den(i) = PE[1][2];
     2483//      setring R;
     2484//      poly f(i) = imap(S, f);
     2485//      setring S;
     2486//      kill f;
     2487//      setring R;
     2488//      kill S;
     2489//    } else {
     2490//      poly f(i) = l[i][1];
     2491//      int den(i) =  l[i][2];
     2492//    }
     2493//    setring P;
     2494//    fNew = fetch(R, f(i));
     2495//    f2 = reduce(fNew, groebner(X - x^den(i)));
     2496//    f2 = subst(f2, X, x);
     2497//    setring R;
     2498//    f(i) = var(2) - fetch(P, f2);
     2499//  }
     2500//  return(f(1..size(l)));
     2501//}
     2502
     2503////////////////////////////////////////////////////////////////////////
     2504
     2505// Input:  matrix M of valuations of differences of expansions of different
     2506//         classes, list MSelf of valuations of an expansions with respect
     2507//         to valuations of the same class, integer d the degree of the
     2508//         required element, intvec md = the number of expansions in each
     2509//         class.
     2510// Output: the maximal valuation of an element of degree d, and the
     2511//         corresponding element.
     2512static proc ibElement(matrix M, list MSelf, int d, intvec md)
     2513{
     2514  // Best i
     2515  int i, j, k;
     2516  int top = d;
     2517  int s = ncols(M);
     2518
     2519  intvec vy = (0,1);
     2520  intvec vx = (1,0);
     2521  number order(1..s);
     2522  number minOrd;
     2523  number maxExp = 0;
     2524  int maxExpi;    // The value of i for the max exp.
     2525
     2526  list sums = summands(d, s, md);
     2527
     2528  for(i = 1; i <= size(sums); i++)
     2529  {
     2530    minOrd = 0;
     2531    for(j = 1; j <= s; j++)
     2532    {
     2533      order(j) = 0;
     2534      for(k = 1; k <= s; k++)
     2535      {
     2536        if(order(j) > -1)
     2537        {
     2538          if(k != j)
     2539          {
     2540            order(j) = order(j) + number(sums[i][k]) * number(M[k, j]);
     2541          } else
     2542          {
     2543            if (sums[i][k] < md[j])
     2544            {
     2545              if(sums[i][k] > 0)
     2546              {
     2547                order(j) = order(j) + MSelf[j][sums[i][k]];
     2548              }
     2549            } else
     2550            {
     2551              order(j) = -1;
     2552            }
     2553          }
     2554        }
     2555      }
     2556      if(((order(j) < minOrd) or (minOrd == 0)) and (order(j) > -1))
     2557      {
     2558        minOrd = order(j);
     2559      }
     2560    }
     2561    if(minOrd > maxExp)
     2562    {
     2563      maxExp = minOrd;
     2564      maxExpi = i;
     2565    }
     2566  }
     2567  intvec elem = sums[maxExpi];
     2568  return(list(maxExp, elem));
     2569}
     2570
     2571////////////////////////////////////////////////////////////////////////
     2572
     2573// Input:  int n, int k, intvec md of size k
     2574// Output: matrix such that it each row is a way of expressing n
     2575//         as a sum of k non-negative integers, where the i-th integer is
     2576//         smaller or equal than md[i].
     2577static proc summands(int n, int k, intvec md)
     2578{
     2579  list l;
     2580  list lT;
     2581  intvec v;
     2582  int i, j;
     2583  int m;
     2584  intvec mdT;
     2585  if(k > 1){
     2586    m = md[1];
     2587    if(m > n)
     2588    {
     2589      m = n;
     2590    }
     2591    for(i = m; i>= 0; i = i-1)
     2592    {
     2593      mdT = md[2..k];
     2594      lT = summands(n-i, k-1, mdT);
     2595      for(j = 1; j <= size(lT); j++)
     2596      {
     2597        v = i, lT[j];
     2598        l = insert(l, v);
     2599      }
     2600    }
     2601  } else {
     2602    if(n <= md[1])
     2603    {
     2604      l = insert(l, n);
     2605    }
     2606  }
     2607  return(l);
     2608}
     2609
     2610// Input:  int n, int k, intvec md of size k
     2611// Output: matrix such that it each row is a way of expressing n
     2612//         as a sum of k non-negative integers, where the i-th integer is
     2613//         smaller or equal than md[i].
     2614static proc summandAll(intvec md)
     2615{
     2616  int k = size(md);
     2617  list l;
     2618  list lT;
     2619  intvec v;
     2620  int i, j;
     2621  int m;
     2622  intvec mdT;
     2623  if(k > 1){
     2624    m = md[1];
     2625    for(i = 0; i <= m; i = i + 1)
     2626    {
     2627      mdT = md[2..k];
     2628      lT = summandAll(mdT);
     2629      for(j = 1; j <= size(lT); j++)
     2630      {
     2631        v = i, lT[j];
     2632        l = l + list(v);
     2633      }
     2634    }
     2635  } else {
     2636    for(i = 0; i <= md[1]; i = i+1)
     2637    {
     2638      l = l + list(i);
     2639    }
     2640  }
     2641  return(l);
     2642}
     2643
     2644
     2645// Next element in a list of integers
     2646static proc nextSummand(intvec md, intvec ch, int cl)
     2647{
     2648  int k = nrows(md);
     2649  int pos = 1;
     2650  if(cl == pos){pos = pos + 1;}
     2651  ch[pos] = ch[pos] + 1;
     2652
     2653//  "md: ", md;
     2654//  "ch: ", ch;
     2655//  "cl: ", cl;
     2656  while(ch[pos] > md[pos])
     2657  {
     2658    ch[pos] = 0;
     2659    pos = pos + 1;
     2660    ch[pos] = ch[pos] + 1;
     2661  }
     2662//  "output: ", ch;
     2663  return(ch);
     2664}
     2665
     2666////////////////////////////////////////////////////////////////////////
     2667
     2668// Input:  poly f in L[x], with L an algebraic extension of K.
     2669// Output: int k = the degree of the first term whose coefficient is in L - K
     2670static proc ratDeg(poly f)
     2671{
     2672  matrix c = coeffs(f, var(1));
     2673  int k = 1;
     2674  while((pardeg(number(c[k,1])) <= 0) and (k < size(c)))
     2675  {
     2676    k++;
     2677  }
     2678  if(pardeg(number(c[k,1])) > 0)
     2679  {
     2680    k--;
     2681  }
     2682  return(k);
     2683}
     2684
     2685// Input:  a list classes, whose elements are classes of conjugate Puiseux
     2686//         expansions, as returned by proc getClasses.
     2687// Output: a list of intvec, where the first element of each vector is the
     2688//         numerator and the second one the denominator of the (rational)
     2689//         order of the Puiseux expansions in each class.
     2690static proc getSlopes(list classes)
     2691{
     2692  int i;
     2693  list slopes;
     2694
     2695  def R = basering;
     2696
     2697  for(i = 1; i <= size(classes); i++)
     2698  {
     2699    if(typeof(classes[i][1]) == "ring")
     2700    {
     2701      def S = classes[i][1];
     2702      setring S;
     2703      slopes[i] = intvec(orderExp(PE[1][1]), PE[1][2]);
     2704      setring R;
     2705      kill S;
     2706    } else
     2707    {
     2708      slopes[i] = intvec(orderExp(classes[i][1][1]), classes[i][1][2]);
     2709    }
     2710  }
     2711  return(slopes);
     2712}
     2713
     2714////////////////////////////////////////////////////////////////////////
     2715
     2716// Input:  a list l of rings, each of these rings containing a list PE of
     2717//         Puiseux expansions.
     2718// Output: a list of rings, with one ring for each of the Puiseux expansions
     2719//         in the original rings.
     2720static proc explodeRings(list l)
     2721{
     2722  def R = basering;
     2723
     2724  int i, j;
     2725  int numb;
     2726  list rings;
     2727
     2728  for(i = 1; i <= size(l); i++){
     2729    if(typeof(l[i]) == "ring"){
     2730      def S = l[i];
     2731      setring S;
     2732      list rl;
     2733      numb = size(PE);
     2734      for(j = 1; j <= numb; j++){
     2735        rl = ringlist(S);
     2736        def SS = ring(rl);
     2737        setring SS;
     2738        list PET = fetch(S, PE);
     2739        list PE = list(PET[j]);
     2740        list erg = fetch(S, erg);
     2741        list minPolys = fetch(S, minPolys);
     2742        export(PE);
     2743        export(erg);
     2744        export(minPolys);
     2745        kill PET;
     2746        setring R;
     2747        rings = rings + list(SS);
     2748        setring S;
     2749        kill SS;
     2750      }
     2751    }
     2752  }
     2753  setring R;
     2754  return(rings);
     2755}
     2756
     2757// Input:  a list l, whose elements are either Puiseux expansions over the
     2758//         base ring or rings containing a list PE of Puiseux expansions.
     2759// Output: a list classes, where each element is a list of conjugate
     2760//         Puiseux expansions (given also either as expansions over the base
     2761//         rings or defined in extension rings).
     2762static proc getClasses(list l)
     2763{
     2764  int i;
     2765  int j;
     2766  int cc;
     2767  int prevI;
     2768  list code;
     2769  list classCode;
     2770  list classes;
     2771
     2772  list l2;
     2773  for(i = 1; i <= size(l); i++)
     2774  {
     2775    if(typeof(l[i]) == "ring"){
     2776      l2 = l2 + explodeRings(l[i]);
     2777    } else
     2778    {
     2779      l2 = l2 + list(l[i]);
     2780    }
     2781  }
     2782  l = l2;
     2783
     2784  int k = 1;
     2785  classes[k] = list();
     2786  classes[k][1] = l[1];
     2787  classCode[1] = 1;
     2788
     2789  def R = basering;
     2790
     2791  for(i = 1; i <= size(l); i++){
     2792    if(typeof(l[i]) == "ring"){
     2793      def S = l[i];
     2794      setring S;
     2795      code[i] = PE[1][6];
     2796      setring R;
     2797      kill S;
     2798    } else {
     2799      code[i] = l[i][6];
     2800    }
     2801    if(i>1)
     2802    {
     2803      prevI = 0;
     2804      for(j = 1; j < i; j++)
     2805      {
     2806        if(equalLists(code[i], code[j]))
     2807        {
     2808          prevI = j;
     2809        }
     2810      }
     2811      if(prevI == 0)
     2812      {
     2813        k++;
     2814        classes[k] = list();
     2815        classes[k][1] = l[i];
     2816        classCode[i] = k;
     2817      } else
     2818      {
     2819        cc = classCode[prevI];
     2820        classes[cc][size(classes[cc])+1] = l[i];
     2821        classCode[i] = classCode[prevI];
     2822      }
     2823    }
     2824  }
     2825  return(classes);
     2826}
     2827
     2828////////////////////////////////////////////////////////////////////////
     2829
     2830// Input:  a list classes, whose elements are classes of conjugate Puiseux
     2831//         expansions, as returned by proc getClasses.
     2832// Output: an intvec degs, where the i-th element is the number of Puiseux
     2833//         expansions in the i-th class (which is equal to the degree in y
     2834//         of the factor corresponding to that conjugacy class).
     2835static proc getDegs(list classes)
     2836{
     2837  int i, j;
     2838  intvec degs;
     2839
     2840  def R = basering;
     2841  int degBase = 1;
     2842  if(pardeg(minpoly) != -1)
     2843  {
     2844    degBase = pardeg(minpoly);
     2845  }
     2846
     2847  for(i = 1; i <= size(classes); i++)
     2848  {
     2849    degs[i] = 0;
     2850    for(j = 1; j <= size(classes[i]); j++)
     2851    {
     2852      if(typeof(classes[i][j]) == "ring")
     2853      {
     2854        def S = classes[i][j];
     2855        setring S;
     2856        degs[i] = degs[i] + (pardeg(minpoly) div degBase)*size(PE);
     2857        setring R;
     2858        kill S;
     2859      } else
     2860      {
     2861        degs[i] = degs[i] + 1;
     2862      }
     2863    }
     2864  }
     2865  return(degs);
     2866}
     2867
     2868////////////////////////////////////////////////////////////////////////
     2869
     2870// Input:  a list l, whose elements are either Puiseux expansions over the
     2871//         base ring or rings containing a list PE of Puiseux expansions.
     2872// Output: an integer d = sum of the degrees of the singular part of all the
     2873//         Puiseux expansions in the input.
     2874static proc getTotalDeg(list l)
     2875{
     2876  int i, j;
     2877  number d = 0;
     2878  number d2;
     2879  int dT, nT;
     2880  int mT;
     2881  def R = basering;
     2882  for(i = 1; i <= size(l); i++)
     2883  {
     2884    if(typeof(l[i]) == "ring")
     2885    {
     2886      def SS = l[i];
     2887      setring SS;
     2888      number dTemp;
     2889      dTemp = 0;
     2890      mT = pardeg(minpoly);
     2891      for(j = 1; j <= size(PE); j++)
     2892      {
     2893        nT = deg(PE[j][1]);
     2894        dT = PE[j][2];
     2895        dTemp = dTemp + (number(nT) / dT) * mT;
     2896      }
     2897      setring R;
     2898      d2 = number(imap(SS, dTemp));
     2899      d = d + d2;
     2900      kill SS;
     2901    } else
     2902    {
     2903      d = d + number(deg(l[i][1])) / l[i][2];
     2904    }
     2905  }
     2906  if(d == int(d))
     2907  {
     2908    return(int(d));
     2909  } else
     2910  {
     2911    //"Computing Puiseux expansions over an algebraic extension! Please check correct output...";
     2912    //"Input: list l";
     2913    //l;
     2914    //"Output: int d";
     2915    //int(d) + 1;
     2916    return(int(d) + 1);
     2917  }
     2918}
     2919
     2920////////////////////////////////////////////////////////////////////////
     2921
     2922// Product modulo x^e.
     2923// Input:  poly p, q in k[x][y], int expo
     2924// Output: p * q reduced mod x^e.
     2925// Remarks: it is assumed that x is the first variable in the ring.
     2926static proc prodMod(poly p, poly q, int expo)
     2927{
     2928  def R = basering;
     2929  qring Q = var(1)^expo;
     2930  poly p = imap(R, p);
     2931  poly q = imap(R, q);
     2932  poly pq = p*q;
     2933  setring R;
     2934  poly pq = imap(Q, pq);
     2935  pq = reduce(pq, groebner(var(1)^expo));
     2936  return(pq);
     2937}
     2938
     2939////////////////////////////////////////////////////////////////////////
     2940
     2941// Computed the order of poly h at the expansion defined by S,
     2942// which may be a ring or a Puiseux expansion
     2943static proc ordAtPol(poly h, def S)
     2944{
     2945  def R = basering;
     2946
     2947  if(typeof(S) == "ring")
     2948  {
     2949    setring S;
     2950    poly h = imap(R, h);
     2951    poly g = PE[1][1];
     2952    int den = PE[1][2];
     2953
     2954    //"here";
     2955    //"h, g", h, g;
     2956
     2957    //"b debug overflow <-";
     2958
     2959    if(size(h) > 1)
     2960    {
     2961      h = subst(h, var(1), var(1)^den);
     2962      poly hs = subst(h, var(2), g);
     2963      //"b debug overflow <-";
     2964
     2965      matrix MM;
     2966      MM = coef(hs, var(1));
     2967      int oo = deg(MM[1, ncols(MM)]);
     2968      kill hs;
     2969    } else
     2970    {
     2971      matrix MM;
     2972      MM = coef(g, var(1));
     2973      int oo = deg(MM[1, ncols(MM)])*deg(h, intvec(0,1)) + deg(h, intvec(1,0))*den;
     2974    }
     2975    //~;
     2976
     2977    number oro = oo/number(den);
     2978
     2979    //"h, oro", h, oro;
     2980    kill h;
     2981    kill g;
     2982    kill MM;
     2983    setring R;
     2984    number oro2 = number(imap(S, oro));
     2985    setring S;
     2986    kill oro;
     2987    setring R;
     2988  } else
     2989  {
     2990    int den = S[2];
     2991    poly g = S[1];
     2992    h = subst(h, var(1), var(1)^den);
     2993    poly hs = subst(h, var(2), g);
     2994
     2995    matrix MM;
     2996    MM = coef(hs, var(1));
     2997    int oo = deg(MM[1, ncols(MM)]);
     2998
     2999    number oro2 = oo/number(den);
     3000  }
     3001  return(oro2);
     3002}
     3003
     3004////////////////////////////////////////////////////////////////////////
     3005
     3006// Computes the factors of f corresponding to each conjugacy class,
     3007// up to degree degExpand
     3008static proc irreducibleFactors(poly f, list classes, int degExpand)
     3009{
     3010  list I2Lifted = henselBlocks(f, degExpand, 1);
     3011
     3012  int nClasses;
     3013  nClasses = size(classes);
     3014
     3015  int gfCheck = 1;  // For checking if the polynomial is over
     3016                    // the ground field.
     3017  list gfCheckList;
     3018
     3019  //"nClasses: ", nClasses;
     3020  //"size(I2Lifted): ", size(I2Lifted);
     3021  //"I2Lifted: ", I2Lifted;
     3022  //"degExpand: ", degExpand;
     3023
     3024  int wrongNumber = 0; // If some hensel block contains different classes
     3025
     3026  // CHECK THIS. How to count factor outside the origin?
     3027  if(nClasses != (size(I2Lifted) - 1))
     3028  {
     3029
     3030    list newL;
     3031    list I2LiftedNew;
     3032    I2LiftedNew[1] = I2Lifted[1];
     3033    int ind = 2;
     3034    list classes2;
     3035    poly fu, fuProd;
     3036    list fuPols;
     3037    int PEPE;
     3038    int cl;
     3039    int i, j;
     3040
     3041    list bPG;
     3042
     3043    def R = basering;
     3044
     3045    for(i = 2; i <= size(I2Lifted); i++)
     3046    {
     3047      //"Computing singular part of Puiseux expansions of factor ", i, ": ", I2Lifted[i];
     3048      newL = puiseux(I2Lifted[i], -1, 1);
     3049      classes2 = getClasses(newL);
     3050
     3051
     3052      if(size(classes2) > 1)
     3053      {
     3054        // We recompute up to the appropiate order for merging
     3055        poly I2Red = reduce(I2Lifted[i], var(1)^(degExpand+1));
     3056
     3057        //"Computing Puiseux expansions up to degree degExpand of factor ", i, ": ", I2Red;
     3058
     3059        newL = puiseux(I2Red, degExpand, 1);
     3060        classes2 = getClasses(newL);
     3061
     3062        for(j = 1; j <= size(classes2); j++)
     3063        {
     3064          fuProd = 1;
     3065          fuPols = list();
     3066          // FIX THIS FOR PUISEUX EXPANSIONS THAT ARE NOT GIVEN AS RINGS
     3067          // Check example
     3068          // ring R = 0, (X,Y), dp;
     3069          // poly f = (Y^6-6*X^3*Y^4-2*X^7*Y^3+12*X^6*Y^2-12*X^10*Y-8*X^9)*(Y^2-2*Y*X^3-2*X^3)*(Y^2+X^7)+X^30;
     3070          // list l = integralBasis(f,2,"atOrigin");
     3071
     3072
     3073          for(cl = 1; cl <= size(classes2[j]); cl++)
     3074          {
     3075
     3076            if(typeof(classes2[j][cl]) == "ring")
     3077            {
     3078              def S = classes2[j][cl];
     3079              setring S;
     3080
     3081              poly fu = buildPolyFrac(PE[1][1]);
     3082
     3083              PEPE = PE[1][2];
     3084
     3085              setring R;
     3086              fu = imap(S, fu);
     3087              kill S;
     3088              fuProd = fuProd * fu;
     3089            } else
     3090            {
     3091              "RING EXPECTED! Please contact the developers.";
     3092              ~;
     3093            }
     3094          }
     3095
     3096          bPG = buildPolyGround(fuProd, PEPE);
     3097
     3098          if(bPG[2] == 0)
     3099          {
     3100            // The polynomial computed is not over the ground field.
     3101            // The classes computed are wrong, we need to recompute.
     3102            "Polynomial not over the ground field.";
     3103            gfCheck = 0;
     3104          }
     3105
     3106          fu = reduce(bPG[1], groebner(var(1)^degExpand));
     3107
     3108          I2LiftedNew[ind] = fu;
     3109          gfCheckList[ind] = bPG[2];
     3110
     3111          ind = ind + 1;
     3112        }
     3113      } else {
     3114        I2LiftedNew[ind] = I2Lifted[i];
     3115        ind = ind + 1;
     3116      }
     3117    }
     3118    I2Lifted = I2LiftedNew;
     3119    wrongNumber = 1;
     3120  }
     3121  list ll = list(I2Lifted, gfCheckList, gfCheck, wrongNumber);
     3122
     3123  return(ll);
     3124}
     3125
     3126////////////////////////////////////////////////////////////////////////
     3127// Computes the maximum degree needed of the factors
     3128
     3129// Input:  n is the degree of f
     3130//         cl is the index of the class for which the loc basis is computed.
     3131// Output: maximal degree needed for computing the basis
     3132// [Example 4]
     3133
     3134static proc maxDegMerge(int n, int cl, int locBasis, int d0, matrix M, list MSelf, intvec md, list classes, list I2Lifted, list bestElem, matrix ordsFull, list ordsBest);
     3135{
     3136  //"START - newib.lib - maxDegMerge - 4";
     3137  int tt = timer;
     3138  def R = basering;
     3139
     3140  int i, j, k;
     3141  list ibNum, ibDen;
     3142  number expUnit;  // The integrality exponent of the local unit
     3143  poly polyUnit;
     3144
     3145  intvec vy = (0,1);
     3146  intvec vx = (1,0);
     3147
     3148  poly baseFactor;
     3149  number expBaseFactor;
     3150  poly locLocFactor = 1;
     3151  expUnit = 0;
     3152
     3153  def SS = classes[cl][1];
     3154
     3155  // This corrects for some wrongly computed number of classes
     3156  int nClasses;
     3157//  if(size(classes) > size(I2Lifted) - 1)
     3158//  {
     3159//    nClasses = size(I2Lifted) - 1;
     3160//  } else
     3161//  {
     3162//    nClasses = size(classes);
     3163//  }
     3164  nClasses = size(classes);
     3165
     3166
     3167  if(nClasses > 1)
     3168  {
     3169    for(j = 1; j <= size(I2Lifted)-1; j++)
     3170    {
     3171      if(j != cl)
     3172      {
     3173        expUnit = expUnit + number(ordsFull[j, cl]);
     3174      }
     3175    }
     3176    // The first term containing the locloc unit
     3177    expBaseFactor = expUnit;
     3178
     3179    // If the order of hi is not integer, we add a factor.
     3180    if(int(denominator(expBaseFactor)) > 1)
     3181    {
     3182
     3183      // We add the factor corresponding to the full expansions
     3184      list fullPoly;
     3185      for(j = 1; j <= nClasses; j++)
     3186      {
     3187        fullPoly[j] = I2Lifted[j+1];
     3188      }
     3189
     3190      int whichElem = 0;
     3191      int den1;
     3192      int den2;
     3193
     3194      intvec degsCl;
     3195      for(i = 1; i <= size(MSelf); i++)
     3196      {
     3197        degsCl[i] = size(MSelf[i]) + 1;
     3198      }
     3199      intvec chVec = 0:size(MSelf);
     3200
     3201      den1 = 1;
     3202      den2 = int(denominator(expBaseFactor));
     3203
     3204      number ordNewFactor;
     3205
     3206      number oAP;
     3207      number oAPT;
     3208
     3209      while(den1 mod den2 != 0)
     3210      {
     3211        chVec = nextSummand(degsCl, chVec, cl);
     3212        ordNewFactor = 0;
     3213        for(i = 1; i <= nClasses; i++)
     3214        {
     3215          if(i != cl)
     3216          {
     3217            k = chVec[i];
     3218            //"i, k", i, k;
     3219            if(k > 0)
     3220            {
     3221              if(k <= size(bestElem[i]))
     3222              {
     3223                oAP = ordsBest[cl][i][k];
     3224                ordNewFactor = ordNewFactor + oAP;
     3225              } else
     3226              {
     3227                oAP = number(ordsFull[i, cl]);
     3228                ordNewFactor = ordNewFactor + oAP;
     3229              }
     3230            }
     3231          }
     3232        }
     3233        den1 = int(denominator(ordNewFactor));
     3234      }
     3235
     3236      poly newFactor = 1;
     3237      int denNewFactor = den1;
     3238      int powFactor = 0;
     3239
     3240      int nnE = int(numerator(expBaseFactor));
     3241      int ddE = int(denominator(expBaseFactor));
     3242      int nnY = int(numerator(ordNewFactor));
     3243
     3244      while(ddE > 1)
     3245      {
     3246        powFactor = powFactor + 1;
     3247        expBaseFactor = expUnit + powFactor * ordNewFactor;
     3248        ddE = int(denominator(expBaseFactor));
     3249      }
     3250    }
     3251  } else
     3252  {
     3253    expBaseFactor = 0;
     3254  }
     3255
     3256  int eu;
     3257  number euNum;
     3258
     3259  euNum = expBaseFactor;
     3260  if(size(MSelf[cl]) > 0)
     3261  {
     3262    euNum = expBaseFactor + MSelf[cl][md[cl]-1];
     3263  }
     3264  eu = int(euNum);
     3265  debug_log_intbas(3, "------Time maxDegMerge: ", timer - tt);
     3266
     3267  return(eu);
     3268}
     3269
     3270////////////////////////////////////////////////////////////////////////
     3271
     3272// Computes the order of a polynomial h at the classes from list classes
     3273// indicated by an entry 1 in the vector classesInd
     3274static proc ordAtClassesPol(poly h, list classes, intvec classesInd)
     3275{
     3276  int i, j;
     3277  number expUnit = 0;
     3278  number expUnitTemp;
     3279
     3280  for(i = 1; i <= size(classes); i++)
     3281  {
     3282    if(classesInd[i] == 1)
     3283    {
     3284      expUnitTemp = ordAtPol(h, classes[i][1]);
     3285      if((expUnit == 0) || (expUnitTemp < expUnit))
     3286      {
     3287        expUnit = expUnitTemp;
     3288      }
     3289    }
     3290  }
     3291  return(expUnit);
     3292}
     3293
     3294////////////////////////////////////////////////////////////////////////
     3295
     3296// Computes the order of a product of polynomials at a list of classes
     3297static proc ordAtClasses(list classes, list fullPoly, intvec classes1Ind, intvec classes2Ind)
     3298{
     3299  int i, j;
     3300  number expUnit = 0;
     3301  number expUnitTemp;
     3302
     3303  for(i = 1; i <= size(classes); i++)
     3304  {
     3305    if(classes1Ind[i] == 1)
     3306    {
     3307      expUnitTemp = 0;
     3308      for(j = 1; j <= size(classes); j++)
     3309      {
     3310        if(classes2Ind[j] == 1)
     3311        {
     3312          expUnitTemp = expUnitTemp + ordAtPol(fullPoly[j], classes[i][1]);
     3313        }
     3314      }
     3315      if((expUnit == 0) || (expUnitTemp < expUnit))
     3316      {
     3317        expUnit = expUnitTemp;
     3318      }
     3319    }
     3320  }
     3321  return(expUnit);
     3322}
     3323
     3324////////////////////////////////////////////////////////////////////////
     3325
     3326// Takes the common denominator in a list of polynomial fractions
     3327static proc comDen(list ibNum, list ibDen)
     3328{
     3329  int i;
     3330  ideal IOut;
     3331  poly ibComDen = 1;
     3332
     3333  for(i = 1; i <= size(ibNum); i++)
     3334  {
     3335    ibComDen = lcm(ibComDen, ibDen[i]);
     3336  }
     3337
     3338  // Common denominator
     3339  for(i = 1; i <= size(ibNum); i++)
     3340  {
     3341    IOut[i] = (ibNum[i] * ibComDen) / ibDen[i];
     3342  }
     3343
     3344  list out = IOut, ibComDen;
     3345  return(out);
     3346}
     3347
     3348
     3349/////////////////////////////////////////////////////////////////////////////
     3350//
     3351//          Auxiliar tools
     3352//
     3353/////////////////////////////////////////////////////////////////////////////
     3354
     3355// The maximum between a and b
     3356static proc maxInt(int a, int b)
     3357{
     3358  if(a > b)
     3359  {
     3360    return(a);
     3361  } else {
     3362    return(b);
     3363  }
     3364}
     3365
     3366// Computes a polynomial over the ground field that together with the
     3367// elements of slower degree in the IB, generates the same ring as the
     3368// polynomial in the extension field.
     3369// Remark: it is assumed that x is the first variable.
     3370static proc elimPar(list ib, int i)
     3371{
     3372  // Trivial case
     3373  if(i == 1)
     3374  {
     3375    //"Trivial case";
     3376    return(ib[1][1]);
     3377  }
     3378
     3379  int t = timer;
     3380  int j;
     3381  def BR = basering;
     3382  poly pa = subst(minpoly, @a, var(1));
     3383
     3384  // We use a lexicographical ordering so that the parameter is eliminated.
     3385  ring ER = 0, (@a,var(1),var(2)), lp;
     3386  intvec va = (1,0,0);
     3387
     3388  // pa will be a polynomial in a.
     3389  poly pa = fetch(BR, pa);
     3390
     3391  // remi will be the ideal of the generators of smaller degree, after taking
     3392  // common denominator.
     3393  ideal remi;
     3394  list ib = imap(BR, ib);
     3395
     3396  int mExp = ib[i][2];
     3397  if(mExp > ib[i][2])
     3398  {
     3399    "WRONG EXPONENT. CHECK!!";
     3400    ~;
     3401    setring BR;
     3402    return(var(2) * ib[i-1][1]);
     3403  }
     3404
     3405  for(j = 1; j < i; j++)
     3406  {
     3407    // var(2) is now x
     3408    remi[j] = ib[j][1] * (var(2)-@a)^(mExp - ib[j][2]);
     3409  }
     3410
     3411  // Module reduction - NOT WORKING!! TO DO!!
     3412  //"Module reduction";
     3413  //"remi: "; remi;
     3414  //"pa: ", pa;
     3415  //"ib[i][1]: ", ib[i][1];
     3416  //poly redT = moduleReduction(remi, pa, ib[i][1]);
     3417
     3418  remi[i] = pa;
     3419  remi = groebner(remi);
     3420
     3421  // We reduce the last element by the rest of the elements
     3422  poly red = reduce(ib[i][1], remi);
     3423
     3424  if(deg(red, va) > 0)
     3425  {
     3426    "Wrong degree! Check!";
     3427    ~;
     3428  }
     3429  setring BR;
     3430  poly red = imap(ER, red);
     3431  return(red);
     3432}
     3433
     3434// The number of different initial coefficients must be equal to the
     3435// order b of the singular points.
     3436static proc newtonInfo(poly f, int b){
     3437  //"START - ibasis.lib - newtonInfo";
     3438  int i;
     3439  int slN, slD;
     3440  int g;
     3441  int dbg = printlevel - voice + 4;
     3442
     3443  list l = newtonpoly(f);
     3444  if(size(l) > 2){
     3445    dbprint(dbg, "The Puiseux Expansions have different initial exponents. New algorithm not implemented for this case.");
     3446    return(list());
     3447  } else {
     3448    slN = l[2][1] - l[1][1];
     3449    slD = l[1][2] - l[2][2];
     3450    g = gcd(slD, slN);
     3451    slD = slD div g;
     3452    slN = slN div g;
     3453    poly pp = Puiseuxexpansions::puiseuxStep(f, slN, slD);
     3454    if(deg(pp) < b){
     3455      dbprint(dbg, "The Puiseux Expansions have repeated initial coefficients. New algorithm not implemented for this case.");
     3456      return(list());
     3457    }
     3458    poly sqpp = squarefree(pp);
     3459    // CHECK! Case deg sqpp = 1 might not be fully implemented.
     3460    if((deg(sqpp) > 1) and (deg(sqpp) < deg(pp))){
     3461      dbprint(dbg, "The Puiseux Expansions have repeated initial coefficients. New algorithm not implemented for this case.");
     3462      return(list());
     3463    }
     3464    if((deg(sqpp) == 1) and (deg(pp) > 1))
     3465    {
     3466      if((slN mod slD) == 0)
     3467      {
     3468        return(list("changeCoord", subst(sqpp, y, 0)*x^(slN div slD)));
     3469      } else
     3470      {
     3471        "Not implemented.";
     3472        return(list());
     3473      }
     3474    }
     3475
     3476    if(slD*slN == 1){
     3477      dbprint(dbg, "Ordinary multiple point.");
     3478    }
     3479    return(list("OK", slN, slD));
     3480  }
     3481}
     3482
     3483// Gives the integral basis in the desired shape.
     3484// It replaces the exponents alpha by the corresponding px^alpha
     3485static proc convertIB(list ib, poly px)
     3486{
     3487  //"START - ibasis.lib - convertIB - 10";
     3488  int i;
     3489  int expDen = ib[size(ib)][2];
     3490  poly den = px^expDen;
     3491  ideal ibCom;
     3492  for(i = 1; i<= size(ib); i++)
     3493  {
     3494    ibCom[i] = ib[i][1]*(px^(expDen-int(ib[i][2])));
     3495  }
     3496  list new = list(ibCom, den);
     3497  return(new);
     3498}
     3499
     3500// Procedures to traslate polynomials
     3501static proc moveToVar(poly f, poly p, poly vari)
     3502{
     3503  ////"START - ibasis.lib - moveToVar - 8";
     3504  matrix c = coeffs(p, vari);
     3505  poly rootP = (-1)*c[1,1] / c[2,1];
     3506  poly fT = subst(f,vari,vari+rootP);
     3507  return(fT);
     3508}
     3509
     3510static proc moveFromVar(poly f, poly p, poly vari)
     3511{
     3512  //"START - ibasis.lib - moveFromVar - 8";
     3513  matrix c = coeffs(p, vari);
     3514  poly rootP = (-1)*c[1,1] / c[2,1];
     3515  poly fT = subst(f,vari,vari-rootP);
     3516  return(fT);
     3517}
     3518
     3519static proc moveTo(poly f, poly px, poly py)
     3520{
     3521  //"START - ibasis.lib - moveTo - 8";
     3522  poly fT = moveToVar(f, px, var(1));
     3523  fT = moveToVar(fT, py, var(2));
     3524  return(fT);
     3525}
     3526
     3527static proc moveFrom(poly f, poly px, poly py)
     3528{
     3529  //"START - ibasis.lib - moveFrom - 8";
     3530  poly fT = moveFromVar(f, px, var(1));
     3531  fT = moveFromVar(fT, py, var(2));
     3532  return(fT);
     3533}
     3534
     3535// Converts an integral basis in the shape {p0, p1, ..., pn-1} to the
     3536// shape (p0, d0), ..., (pn-1, dn-1)
     3537static proc intBasIdealToList(ideal I)
     3538{
     3539  list ib;
     3540  int d = deg(I[1], intvec(1,0));
     3541  list out;
     3542  for(int i = 1; i <= ncols(I); i++)
     3543  {
     3544    out = divideBy(I[i], var(1));
     3545    ib[i] = list(out[1], d - out[2]);
     3546  }
     3547  return(ib);
     3548}
     3549
     3550
     3551// Divides f by the maximum possible power of g.
     3552// Returns the quotient and the exponent used of g.
     3553static proc divideBy(poly f, poly g)
     3554"USAGE:  divideBy(f,g); f, g multivariate polynomials
     3555RETURN:  a list of two elements. The first element is the polynomial f
     3556divided by the maximum possible power of g and the second element is an
     3557integer indicating the power of g used.
     3558KEYWORDS: division multivariate polynomials
     3559"
     3560
     3561{
     3562  int i = 1;
     3563  ideal G = groebner(g);
     3564  while(reduce(f, G) == 0)
     3565  {
     3566    f = f / g;
     3567    i = i + 1;
     3568  }
     3569  list out = f, i-1;
     3570  return(out);
     3571}
     3572
     3573// Compares two polynomials in two variables.
     3574// This is used so that the puiseux expansions are always given in the same
     3575// order.
     3576static proc isBigger(poly f, poly g)
     3577{
     3578  //"START - integralbasis.lib - isBigger - 1";
     3579  int i;
     3580  intvec vy = (0,1);
     3581  if(deg(f, vy) > deg(g, vy))
     3582  {
     3583    // f is bigger
     3584    return(1);
     3585  }
     3586  if(deg(f, vy) < deg(g, vy))
     3587  {
     3588    // g is bigger
     3589    return(-1);
     3590  }
     3591  matrix cf = coeffs(f, var(2));
     3592  matrix cg = coeffs(g, var(2));
     3593  for(i = size(cf); i >= 1; i = i-1)
     3594  {
     3595    if(cf[i,1] > cg[i,1])
     3596    {
     3597      return(1);
     3598    }
     3599    if(cf[i,1] < cg[i,1])
     3600    {
     3601      return(-1);
     3602    }
     3603  }
     3604  // f is equal to g.
     3605  return(0);
     3606}
     3607
     3608// This is used so that the puiseux expansions are always given in
     3609// the same order. This procedure is also used in Puiseux library.
     3610static proc sortFactors(list facts)
     3611{
     3612  //"START - integralbasis.lib - sortFactors - 1";
     3613  int i, j;
     3614  int n = size(facts[1]);
     3615  poly pTemp;
     3616  int eTemp;
     3617  for (i = n; i >= 1; i--)
     3618  {
     3619    for (j = 1; j <= i-1; j++)
     3620    {
     3621      if(isBigger(facts[1][j], facts[1][j+1]) == 1)
     3622      {
     3623        pTemp = facts[1][j];
     3624        eTemp = facts[2][j];
     3625        facts[1][j] = facts[1][j+1];
     3626        facts[2][j] = facts[2][j+1];
     3627        facts[1][j+1] = pTemp;
     3628        facts[2][j+1] = eTemp;
     3629      }
     3630    }
     3631  }
     3632  return(facts);
     3633}
     3634
     3635
    2943636///////////////////////////////////////////////////////////////////////////////
    2953637
    296 static proc integralLocal(ideal I, list #){
    297 // Computes the integral basis  by localizing at the different components of
    298 // the singular locus.
     3638// Convert a list of numbers into an intvec
     3639static proc poly2intvec(poly p)
     3640{
     3641  intvec c;
     3642  matrix M = coef(p, var(1));
     3643  int n = ncols(M);
     3644  for(int i = 1; i <= n; i++)
     3645  {
     3646    c[i] = int(deg(M[1,n+1-i]));
     3647  }
     3648  return(c);
     3649}
     3650
     3651///////////////////////////////////////////////////////////////////////////////
     3652
     3653// Convert a list of numbers into an intvec
     3654static proc list2intvec(list l)
     3655{
     3656  intvec c;
     3657  for(int i = 1; i <= size(l); i++)
     3658  {
     3659    c[i] = int(l[i]);
     3660  }
     3661  return(c);
     3662}
     3663
     3664///////////////////////////////////////////////////////////////////////////////
     3665
     3666// Given two intvecs, both ordered for lowest to highest, it return
     3667// a new intvec containing the union of both intvecs, ordered from lowest
     3668// to highest.
     3669static proc appendIntvecs(intvec a, intvec b)
     3670{
     3671  intvec c;
     3672  int indA = 1;
     3673  int indB = 1;
     3674  int indC = 1;
     3675  int last = -1;
     3676  while((indA <= size(a)) and (indB <= size(b)))
     3677  {
     3678    if(a[indA] < b[indB]){
     3679      if(a[indA] > last)
     3680      {
     3681        c[indC] = a[indA];
     3682        last = c[indC];
     3683        indC++;
     3684      }
     3685      indA++;
     3686    } else {
     3687      if(b[indB] > last)
     3688      {
     3689        c[indC] = b[indB];
     3690        last = c[indC];
     3691        indC++;
     3692      }
     3693      indB++;
     3694    }
     3695  }
     3696  while(indA <= size(a))
     3697  {
     3698    if(a[indA] > last)
     3699    {
     3700      c[indC] = a[indA];
     3701      last = c[indC];
     3702      indC++;
     3703    }
     3704    indA++;
     3705  }
     3706  while(indB <= size(b))
     3707  {
     3708    if(b[indB] > last)
     3709    {
     3710      c[indC] = b[indB];
     3711      last = c[indC];
     3712      indC++;
     3713    }
     3714    indB++;
     3715  }
     3716  return(c);
     3717}
     3718
     3719
     3720// Computes a Groebner basis of P with lex order and y > x.
     3721static proc yInTermOfx(ideal P)
     3722{
     3723  //"START - integralbasis.lib - yInTermOfx - 1";
     3724  def R = basering;
     3725  ring S = 0, (var(2), var(1)), lp;
     3726  ideal P = imap(R, P);
     3727  P = groebner(P);
     3728  setring R;
     3729  P = imap(S, P);
     3730  return(P);
     3731}
     3732
     3733// Divides a polynomial by a - x.
     3734static proc divXA(poly f)
     3735{
     3736  //"START - integralbasis.lib - divXA";
     3737  def R = basering;
     3738
     3739  ring W = 0, (@a,var(1),var(2)), lp;
     3740  poly f = imap(R, f);
     3741  //list l = division(f, @a-x);
     3742  list l = division(f, @a-var(2));
     3743  setring R;
     3744  list l = imap(W, l);
     3745  list l2 = l[1][1,1], l[2][1];
     3746  return(l2);
     3747}
     3748
     3749static proc swapXYIdeal(ideal I)
     3750{
     3751  //"START - integralbasis.lib - swapXYIdeal";
     3752  def R = basering;
     3753  def R2 = ring(0, (y,x), dp);
     3754  setring R2;
     3755  ideal I = fetch(R, I);
     3756  setring R;
     3757  I = imap(R2, I);
     3758  return(I);
     3759}
     3760
     3761static proc swapXYPoly(poly f)
     3762{
     3763  //"START - integralbasis.lib - swapXYPoly";
     3764  def R = basering;
     3765  def R2 = ring(0, (y,x), dp);
     3766  setring R2;
     3767  poly f = fetch(R, f);
     3768  setring R;
     3769  f = imap(R2, f);
     3770  return(f);
     3771}
     3772
     3773// f monic as poly in the second variable (assuming that the coefficient of
     3774// the max degree is a constant)
     3775proc monic(poly f)
     3776"USAGE:  monic(f); f polynomial in two variables whose leadi.
     3777RETURN:  a multiple of f monic as polynomial in the second variables,
     3778polynomial of degree d in the second variable of the ring with
     3779an ordinary  multiple point at the origin of order k.
     3780ASSUME:  f is a bivariate polynomial whose leading coefficients as
     3781polynomial in the second variable is a unit.
     3782EXAMPLE: example monic; shows an example
     3783"
     3784{
     3785  //"START - integralbasis.lib - monic - 1";
     3786  matrix c = coeffs(f,var(2));
     3787  f = f/c[size(c), 1];
     3788  return(f);
     3789}
     3790example
     3791{ "EXAMPLE:";
     3792  echo = 2;
     3793  ring R = 0, (x,y), dp;
     3794  poly f = -3y3 + 3x2y + y2 + 1;
     3795  monic(f);
     3796}
     3797
     3798
     3799
     3800// Generates a polynomial of degree d in y with a ordinary multiple point at
     3801// the origin of order k.
     3802proc polyDK(int d, int k, list #)
     3803"USAGE:  polyDK(d,k,#); d integer, k<=d integer.
     3804RETURN:  polynomial of degree d in the second variable of the ring with
     3805an ordinary  multiple point at the origin of order k.
     3806KEYWORDS: singularities ordinary multiple point.
     3807EXAMPLE: example polyDK; shows an example
     3808"
     3809
     3810{
     3811  //"START - integralbasis.lib - polyDK";
     3812  if(size(#) > 0){
     3813    if(typeof(#[1]) == "int"){
     3814      int sd = #[1];
     3815      //"Setting the seed to ", sd;
     3816      system("--random", sd);
     3817    }
     3818  }
     3819
    2993820  int i;
    300   int dbg = printlevel - voice + 4;
     3821  def r = basering;
     3822  ring s = 0, (x,y,z), dp;
     3823  ideal m2 = maxideal(d);
     3824  ideal m1 = ideal(x,y);
     3825  m1 = m1^k;
     3826  ideal J = intersect(m1, m2);
     3827
     3828  int good = 0;
     3829  while(good == 0){
     3830    setring s;
     3831    matrix M = randommat(1,1,J,5);
     3832    poly p = M[1,1];
     3833    p = p+y^(d);
     3834    p = subst(p,z,1);
     3835
     3836    setring r;
     3837    poly p = fetch(s, p);
     3838    matrix c = coeffs(p,y);
     3839    poly f = p / c[size(c), 1];
     3840
     3841    // We check if f satisfies the desired properties.
     3842    list fc = divideBy(subst(f,x,0), y);
     3843    if(fc[2] == k){
     3844      good = 1;
     3845    }
     3846  }
     3847  return(f);
     3848}
     3849example
     3850{ "EXAMPLE:";
     3851  echo = 2;
     3852  ring R = 0, (x,y), dp;
     3853  int k = 3;
     3854  int d = 6;
     3855
     3856  // Polynomial of degree 6 in y with an ordinary multiple point
     3857  // at the origin of order k.
     3858  poly f = polyDK(d, k, 1231);
     3859  f;
     3860
     3861  // The integral basis of R / <f>
     3862  list l = integralBasis(f, 2, "atOrigin");
     3863  l;
     3864  echo = 0;
     3865}
     3866
     3867
     3868
     3869/////////////////////////////////////////////////////////////////////////////
     3870//
     3871//          Hensel Lifting
     3872//
     3873/////////////////////////////////////////////////////////////////////////////
     3874
     3875proc henselGlobal(poly f, poly g, poly h, int order)
     3876"USAGE:  henselGlobal(f,g,h,order); h is polynomial in x and y.
     3877f and g are polynomials in y such that f(y)*g(y) = h(0,y) and <f, g> = 1.
     3878RETURN:  polynomials f1 and g1 such that
     38791) h = f1*g1 up to the required order in x.
     38802) f1(0,y) = f, g1(0,y) = g
     3881KEYWORDS: hensel lifting.
     3882"
     3883{
     3884  //"START - hensel.lib - henselGlobal - 1";
     3885  intvec vx = (1,0);
     3886
     3887  int dbg = printlevel - voice + 2;
     3888  //if(dbg > 2)
     3889  //{
     3890  //  "Hensel lifting input:";
     3891  //  "f: ", f; "g: ", g; "h: ", h;
     3892  //  "order: ", order;
     3893  //}
     3894
     3895  // Trivial cases
     3896  //if(f == 1)
     3897  if(deg(f,intvec(0,1)) == 0)
     3898  {
     3899    //if(f != 1)
     3900    //{
     3901    //  "Non monic at henselGlobal, please check.";
     3902    //}
     3903    if(subst(h, var(1), 0) == f * g)
     3904    {
     3905      list L = f, jet(h, order, vx);
     3906      //dbprint(dbg - 2, "Output: ", L);
     3907      //"DBG - henselGlobal easy ends";
     3908      return(L);
     3909    } else
     3910    {
     3911    "ERROR";
     3912    ~;
     3913      ERROR("f(y)*g(y) != h(0,y)");
     3914    }
     3915  }
     3916  //if(g == 1)
     3917  if(deg(g, intvec(0,1)) == 0)
     3918  {
     3919    //if(g != 1)
     3920    //{
     3921    //  "Non monic at henselGlobal, please check.";
     3922    //}
     3923    if(subst(h, var(1), 0) == f * g)
     3924    {
     3925      list L = jet(h, order, vx), poly(1);
     3926      //"DBG - henselGlobal easy ends";
     3927      //dbprint(dbg - 2, "Output: ", L);
     3928      return(L);
     3929    } else
     3930    {
     3931      "ERROR";
     3932      ~;
     3933      ERROR("f(y)*g(y) != h(0,y)");
     3934    }
     3935  }
     3936
     3937  int t = timer;
     3938  // Kernel version
     3939  dbprint(dbg, "--------Calling Hensel lifting (kernel)...");
     3940  //"DBG - Calling hensel lifting (kernel)..."; "h: ", h; "f: ", f; "g:", g;
     3941
     3942  // DEBUG!!
     3943  // REMOVE!!!
     3944  //order = order * 10;
     3945
     3946  //"h, order, f, g", h, order, f, g;
     3947  list L = factmodd(h, order, f, g, 1, 2);
     3948
     3949  //list L = system("henselfactors", 1, 2, h, f, g, order);
     3950  debug_log_intbas(3, "--------Time hensel lifting (kernel): ", timer-t);
     3951  //"DBG - Time hensel lifting (kernel): ", timer-t;
     3952
     3953  dbprint(dbg - 2, "--------Output of Hensel lifting: ", L);
     3954  //"DBG - henselGlobal ends";
     3955  //"Check: "; jet(L[1]*L[2] - h, order, vx);
     3956  return(L);
     3957}
     3958example
     3959{ "EXAMPLE:";
     3960  echo = 2;
     3961  ring R = 0, (x,y), dp;
     3962
     3963  // Polynomial of degree 6 in y with an ordinary multiple point
     3964  // at the origin of order k.
     3965  poly h = (y2 + 3xy + x3 + x4)*(y3 + 2x + 1);
     3966  poly f = y2;
     3967  poly g = y3 + 1;
     3968  henselGlobal(f, g, h, 3);
     3969  echo = 0;
     3970}
     3971
     3972
     3973
     3974
     3975// This procedure separates the segment with slope slN / slD (assuming that
     3976// it is the smallest slope) from the rest.
     3977// It returns a list containing the factor correspoding to the slope slN / slD, and
     3978// the polynomial corresponding to all the factors with larger slope.
     3979// This procedure tranforms the polynomials so that the Hensel Lifting Lemma
     3980// can be applied, and uses it to lift the factorization up to the desired
     3981// order.
     3982static proc henselLocal(poly f, int slN, int slD, int order)
     3983{
     3984  int dbg = printlevel - voice + 5;
     3985  int i;
     3986  intvec vy = 0, 1;
     3987  poly x = var(1);
     3988  poly y = var(2);
     3989  int d = deg(f, vy);
     3990
     3991  //"Transformation...", slN, slD;
     3992
     3993  // We transform y by x^(slN / slD)y in f.
     3994  // and factor out the powers of x.
     3995  // (In fact, to avoid fractional exponents,
     3996  // we map x to x^slD and y to x^slN*y.)
     3997  poly f1 = mapTo(f, slN, slD);
     3998  int fD = slN * d;
     3999  f1 = f1 / (x^fD);
     4000  poly f0 = subst(f1, x, 0);
     4001  list l1 = divideBy(f0, y);
     4002  poly g0 = l1[1];
     4003  int gD = deg(g0, vy);
     4004  int hD = l1[2];
     4005  poly h0 = y^hD;
     4006
     4007  // We set up to which order we have to compute the expansions
     4008  int ordCommon;
     4009  if(hD < gD)
     4010  {
     4011    ordCommon = slN * hD;
     4012  } else
     4013  {
     4014    ordCommon = slN * gD;
     4015  }
     4016
     4017  //dbprint(dbg, "henselGlobal inside henselLocal");
     4018  //dbprint(dbg - 1, "Order: ", order * slD - ordCommon);
     4019
     4020  // DEBUG!!!
     4021  //order = order * 10;
     4022
     4023  list l2 = henselGlobal(g0, h0, f1, order * slD - ordCommon);
     4024  //dbprint(dbg, "henselGlobal inside henselLocal finished");
     4025
     4026  // We transform everything back to the original setting
     4027  // The case of several blocks with the same slope is not implemented.
     4028  //list comps = henselFacs(g, order * slD - ordCommon);
     4029  poly g = l2[1] * (x^(gD * slN));
     4030
     4031  g = mapFrom(g, slN, slD);
     4032
     4033  poly h = l2[2] * (x^(hD*slN));
     4034  h = mapFrom(h, slN, slD);
     4035  return(list(g, h));
     4036}
     4037
     4038// Maps x to x^slD and y to x^slN*y.
     4039static proc mapTo(poly f, int slN, int slD)
     4040{
     4041  f = subst(f, var(1), var(1)^slD);
     4042  f = subst(f, var(2), var(1)^slN*var(2));
     4043  return(f);
     4044}
     4045
     4046// We map back x^slN*y to y and x^slD to x.
     4047static proc mapFrom(poly f, int slN, int slD)
     4048{
     4049  //"START - hensel.lib - mapFrom - 1";
    3014050  def R = basering;
    302 
    303   list n;         // Output of proc normal
    304   ideal norT;     // Temporary data.
    305   poly denomT;    // Temporary data.
    306 
    307   ideal nor;      // Output of normal with the denominator changed to the
    308                   // common denominator.
    309   ideal res;      // The full integral basis
    310 
    311 //--------------------------- read the input options---------------------------
    312   int denomOption = 0;
    313   for ( i=1; i <= size(#); i++ )
    314   {
    315     if ( typeof(#[i]) == "string" )
    316     {
    317       if (#[i]=="var1")
    318       {denomOption = 1;}
    319       if (#[i]=="var2")
    320       {denomOption = 2;}
    321     }
    322   }
    323 
    324 //------------------------ singular locus computation -------------------------
    325   // We use a general method that works for any ideal.
    326   // For I defined by a single polynomial a simpler method could be used.
    327   list IM = mstd(I);
    328   I = IM[1];
    329   int d = dim(I);
    330   ideal IMin = IM[2];
    331   qring Q = I;  // We work in the quotient by the Groebner basis of the ideal I
    332   option("redSB");
    333   option("returnSB");
    334   ideal I = fetch(R, I);
    335   attrib(I, "isSB", 1);
    336   ideal IMin = fetch(R, IMin);
    337   if(dbg >= 2){
    338     int t = timer;
    339   }
    340   ideal J = minor(jacob(IMin), nvars(basering) - d, I);
    341   if(dbg >= 2){
    342     "singular locus time: ", timer - t;
    343     t = timer;
    344   }
     4051  int jj = attrib(basering, "maxExp");
     4052  ring S = (0, @a), (x, y, T), (dp, L(jj));
     4053  poly f = fetch(R, f);
     4054  ideal I1 = x^slN*y-T;
     4055  poly g = reduce(f, groebner(I1));
     4056  g = subst(g, T, y);
     4057  ideal I2 = x^slD - T;
     4058  g = reduce(g, groebner(I2));
     4059  g = subst(g, T, x);
    3454060  setring R;
    346   ideal J = fetch(Q, J);
    347   J = J, I;
    348   J = groebner(J);
    349 
    350   if(dbg >= 2){
    351     "groebner of the singular locus time: ", timer - t;
    352     t = timer;
    353   }
    354 
    355   if(dbg >= 2){
    356     "The original singular locus is";
    357     J;
    358   }
    359 
    360 //------------------------ universal denominator ------------------------------
    361   // We could use the LCD of the denominators of each component, but we need
    362   // a denominator in the required variable.
    363   if(denomOption == 0){
    364     poly condu = getSmallest(J);   // Choses the polynomial of smallest degree
    365                                    // of J as universal denominator.
     4061  poly g = fetch(S, g);
     4062  //"ENDS - hensel.lib - mapFrom - 1";
     4063  return(g);
     4064}
     4065
     4066//------------------------------------------------------------------
     4067// General procedure for computing factors via hensel lifting
     4068//------------------------------------------------------------------
     4069// Computes the factors of f corresponding to the Puiseux blocks up to a given
     4070// order in the power series ring.
     4071static proc henselBlocks(poly f, int globOrder, int loc)
     4072{
     4073  int dbg = printlevel - voice + 5;
     4074
     4075  // If loc = 1, the factors outside the origin will be taken all together.
     4076  // The first poly in the ouput will be the factor corresponding to the component
     4077  // outside the origin.
     4078
     4079  //if(dbg > 5)
     4080  //{
     4081  //  "---- henselBlock begins";
     4082  //}
     4083
     4084  poly x = var(1);
     4085  poly y = var(2);
     4086
     4087  int comp = 1;
     4088  list comps;
     4089  list compsT;
     4090  int i, j, k;
     4091  int first;
     4092  int stop, last;
     4093
     4094  list fSegment;
     4095
     4096  intvec vx = (1,0);
     4097  intvec vy = (0,1);
     4098  int maxOrder = deg(f, vx);
     4099  if(globOrder > maxOrder)
     4100  {
     4101    maxOrder = globOrder;
     4102  }
     4103  int locOrder = maxOrder;
     4104
     4105  if(loc == 1)
     4106  {
     4107    poly f0 = subst(f, x, 0);
     4108
     4109    list fl = divideBy(f0, y);
     4110
     4111    list fGlob = henselGlobal(y^fl[2], fl[1], f, maxOrder);
     4112
     4113    poly fLoc = fGlob[1];
     4114
     4115    if(fLoc == 1)
     4116    {
     4117      "Warning! No local component. This may indicate you are computing the basis at a value of X where there is no singularity.";
     4118    }
     4119    comps[1] = fGlob[2];    // comp[1] is the component outside the origin.
     4120    comp = 2;
     4121    dbprint(dbg, "----Computing Puiseux Segments...");
     4122    fSegment = henselSegments(fLoc, maxOrder);
     4123
     4124    for(i = 1; i <= size(fSegment); i++)
     4125    {
     4126      compsT = henselInSegment(fSegment[i], maxOrder);
     4127
     4128      for(k = 1; k <= size(compsT); k++){
     4129        comps[comp] = compsT[k];
     4130        comp++;
     4131      }
     4132    }
     4133  } else
     4134  {
     4135    comps = henselTotal(f, maxOrder);
     4136    comp = size(comps) + 1;
     4137  }
     4138
     4139  return(comps);
     4140}
     4141
     4142// Given a poly without components outside the origin, computes the factors
     4143// corresponding to each slope in the power series rings.
     4144static proc henselSegments(poly f, int order)
     4145{
     4146  //if(printlevel - voice > 5)
     4147  //{
     4148  //  "START - hensel.lib - henselSegments - 1";
     4149  //}
     4150
     4151  int dbg = printlevel - voice + 5;
     4152  int i;
     4153  int slN, slD;
     4154  poly fLoc = f;
     4155  list lLoc;
     4156
     4157  list l = newtonpoly(f);
     4158  list hSegment;
     4159
     4160  for(i = 1; i < size(l) - 1; i++)
     4161  {
     4162    slN = l[i+1][1] - l[i][1];
     4163    slD = l[i][2] - l[i+1][2];
     4164
     4165    // The polynomial corresponding to the segment.
     4166    if(dbg > 0)
     4167    {
     4168      "------Computing the polynomial corresponding to segment", i;
     4169    }
     4170    lLoc = henselLocal(fLoc, slN, slD, order);
     4171
     4172    //dbprint(dbg, "Done.");
     4173    hSegment[i] = lLoc[1];
     4174    fLoc = lLoc[2];
     4175  }
     4176  hSegment[size(l) - 1] = fLoc;
     4177
     4178  return(hSegment);
     4179}
     4180
     4181// Computes the different blocks in a segment up to the given order.
     4182static proc henselInSegment(poly f, int globOrder)
     4183{
     4184  //if(printlevel - voice > 5)
     4185  //{
     4186  //  "START - hensel.lib - henselSegments - 1";
     4187  //}
     4188  int i, j;
     4189  int loc;
     4190  list comps;
     4191
     4192  poly x = var(1);
     4193  poly y = var(2);
     4194  intvec vx = (1,0);
     4195  intvec vy = (0,1);
     4196  int d = deg(f, vy);
     4197
     4198  list l = newtonpoly(f);
     4199
     4200  int slN = l[2][1] - l[1][1];
     4201  int slD = l[1][2] - l[2][2];
     4202  int g = gcd(slD, slN);
     4203  slD = slD div g;
     4204  slN = slN div g;
     4205
     4206  poly je = Puiseuxexpansions::minEqNewton(f, slN, slD);
     4207  list fJe = factorize(je);
     4208  fJe = sortFactors(fJe);
     4209
     4210  // We transform y by x^(slN / slD)y in f.
     4211  // and factor out the powers of x.
     4212  // (In fact, to avoid fractional exponents,
     4213  // we map x to x^slD and y to x^slN*y.)
     4214  poly f1 = mapTo(f, slN, slD);
     4215  f1 = f1 / (x^(d*slN));
     4216
     4217  poly je1 = mapTo(je, slN, slD);
     4218  je1 = je1 / (x^(d*slN));
     4219
     4220  // For each factor of the equation, compute the corresponding lifted factor
     4221  list lLoc;
     4222  poly fLoc = f1;
     4223  list hFactor;
     4224  poly fJe1;
     4225  int sFac = size(fJe[1]) - 1;
     4226
     4227  for(i = 1; i < sFac; i++)
     4228  {
     4229    fJe1 = mapTo(fJe[1][i+1]^(fJe[2][i+1]), slN, slD);
     4230    fJe1 = fJe1 / (x^(deg(fJe1, vy) * slN));
     4231    je1 = je1 / fJe1;
     4232    lLoc = henselGlobal(fJe1, je1, fLoc, globOrder);
     4233    hFactor[i] = lLoc[1];
     4234    fLoc = lLoc[2];
     4235  }
     4236  hFactor[sFac] = fLoc;
     4237
     4238  int degFac;
     4239  int comp = 1;
     4240  poly ratPart;
     4241  list compsT;
     4242  for(i = 1; i <= sFac; i++)
     4243  {
     4244    degFac = deg(fJe[1][i+1], vy) * fJe[2][i+1];
     4245    hFactor[i] = hFactor[i] * (x^(degFac * slN));
     4246    hFactor[i] = mapFrom(hFactor[i], slN, slD);
     4247    compsT = splitFact(hFactor[i], fJe[1][i+1], fJe[2][i+1], globOrder);
     4248    for(j = 1; j <= size(compsT); j++)
     4249    {
     4250      comps[comp] = compsT[j];
     4251      comp++;
     4252    }
     4253  }
     4254  return(comps);
     4255}
     4256
     4257// Computes the Puiseux block at the origin an outside the origin.
     4258// It lifts all the factors of h(0,y) and splits them.
     4259static proc henselTotal(poly h, int order)
     4260{
     4261  if(printlevel - voice > 5)
     4262  {
     4263    "START - hensel.lib - henselTotal";
     4264  }
     4265
     4266  poly f, g;
     4267  int i, j;
     4268  list facs;
     4269  list comps;
     4270  list hFacts;
     4271  int comp = 1;
     4272
     4273  poly x = var(1);
     4274  poly y = var(2);
     4275  intvec vy = (0,1);
     4276
     4277  poly h0 = subst(h, x, 0);
     4278  list fc = factorize(h0);
     4279  fc = sortFactors(fc);
     4280
     4281  g = h;
     4282
     4283  // Computes the lifting of the factors
     4284  list compsT;
     4285  for(i = 2; i < size(fc[1]); i++)
     4286  {
     4287    f = fc[1][i]^(fc[2][i]);
     4288    g = g / f;
     4289    facs = henselGlobal(f, g, h, order);
     4290    h = facs[2];
     4291    hFacts[i-1] = facs[1];
     4292  }
     4293  hFacts[size(fc[1]) - 1] = h;
     4294
     4295  // Splits the factors
     4296  for(i = 1; i <= size(hFacts); i++)
     4297  {
     4298    compsT = splitFact(hFacts[i], fc[1][i+1], fc[2][i+1], order);
     4299    for(j = 1; j <= size(compsT); j++)
     4300    {
     4301      comps[comp] = compsT[j];
     4302      comp++;
     4303    }
     4304  }
     4305  return(comps);
     4306}
     4307
     4308// Split poly f assuming that it corresponds to a factor factor^exp
     4309static proc splitFact(poly f, poly fact, int exp, int order)
     4310{
     4311  poly x = var(1);
     4312  poly y = var(2);
     4313
     4314  fact = monic(fact);
     4315  int i, j;
     4316  list comps;
     4317
     4318  intvec vy = (0,1);
     4319  int comp = 1;
     4320
     4321  // If the degree of the minimal polynomial is greater than 1,
     4322  // the splitting is not implemented.
     4323
     4324  // If the degree is 1, and the exponent is 1, there is nothing to do.
     4325  if((deg(fact, vy) == 1) and (exp > 1))
     4326  {
     4327    // The rational part.
     4328    fact = monic(fact);
     4329    poly ratPart = subst(fact, y, 0);
     4330    poly fNew = subst(f, y, y - ratPart);
     4331
     4332    int loc;
     4333    int start;
     4334    if(fact == y)
     4335    {
     4336      loc = 1;    // Separate only the factors at the origin.
     4337      start = 2;
     4338    } else
     4339    {
     4340      loc = 0;    // Separate also the factors outside the origin.
     4341      start = 1;
     4342    }
     4343    list compsT = henselBlocks(fNew, order, loc);
     4344    for(j = start; j <= size(compsT); j++)
     4345    {
     4346      comps[comp] = subst(compsT[j], y, y + ratPart);
     4347      comp++;
     4348    }
     4349  } else
     4350  {
     4351    comps[1] = f;
     4352  }
     4353  return(comps);
     4354}
     4355
     4356///////////////////////////////////////////////////////////////////////
     4357//
     4358//                             Auxiliary tools
     4359//
     4360///////////////////////////////////////////////////////////////////////
     4361
     4362// Checks if the term of highest degree in y of f contains x.
     4363static proc isXMonic(poly f){
     4364  //"START - integralbasis.lib - isXMonic";
     4365  matrix c = coeffs(f,var(2));
     4366  return(deg(c[size(c), 1]) == 0);
     4367}
     4368
     4369// Check if the only singularity is at the origin
     4370static proc checkAt0(poly f, int modular)
     4371{
     4372  def R = basering;
     4373
     4374  int vdDS, vd32003;
     4375  int vdx, vdy;
     4376
     4377  // vdim at origin (using ds ordering)
     4378  //"checking at 0";
     4379  list rlDS = ringlist(R);
     4380  rlDS[3] = list(list("C", 0), list("ds", intvec(1,1)));
     4381  def S1 = ring(rlDS);
     4382  setring S1;
     4383  poly f = imap(R, f);
     4384  ideal SL = f, diff(f, var(1)), diff(f, var(2));
     4385
     4386  if(modular == 0)
     4387  {
     4388    SL = groebner(SL);
    3664389  } else {
    367     poly condu = getOneVar(J, denomOption);
    368   }
    369 
    370 //------------------- components of the singular locus------------------------
    371   list pd = primdecGTZ(J);
    372   if(dbg >= 2){
    373     "primary decomposition time:", timer - t;
    374   }
    375   if(dbg >= 1){
    376     "The number of components of the Singular Locus is ", size(pd);
    377   }
    378 
    379   // The following commented lines are not needed for integral basis, since
    380   // all components are maximal.
    381   // Computes the maximal components and the components included in them
    382   //list comps = maxComps(pd);
    383   // For each maximal component, it intersects all the components included in it
    384   //list locs = intersectList(comps);
    385 
    386 //------------------- normalization of each component--------------------------
    387   list opts;
    388   for(i = 1; i <= size(pd); i++){
    389     //opts = #;
    390     // We use the prime components as test ideals in the normalization.
    391     //opts = list(list("inputJ", pd[i][2]));
    392     // We use the primary components as conductor in the normalization.
    393     opts = list(list("inputC", pd[i][1]));
    394 
    395     if(dbg >= 2){
    396       t = timer;
    397     }
    398     n = normal(I, opts);
    399     if(dbg >= 2){
    400       "normalization of component ", i, " time: ", timer - t;
    401     }
    402     if(size(n[2]) > 1){
    403       ERROR("The input polynomial is not irreducible.");
    404     }
    405 
    406     // We add up the normalizations at each localization, to construct the
    407     // normalization of the whole ideal.
    408     norT = n[2][1];
    409     denomT = norT[size(norT)];
    410 
    411     // We change the denominator of the normalization of the localized ring,
    412     // to have the same denominator for all the normalizations.
    413     nor = changeDenominator(norT, denomT, condu, I);
    414 
    415     // We sum the result to the previous results.
    416     res = res, nor;
    417   }
    418   res = groebner(res);
    419   res[size(res)+1] = condu;
    420 
    421   // The output follows the output of proc normal, but we don't return the
    422   // ring structure, only the generators. (We return 0 instead of the ring.)
    423   return(list(0,list(res)));
    424 }
    425 
     4390    SL = modStd(SL);
     4391  }
     4392  vdDS = vdim(SL);
     4393  setring R;
     4394
     4395  // vdim at affine ring (using char 32003)
     4396  list rl32003 = ringlist(R);
     4397  rl32003[1] = 32003;
     4398  def S2 = ring(rl32003);
     4399  setring S2;
     4400  poly f = imap(R, f);
     4401  ideal SL = f, diff(f, var(1)), diff(f, var(2));
     4402  SL = groebner(SL);
     4403  vd32003 = vdim(SL);
     4404  setring R;
     4405  if(vdDS == vd32003)
     4406  {
     4407
     4408    // vdim at charts (using char 32003)
     4409    ring S = 0, (x,y,z), dp;
     4410    poly f = fetch(R, f);
     4411    f = homog(f, z);
     4412
     4413    poly fy = subst(f, y, 1);
     4414    poly fx = subst(f, x, 1);
     4415
     4416    ring Sx = 32003, (y, z), dp;
     4417    poly fx5 = imap(S, fx);
     4418    ideal J = fx5, diff(fx5, y), diff(fx5, z);
     4419    J = groebner(J);
     4420    vdx = vdim(J);
     4421
     4422    ring Sy = 32003, (x, z), dp;
     4423    poly fy5 = imap(S, fy);
     4424    ideal J = fy5, diff(fy5, x), diff(fy5, z);
     4425    J = groebner(J);
     4426    vdy = vdim(J);
     4427
     4428    if((vdx == 0) && (vdy == 0))
     4429    {
     4430      // No singularities at infinity
     4431      return(1);
     4432    } else
     4433    {
     4434      // Singularities at infinity
     4435      "Singularities at infinity";
     4436      return(0);
     4437    }
     4438  } else
     4439  {
     4440    "Check at origin: FALSE";
     4441    return(0);
     4442  }
     4443  kill vdDS, vd32003;
     4444  kill S1, S2;
     4445  kill rlDS, rl32003;
     4446}
     4447
     4448static proc xCondu(poly px, list norOut, ideal I)
     4449{
     4450  ideal XC = quotient(norOut[2]+I, norOut[1]);
     4451  ideal XCX = eliminate(XC, var(2));
     4452  //"The x-conductor is ", XCX[1];
     4453  return(XCX[1]);
     4454}
     4455
     4456// Compose the tower of minimimal polynomials.
     4457// We assume that the polynomials are given in the second variable.
     4458// The first polynomial in the list is not used.
     4459static proc composePolys(list minPolys)
     4460{
     4461  int i;
     4462  poly mp = minPolys[size(minPolys)];
     4463  for(i = size(minPolys)-1; i > 1; i--)
     4464  {
     4465    mp = subst(mp, var(2), minPolys[i]);
     4466  }
     4467  return(mp);
     4468}
     4469
     4470// We work in a ring extension from a ring extension, and we compute the
     4471// coefficients of f in the original ring (we assume they are elements of the
     4472// original ring).
     4473// poly alpha is the primitive element of the first extension mapped into the
     4474// extended ring
     4475// d is the degree of the original extension
     4476static proc extendBack(poly f, poly alpha, int d)
     4477{
     4478  def R = basering;
     4479  ideal I;
     4480  for(int i = 1; i <= d; i++)
     4481  {
     4482    I[i] = alpha^(i-1);
     4483  }
     4484
     4485  ring S = 0, (var(1), var(2), @a), dp;
     4486  poly f = imap(R, f);
     4487  ideal I = imap(R, I);
     4488  module M = coeffs(I, @a);
     4489  matrix CC = coef(f, var(1)*var(2));
     4490  module P;
     4491  matrix L;
     4492  int j;
     4493  ideal rel;
     4494  for(i = 1; i <= ncols(CC); i++)
     4495  {
     4496    P = coeffs(CC[2, i], @a);
     4497    L = lift(M, P);
     4498    rel[i] = 0;
     4499    for(j = 1; j <= nrows(L); j++)
     4500    {
     4501      rel[i] = rel[i] + L[j, 1] * var(1)^(j-1);
     4502    }
     4503
     4504  }
     4505  setring R;
     4506  ideal rel = imap(S, rel);
     4507  return(rel);
     4508}
     4509
     4510static proc changeDenominatorFast(ideal U1, poly c1, poly c2, ideal I)
     4511{
     4512  //"changeDenominatorFast";
     4513  ideal U2 = quotient(c2*U1+I, c1);
     4514  return(U2);
     4515}
     4516
     4517static proc trivialBasis(poly f)
     4518{
     4519  int j;
     4520
     4521  intvec vy = (0, 1);
     4522  int n = deg(f, vy);
     4523  ideal l;
     4524
     4525  for(j = 0; j < n; j++)
     4526  {
     4527    l[j+1] = var(2)^j;
     4528  }
     4529  return(list(l, poly(1)));
     4530}
     4531
     4532static proc isOneIdeal(ideal I)
     4533{
     4534  I = groebner(I);
     4535  int i;
     4536  int out = 0;
     4537
     4538  for (i = 1; i <= ncols(I); i++)
     4539  {
     4540    if(I[i] == 1){out = 1;}
     4541  }
     4542  return(out);
     4543}
     4544
     4545static proc isZeroIdeal(ideal I)
     4546{
     4547  int i;
     4548  int out = 1;
     4549  for (i = 1; i <= ncols(I); i++)
     4550  {
     4551    if(I[i] != 0){out = 0;}
     4552  }
     4553  return(out);
     4554}
     4555
     4556////////////////////////////////////////////////////////////////////////////////
     4557// SPECIAL ALGORITHM FOR SINGULARITIES WITH SAME X-COORDINATE
     4558////////////////////////////////////////////////////////////////////////////////
     4559
     4560// Case: singularity with non-rational Y coordinate, and X = 0.
     4561// py is a polynomial in Y, whose roots are the Y-coordinate of the
     4562// singuarities.
     4563static proc ibNonRatY(poly f, poly py, int locBasis){
     4564  // We have singularities at <x, roots of(py)>.
     4565  int i;
     4566  int b;    // Multiplicity of the singularity.
     4567  int dbg = printlevel - voice + 5;
     4568
     4569  poly x = var(1);
     4570  poly y = var(2);
     4571  intvec vY = (0,1);
     4572  intvec vX = (1,0);
     4573
     4574  def R = basering;
     4575  int d = deg(f,vY);
     4576
     4577  // We add one of the roots of py to the basering.
     4578  def S = splitRingAt(py);
     4579  setring S;
     4580  poly f = fetch(R, f);
     4581  poly py = fetch(R, py);
     4582
     4583  // Initial terms of the Puiseux expansion of f at the singularity, y = PE.
     4584  poly PE = par(1);
     4585
     4586  // We move the singularity to the origin
     4587  poly fT = subst(f, var(2), var(2) + par(1));
     4588
     4589  // We compute the integral basis with the singularity at the origin.
     4590  list ib = ibNonRatYSplit(fT, f, py, PE, locBasis);
     4591
     4592  // We do not need to move back the integral basis, because it is already
     4593  // computed using the original f.
     4594
     4595  // Back to the original ring
     4596  setring R;
     4597  list ib = imap(S, ib);
     4598  return(ib);
     4599}
     4600
     4601// fOrig and py are the original polynomials, they will not be changed.
     4602// f and PE are changed so as to compute the puiseux expansions
     4603static proc ibNonRatYSplit(poly f, poly fOrig, poly py, poly PE, int locBasis)
     4604{
     4605  debug_log_intbas(4, "--------START - integralbasis.lib - ibLocalNonRatYSplit");
     4606//  "f", f;
     4607//  "fOrig", fOrig;
     4608//  "py", py;
     4609//  "PE", PE;
     4610//  "locBasis", locBasis;
     4611//  "basering", basering;
     4612
     4613  int i;
     4614  int dbg = printlevel - voice + 5;
     4615
     4616  poly x = var(1);
     4617  poly y = var(2);
     4618
     4619  intvec vY = (0,1);
     4620  intvec vX = (1,0);
     4621  int d = deg(fOrig,vY);
     4622
     4623  // We compute the multiplicity of the singularity.
     4624  poly f0 = subst(fOrig,x,0);
     4625  list fc = divideBy(f0, py);
     4626  int b = fc[2];
     4627
     4628  list dat = newtonInfo(f, b);
     4629
     4630  list ib;    // Integral basis
     4631  if(size(dat) == 0){
     4632    // The simple algorithm cannot be used.
     4633    return(list());
     4634  }
     4635  if(dat[1] == "changeCoord")
     4636  {
     4637    // The first term of the Puiseux expansions is repeated.
     4638    // We remove it and compute the integral basis recursively.
     4639    //"DBG - Change coord (linear term in PE)";
     4640    f = subst(f, y, y - dat[2]);
     4641
     4642    // We add the new terms of the Puiseux expansion
     4643    PE = PE - dat[2];
     4644
     4645    // We compute the integral basis
     4646    ib = ibNonRatYSplit(f, fOrig, py, PE, locBasis);
     4647
     4648    if(size(ib) > 0)
     4649    {
     4650      return(ib);
     4651    } else
     4652    {
     4653      // The integral basis could not be computed.
     4654      return(list());
     4655    }
     4656  }
     4657
     4658  // We run the algorithm
     4659  dbprint(dbg, "Simple algorithm is used for this component.");
     4660
     4661  poly f1, f2;    // fOrig(0,y) = f1*f2
     4662  f1 = py^b;
     4663  f2 = fc[1];
     4664
     4665  // Slope of the Newton polygon (giving the initial exponent)
     4666  int slN = dat[2];
     4667  int slD = dat[3];
     4668
     4669  // Degrees of the polynomials
     4670  int dU = deg(f2,vY);
     4671  int dPY = deg(py, vY);
     4672
     4673  // Maximum integrality exponent
     4674  int maxExpDen = (slN * (((d-1)-dU) div dPY)) div slD;
     4675  if(dbg >= 1)
     4676  {
     4677    "Hensel lifting - order = ", maxExpDen;
     4678  }
     4679  // We compute the lifiting of the factor outside the origin up to the
     4680  // maximum integrality exponent
     4681  list hen = henselGlobal(f1, f2, fOrig, maxExpDen);
     4682  poly p = hen[1];
     4683  poly u = hen[2];
     4684
     4685  // We multiply the conjugates of (y - PE) to get a polynomial over
     4686  // the ground field
     4687  poly PEGround = buildPolyFrac(PE);
     4688  //"PE: "; PE;
     4689  //"PEground: "; PEGround;
     4690
     4691  // We compute the integral basis from the data obtained.
     4692  // It will be a product of u (the factor outside the singularity) and
     4693  // powers of y and PEGround.
     4694  int expDen;
     4695  int expPY, expY;  // The exponent of py and y in the numerator.
     4696  int ordU;
     4697  if(locBasis == 0)
     4698  {
     4699    for(i = 0; i < d; i++){
     4700      if(i >= dU + dPY){
     4701        expDen = (slN * ((i-dU) div dPY)) div slD;
     4702        ordU = expDen - 1;
     4703        if (ordU < 0){ordU = 0;}
     4704        expPY = (int(i-dU) div dPY);
     4705        expY = i-dU-(expPY * dPY);
     4706        ib[i+1] = list(PEGround^expPY * y^expY, x^(expDen));
     4707        if(dU > 0){
     4708          ib[i+1][1] = ib[i+1][1] * jet(u, ordU, vX);
     4709        }
     4710      } else {
     4711        ib[i+1] = list(y^i, 1);
     4712      }
     4713    }
     4714  } else
     4715  {
     4716    for(i = 0; i < d - dU; i++)
     4717    {
     4718      if(i > 0)
     4719      {
     4720        expDen = (slN* (i div dPY)) div slD;
     4721        expPY = (i/dPY);
     4722        expY = i-(expPY * dPY);
     4723        ib[i+1] = list(py^expPY * y^expY, x^(expDen));
     4724      } else
     4725      {
     4726        ib[1] = list(1, 0);
     4727      }
     4728    }
     4729  }
     4730
     4731  // We put the integral basis in the usual form, with a common denominator.
     4732  poly den = ib[size(ib)][2];
     4733  ideal ibCom;
     4734  for(i = 1; i<= size(ib); i++){
     4735    ibCom[i] = ib[i][1]*den/ib[i][2];
     4736  }
     4737  list new = list(ibCom, den);
     4738  //"time for generating the base: "; timer - t;
     4739  return(new);
     4740}
     4741
     4742// Checks if two lists are equal
     4743static proc equalLists(list l1, list l2)
     4744{
     4745  int i;
     4746  if(size(l1) != size(l2))
     4747  {
     4748    return(0);
     4749  }
     4750  for(i = 1; i <= size(l1); i++)
     4751  {
     4752    if(l1[i] != l2[i])
     4753    {
     4754      return(0);
     4755    }
     4756  }
     4757  return(1);
     4758}
     4759
     4760
     4761// Merge classes if the corresponding factors are not over the ground field
     4762// Takes as input the output of proc irreducibleFactors
     4763
     4764static proc mergeClassesIF(poly f, list classes, list ifOut, int mdm)
     4765{
     4766  int h, i, j;
     4767
     4768  list cl;
     4769
     4770  int rep = 0;
     4771
     4772  for(i = 1; i <= size(classes); i++)
     4773  {
     4774    if(ifOut[2][i+1] == 0)
     4775    {
     4776      "Recombination of conjugation classes is not fully implemented. ";
     4777      "Please check output.";
     4778
     4779      rep = 1;
     4780
     4781      cl = getClassVector(classes[i]);
     4782      for(h = 1; h <= size(classes); h++)
     4783      {
     4784        if(i != h)
     4785        {
     4786          if(sameClass(cl, getClassVector(classes[h]), 1))
     4787          {
     4788            classes[h] = setClassVector(classes[h], cl);
     4789          }
     4790        }
     4791      }
     4792      break;
     4793    }
     4794  }
     4795
     4796  // Regroup classes
     4797  list classesNew;
     4798  for(i = 1; i <= size(classes); i++)
     4799  {
     4800    classesNew = classesNew + classes[i];
     4801  }
     4802  classes = getClasses(classesNew);
     4803
     4804  if(rep == 1)
     4805  {
     4806    ifOut = irreducibleFactors(f, classes, mdm);
     4807    if(ifOut[3] == 0)
     4808    {
     4809      classes = mergeClassesIF(f, classes, ifOut, mdm);
     4810    }
     4811  }
     4812  return(list(classes, ifOut));
     4813}
     4814
     4815static proc mergeTwoClasses(list classes, int a1, int a2)
     4816{
     4817  classes[a1] = classes[a1] + classes[a2];
     4818  classes = delete(classes,a2);
     4819  return(classes);
     4820}
     4821
     4822
     4823/////////////////////////////////////////////////////////////////////
     4824
     4825// splitring from primitiv.lib changed so that the variables
     4826// are named @a and not a
     4827
     4828static proc splitRingAt(poly f,list #)
     4829"USAGE:   splitringAt(f[,L]); f poly, L list of polys and/or ideals
     4830         (optional)
     4831ASSUME:  f is univariate and irreducible over the active ring. @*
     4832         The active ring must allow an algebraic extension (e.g., it cannot
     4833         be a transcendent ring extension of Q or Z/p).
     4834RETURN:  ring; @*
     4835           if called with a nonempty second parameter L, then in the output
     4836           ring there is defined a list erg ( =L mapped to the new ring);
     4837           if the minpoly of the active ring is non-zero, then the image of
     4838           the primitive root of f in the output ring is appended as last
     4839           entry of the list erg.
     4840NOTE:    If the old ring has no parameter, the name @code{a} is chosen for the
     4841         parameter of R (if @code{a} is no ring variable; if it is, @code{b} is
     4842         chosen, etc.; if @code{a,b,c,o} are ring variables,
     4843         @code{splitring(f[,L])} produces an error message), otherwise the
     4844         name of the parameter is kept and only the minimal polynomial is
     4845         changed. @*
     4846         The names of the ring variables and the orderings are not affected. @*
     4847KEYWORDS: algebraic field extension; extension of rings
     4848EXAMPLE: example splitring;  shows an example
     4849"
     4850{
     4851 //----------------- split ist bereits eine proc in 'inout.lib' ! -------------
     4852 if (size(#)>=1) {
     4853    list L=#;
     4854    int L_groesse=size(L);
     4855 }
     4856 else { int L_groesse=-1; }
     4857 //-------------- ermittle das Minimalpolynom des aktuellen Rings: ------------
     4858 string minp=string(minpoly);
     4859
     4860 def altring=basering;
     4861 string charakt=string(char(altring));
     4862 string varnames=varstr(altring);
     4863 string algname;
     4864 int i;
     4865 int anzvar=size(maxideal(1));
     4866 //--------------- Fall 1: Bisheriger Ring hatte kein Minimalpolynom ----------
     4867 if (minp=="0") { // only possible without parameters (by assumption)
     4868  if (find(varnames,"@a")==0)        { algname="@a";}
     4869  else { if (find(varnames,"@b")==0) { algname="@b";}
     4870         else { if (find(varnames,"@c")==0)
     4871                                    { algname="@c";}
     4872         else { if (find(varnames,"@o")==0)
     4873                                    { algname="@o";}
     4874         else {
     4875           "** Sorry -- could not find a free name for the primitive element.";
     4876           "** Try e.g. a ring without '@a' or '@b' as variable.";
     4877           return();
     4878         }}
     4879       }
     4880  }
     4881  //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: -
     4882  execute("ring splt1="+charakt+","+algname+",dp;");
     4883  ideal abbnach=var(1);
     4884  for (i=1; i<anzvar; i++) { abbnach=abbnach,var(1); }
     4885  map nach_splt1=altring,abbnach;
     4886  execute("poly mipol="+string(nach_splt1(f))+";");
     4887  string Rminp=string(mipol);
     4888  //~;
     4889
     4890  //--------------------- definiere den neuen Ring: ---------------------------
     4891  list ordStrNew = ordstr(altring);
     4892  int jj = attrib(altring,"maxExp");
     4893
     4894  ordStrNew = ordStrNew + list("L", jj);
     4895
     4896  execute("ring neuring = ("+charakt+","+algname+"),("+varnames+"),("
     4897           +ordstr(altring)+");");
     4898  execute("minpoly="+Rminp+";");
     4899
     4900  //---------------------- Berechne die zurueckzugebende Liste: ---------------
     4901  if (L_groesse>0) {
     4902   list erg;
     4903   map take=altring,maxideal(1);
     4904   erg=take(L);
     4905  }
     4906 }
     4907 else {
     4908
     4909  //------------- Fall 2: Bisheriger Ring hatte ein Minimalpolynom: -----------
     4910  algname=parstr(altring);           // Name des algebraischen Elements
     4911  if (npars(altring)>1) {"only one Parameter is allowed!!"; return(altring);}
     4912
     4913  //---------------- Minimalpolynom in ein Polynom umwandeln: -----------------
     4914  execute("ring splt2="+charakt+","+algname+",dp;");
     4915  execute("poly mipol="+minp+";");
     4916  // f ist Polynom in algname und einer weiteren Variablen -> mache f bivariat:
     4917  execute("ring splt3="+charakt+",("+algname+","+varnames+"),dp;");
     4918  poly f=imap(altring,f);
     4919
     4920  //-------------- Vorbereitung des Aufrufes von primitive: -------------------
     4921  execute("ring splt1="+charakt+",(x,y),dp;");
     4922  ideal abbnach=x;
     4923  for (i=1; i<=anzvar; i++) { abbnach=abbnach,y; }
     4924  map nach_splt1_3=splt3,abbnach;
     4925  map nach_splt1_2=splt2,x;
     4926  ideal maxid=nach_splt1_2(mipol),nach_splt1_3(f);
     4927  ideal primit=primitive(maxid);
     4928  if (size(primit)==0) {             // Suche mit 1. Proc erfolglos
     4929    primit=primitive_extra(maxid);
     4930  }
     4931  //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: -
     4932  setring splt2;
     4933  map nach_splt2=splt1,0,var(1);     // x->0, y->a
     4934  minp=string(nach_splt2(primit)[1]);
     4935  if (printlevel > -1) { "// new minimal polynomial:",minp; }
     4936  //--------------------- definiere den neuen Ring: ---------------------------
     4937  execute("ring neuring = ("+charakt+","+algname+"),("+varnames+"),("
     4938          +ordstr(altring)+");");
     4939  execute("minpoly="+minp+";");
     4940
     4941  if (L_groesse>0) {
     4942    //---------------------- Berechne die zurueckzugebende Liste: -------------
     4943    list erg;
     4944    setring splt3;
     4945    list zwi=imap(altring,L);
     4946    map nach_splt3_1=splt1,0,var(1);  // x->0, y->a
     4947    //----- rechne das primitive Element von altring in das von neuring um: ---
     4948    ideal convid=maxideal(1);
     4949    convid[1]=nach_splt3_1(primit)[2];
     4950    poly new_b=nach_splt3_1(primit)[3];
     4951    map convert=splt3,convid;
     4952    zwi=convert(zwi);
     4953    setring neuring;
     4954    erg=imap(splt3,zwi);
     4955    erg[size(erg)+1]=imap(splt3,new_b);
     4956  }
     4957 }
     4958 if (defined(erg)){export erg;}
     4959 return(neuring);
     4960}
     4961example
     4962{ "EXAMPLE:"; echo = 2;
     4963 ring r=0,(x,y),dp;
     4964 def r1=splitring(x2-2);
     4965 setring r1; basering;    // change to Q(sqrt(2))
     4966 // change to Q(sqrt(2),sqrt(sqrt(2)))=Q(a) and return the transformed
     4967 // old parameter:
     4968 def r2=splitring(x2-a,a);
     4969 setring r2; basering; erg;
     4970 // the result is (a)^2 = (sqrt(sqrt(2)))^2
     4971 kill r1; kill r2;
     4972}
    4264973///////////////////////////////////////////////////////////////////////////////
    4274974
    428 static proc cancelCF(list IB)
    429 "USAGE:  cancelCF(IB); IB list of type returned by integralBasis
    430 RETURN:  list of same type with  common factor cancelled.
    431 KEYWORDS: greatest common divisor.
     4975
     4976static proc getClassVector(list cl);
     4977{
     4978  if(typeof(cl[1]) == "ring")
     4979  {
     4980    def S = cl[1];
     4981    setring S;
     4982    list clVec = PE[1][6];
     4983  } else
     4984  {
     4985    list clVec = cl[1][6];
     4986  }
     4987  return(clVec);
     4988}
     4989
     4990static proc setClassVector(list cl, list clVec);
     4991{
     4992  def R = basering;
     4993  int i, j;
     4994  for(i = 1; i <=size(cl); i++)
     4995  {
     4996    if(typeof(cl[i]) == "ring")
     4997    {
     4998      def S = cl[i];
     4999      setring S;
     5000      for(j = 1; j <= size(PE); j++)
     5001      {
     5002        PE[j][6] = clVec;
     5003      }
     5004      setring R;
     5005      kill S;
     5006    } else
     5007    {
     5008      for(j = 1; j <= size(cl); j++)
     5009      {
     5010        cl[j][6] = clVec;
     5011      }
     5012
     5013    }
     5014  }
     5015  return(cl);
     5016}
     5017
     5018static proc sameClass(list l1, list l2, int offset)
     5019{
     5020  int i;
     5021  int same = 1;
     5022  for(i = 1; i <= size(l1) - offset; i++)
     5023  {
     5024    if(l1[i] != l2[i])
     5025    {
     5026      same = 0;
     5027    }
     5028  }
     5029  return(same);
     5030}
     5031
     5032
     5033// proc checkClass(list expClass)
     5034// {
     5035//     // If there is only one expansion in the class, there is nothing to do
     5036//     if(typeof(expClass[1]) == "ring")
     5037//     {
     5038//       for(j = 1; j <= size(classes[i]); j++)
     5039//       {
     5040//         if(typeof(classes[i][j]) == "ring")
     5041//         {
     5042//           S = classes[i][j];
     5043//           setring S;
     5044//           if(typeof(PE[1][7])!= "none")
     5045//           {
     5046//
     5047
     5048///////////////////////////////////////////////////////////////////////////////
     5049// Copied from classify.lib
     5050static proc init_debug_intbas(list #)
     5051"USAGE:    init_debug([level]);  level=int
     5052COMPUTE:  Set the global variable @DeBug to level. The variable @DeBug is
     5053          used by the function debug_log_intbas(level, list of strings) to know
     5054          when to print the list of strings. init_debug() reports only
     5055          changes of @DeBug.
     5056NOTE:     The procedure init_debug(n); is usefull as trace-mode. n may
     5057          range from 0 to 10, higher values of n give more information.
     5058EXAMPLE:  example init_debug; shows an example"
     5059{
     5060  int newDebug=0;
     5061  if( defined(@DeBug) != 0 ) { newDebug = @DeBug; }
     5062
     5063  if( size(#) > 0 )
     5064  {
     5065    newDebug=#[1];
     5066  }
     5067  else
     5068  {
     5069    string s=system("getenv", "SG_DEBUG");
     5070    if( s != "" && defined(@DeBug)==0)
     5071    {
     5072      s="newDebug="+s;
     5073      execute(s);
     5074    }
     5075  }
     5076  if( defined(@DeBug) == 0)
     5077  {
     5078    int @DeBug = newDebug;
     5079    export @DeBug;
     5080    if(@DeBug>0) { "Debugging level is set to ", @DeBug; }
     5081  }
     5082  else
     5083  {
     5084    if( (size(#) == 0) && (newDebug < @DeBug) ) { return(); }
     5085    if( @DeBug != newDebug)
     5086    {
     5087      int oldDebug = @DeBug;
     5088      @DeBug = newDebug;
     5089      if(@DeBug>0) { "Debugging level change from ", oldDebug, " to ",@DeBug; }
     5090      else
     5091      {
     5092        if( @DeBug==0 && oldDebug>0 ) { "Debugging switched off."; }
     5093      }
     5094    }
     5095  }
     5096  //printlevel = @DeBug;
     5097}
     5098example
     5099{ "EXAMPLE:"; echo=2;
     5100  init_debug();
     5101  debug_log_intbas(1,"no trace information printed");
     5102  init_debug(1);
     5103  debug_log_intbas(1,"some trace information");
     5104  init_debug(2);
     5105  debug_log_intbas(2,"nice for debugging scripts");
     5106  init_debug(0);
     5107}
     5108
     5109///////////////////////////////////////////////////////////////////////////////
     5110static proc debug_log_intbas (int level, list #)
     5111"USAGE:    debug_log_intbas(level,li); level=int, li=comma separated \"message\" list
     5112COMPUTE:  print \"messages\" if level>=@DeBug.
     5113          useful for user-defined trace messages.
     5114EXAMPLE:  example debug_log_intbas; shows an example
     5115SEE ALSO: init_debug
    4325116"
    4335117{
    434   int l = size(IB[1]);
    435   poly GrCoDi = IB[2];
    436   int k = l;
    437   while((GrCoDi != 1) && (k >=1))
    438       {
    439         GrCoDi = gcd(GrCoDi,IB[1][k]);
    440         k = k-1;
    441       }
    442   if(GrCoDi != 1)
    443     {
    444       for(k = 1; k <= l; k++)
    445          {
    446            IB[1][k] = IB[1][k]/GrCoDi;
    447          }
    448       IB[2] = IB[2]/GrCoDi;
    449     }
    450   return(IB);
    451 }
     5118   int len = size(#);
     5119//   int printresult = printlevel - level +1;
     5120//   if(level>1)
     5121//   {
     5122//     dbprint(printresult, "Debug:("+ string(level)+ "): ", #[2..len]);
     5123//   }
     5124//   else { dbprint(printresult, #[1..len]); }
     5125   if( defined(@DeBug) == 0 ) { init_debug_intbas(); }
     5126   if(@DeBug>=level)
     5127   {
     5128      if(level>1) { "Debug:("+ string(level)+ "): ", #[1..len]; }
     5129      else { #[1..len]; }
     5130   }
     5131}
     5132example
     5133{ "EXAMPLE:"; echo=2;
     5134  example init_debug;
     5135}
     5136
     5137static proc debug_lvl()
     5138{
     5139  int j = @DeBug;
     5140  return(j);
     5141}
     5142
     5143// Alternative procedure for computing characteristic exponents
     5144// from the exponentes of the series.
     5145// Not used beacuse we need to use characteristic orders, it is
     5146// not enough to compute the characteristic exponents.
     5147static proc charExp(intvec v, int k)
     5148{
     5149  intvec vNew;
     5150  int i = 1;
     5151  int ind = 1;
     5152  while ((v[i] mod k) == 0)
     5153  {
     5154    i++;
     5155  }
     5156  vNew[1] = v[i];
     5157  ind++;
     5158  int g = gcd(k, vNew[1]);
     5159  while(i <= size(v))
     5160  {
     5161    while((v[i] mod g) == 0)
     5162    {
     5163      i++;
     5164      if(i > size(v)){break;}
     5165    }
     5166    if(i <= size(v))
     5167    {
     5168      vNew[ind] = v[i];
     5169      g = gcd(g, vNew[ind]);
     5170      ind++;
     5171    }
     5172  }
     5173  return(vNew);
     5174}
     5175
     5176
     5177
    4525178/////////////////////////////////////////////////////////////////////////////
    4535179/////////////////////////////////////////////////////////////////////////////
     
    4875213integralBasis(f, 2);
    4885214f =1/11*f;
     5215integralBasis(f, 2);  // local by default, time 0
    4895216integralBasis(f, 2, "global");  // time 2
    490 integralBasis(f, 2);  // local by default, time 0
    4915217kill RR;
    4925218// -------------------------------------------------------
     
    5075233ring RR = 0, (x,y), dp;
    5085234poly f = fetch(SS,f);
    509 integralBasis(f, 2);  integralBasis(f, 2, "global");  // time 1
    5105235integralBasis(f, 2);  // local by default, time 0
     5236integralBasis(f, 2, "global");  // time 1
    5115237kill RR, SS;
    5125238// -------------------------------------------------------
     
    5675293kill RR, SS;
    5685294*/
    569 
    570 
  • Tst/Manual/integralBasis.res.gz.uu

    r1edfd9 r7d6fbd  
    11begin 640 integralBasis.res.gz
    2 M'XL(",0I<DX``VEN=&5G<F%L0F%S:7,N<F5S`'52RV[",!"\YRM6J(<@0B#!
    3 M]!7A`^H%"55"X8802HBAEAP'Q0Z-_[[KD$=[Z,FSN[/CV;7C_<?F$P`""MO-
    4 M&D9::5_P=!0!HA.77+OCR+$G4`I<:G8M$[%.%%>^9-^^THEVXE8D;$4Z6MK0
    5 M&KF>LZ!P*Y$@V)T)6/T*)L'`(A0P?P6%C+GGUIX9>]EMJ"]1I1`&+E@WRZDA
    6 M]828L`ZG-1E(SQ0$5QKL-7^<NQ</0AQK_\5`5GG*2B@N<"[R6R&9U,I&&FLQ
    7 M6JA$4L*V.%<*N,(]]>HOJ!XYA^#X[F!T0K"J%P\86F@>>($X-.$C(!B8EK0\
    8 MK@R9$"PZV-"(8'^G_DIA-@-KL',.S38[:WWV+`I5E<SF=X?ZB`78-?O">20V
    9 M:-5KOOE6LQ5@@N7=K`+-0\;O/&,9I*:IV_7*(N=XA4!_?J<2S/W_'G`Z/&"`
    10 6_\E^(/L]*N4&X^C)^0$NE;9J:P(`````
     2M'XL(")KPP6$"`VEN=&5G<F%L0F%S:7,N<F5S`(53P4[C,!"]^RM&:`^IVAB2
     3MINPN57-@N51"2!7L"57(3=S6DF-7L0/QWS-V0DJTBSAE/._-FS?.^/'I;OT`
     4M`$D.]^M;N+#&4BEV%TO`Z$4H8:/)DO@OY#D(9?FA9O*6&6&HXF_46&;)8R^2
     5M]B(?M%V@!;F!,\_A5"-!\E<N8?7I,$W.K"P'S!_`(.-J%K4S-YF5IS.^0!4M
     6M'>P1=XO89>TT<VF;QFUV)EWG((6QX-N,G$?[&:0XUA]=G1KK^]@C'RC0V::4
     7MQ/&8P8S1A6"6E]YVQ0WH?0`,,AK):I"Z:$(I0/379T%I%5>Z#"B3!UT+>ZSH
     8MY!_M<7=@%C@KCE`@22NN;.?GFRJT,Q0`28:"D+@!$L#G9+MR?9AN5RU9CT6*
     9MT(%9H17L\<^;(R_I<*D_\5*7!#5N<$9X\6+MO`N]V-QU\1SCU*7=(<.#ZTD+
     10M;)Y-,P0)%@01K/]0_Y7#Y24\_7>RT;R%U*:IN<]OGMLM`K`):X+V%198,VC^
     11MIEZS%^"25W@705"B>2C%JRCQA^Y<P/U6*5T);"'1WS!W<D6_VMOXO+<)/B/_
     123;ORK:$R43)8_R#LE93,Z8@,`````
    1113`
    1214end
  • Tst/Manual/integralBasis.stat

    r1edfd9 r7d6fbd  
    1 1 >> tst_memory_0 :: 1316104113:3132- exportiert :3-1-3:ix86-Linux:mamawutz:385436
    2 1 >> tst_memory_1 :: 1316104113:3132- exportiert :3-1-3:ix86-Linux:mamawutz:962560
    3 1 >> tst_memory_2 :: 1316104113:3132- exportiert :3-1-3:ix86-Linux:mamawutz:1023876
    4 1 >> tst_timer_1 :: 1316104113:3132- exportiert :3-1-3:ix86-Linux:mamawutz:32
     11 >> tst_memory_0 :: 1640099994:4212, 64 bit:4.2.1:x86_64-Linux:nepomuck:486208
     21 >> tst_memory_1 :: 1640099994:4212, 64 bit:4.2.1:x86_64-Linux:nepomuck:2482176
     31 >> tst_memory_2 :: 1640099994:4212, 64 bit:4.2.1:x86_64-Linux:nepomuck:2650112
     41 >> tst_timer_1 :: 1640099994:4212, 64 bit:4.2.1:x86_64-Linux:nepomuck:12
  • doc/NEWS.texi

    r1edfd9 r7d6fbd  
    3434@item sagbigrob.lib: Sagbi-Groebner basis of an ideal of a subalgebra (@nref{sagbigrob_lib})
    3535@item puiseuxexpansion.lib: Puiseux expansions over algebraic extensions (@nref{puiseuxexpansioni_lib})
     36@item integralbasis_lib: Integral basis in algebraic function fields: new version (@nref{integralbasis_lib})
    3637@end itemize
    3738
Note: See TracChangeset for help on using the changeset viewer.