source: git/Singular/LIB/standard.lib @ 1a106c

spielwiese
Last change on this file since 1a106c was 1a106c, checked in by Hans Schoenemann <hannes@…>, 2 years ago
add groebner(i,"HC")
  • Property mode set to 100644
File size: 76.5 KB
Line 
1///////////////////////////////////////////////////////////////////////////
2version="version standard.lib 4.2.1.1 Jul_2021 "; // $Id$
3category="Miscellaneous";
4info="
5LIBRARY: standard.lib   Procedures which are always loaded at Start-up
6
7PROCEDURES:
8 stdfglm(ideal[,ord])   standard basis of ideal via fglm [and ordering ord]
9 stdhilb(ideal[,h])     Hilbert driven Groebner basis of ideal
10 groebner(ideal,...)    standard basis using a heuristically chosen method
11 res(ideal/module,[i])  free resolution of ideal or module
12 sprintf(fmt,...)       returns formatted string
13 fprintf(link,fmt,..)   writes formatted string to link
14 printf(fmt,...)        displays formatted string
15 weightKB(stc,dd,vl)    degree dd part of a kbase w.r.t. some weights
16 qslimgb(i)             computes a standard basis with slimgb in a qring
17 par2varRing([i])       create a ring making pars to vars, together with i
18 datetime()             return date and time as a string
19 max(i_1,...,i_k)       maximum of i_1, ..., i_k
20 min(i_1,...,i_k)       minimum of i_1, ..., i_k
21 create_ring(l1,l2,l3,l4) return ring(list(l1, l2, l3, l4))
22
23";
24//AUXILIARY PROCEDURES:
25// hilbRing([i])          ring for computing the (weighted) hilbert series
26// quotientList(L,...)    ringlist for creating a correct quotient ring
27
28//////////////////////////////////////////////////////////////////////////////
29
30proc stdfglm (ideal i, list #)
31"SYNTAX: @code{stdfglm (} ideal_expression @code{)} @*
32         @code{stdfglm (} ideal_expression@code{,} string_expression @code{)}
33TYPE:    ideal
34PURPOSE: computes the standard basis of the ideal in the basering
35         via @code{fglm} from the ordering given as the second argument
36         to the ordering of the basering. If no second argument is given,
37         \"dp\" is used. The standard basis for the given ordering (resp. for
38         \"dp\") is computed via the command groebner except if a further
39         argument \"std\" or \"slimgb\" is given in which case std resp.
40         slimgb is used.
41SEE ALSO: fglm, groebner, std, slimgb, stdhilb
42KEYWORDS: fglm
43EXAMPLE: example stdfglm; shows an example"
44{
45  string os;
46  int s = size(#);
47  def P= basering;
48  string algorithm;
49  int ii;
50  for( ii=1; ii<=s; ii++)
51  {
52    if ( typeof(#[ii])== "string" )
53    {
54      if ( #[ii]=="std" || #[ii]=="slimgb" )
55      {
56        algorithm =  #[ii];
57        # = delete(#,ii);
58        s--;
59        ii--;
60      }
61    }
62  }
63
64  if((s > 0) && (typeof(#[1]) == "string"))
65  {
66    os = #[1];
67    ideal Qideal = ideal(P);
68    int sQ = size(Qideal);
69    int sM = size(minpoly);
70    if ( sM!=0 )
71    {
72      string mpoly = string(minpoly);
73    }
74    if (sQ!=0 )
75    {
76      ring Rfglm = create_ring(ring_list(P)[1], "("+varstr(P)+")", os, "no_minpoly");
77      ideal Qideal = fetch(P,Qideal);
78      qring Pfglm = groebner(Qideal,"std","slimgb");
79    }
80    else
81    {
82      ring Pfglm = create_ring(ring_list(P)[1], "("+varstr(P)+")", os, "no_minpoly");
83    }
84    if ( sM!=0 )
85    {
86      execute("minpoly="+mpoly+";");
87    }
88  }
89  else
90  {
91    list BRlist = ring_list(P);
92    int nvarP = nvars(P);
93    intvec w;                       //for ringweights of basering P
94    int k;
95    for(k=1;  k <= nvarP; k++)
96    {
97      w[k]=deg(var(k));
98    }
99
100    BRlist[3] = list();
101    if( s==0 or (typeof(#[1]) != "string") )
102    {
103      if( w==1 )
104      {
105        BRlist[3][1]=list("dp",w);
106      }
107      else
108      {
109        BRlist[3][1]=list("wp",w);
110      }
111      BRlist[3][2]=list("C",intvec(0));
112      def Pfglm = ring(quotientList(BRlist));
113      setring Pfglm;
114    }
115  }
116  ideal i = fetch(P,i);
117
118  intvec opt = option(get);            //save options
119  option(redSB);
120  if (size(algorithm) > 0)
121  {
122    i = groebner(i,algorithm);
123  }
124  else
125  {
126    i = groebner(i);
127  }
128  option(set,opt);
129  setring P;
130  return (fglm(Pfglm,i));
131}
132example
133{ "EXAMPLE:"; echo = 2;
134   ring r  = 0,(x,y,z),lp;
135   ideal i = y3+x2,x2y+x2,x3-x2,z4-x2-y;
136   stdfglm(i);                   //uses fglm from "dp" (with groebner) to "lp"
137   stdfglm(i,"std");             //uses fglm from "dp" (with std) to "lp"
138
139   ring s  = (0,x),(y,z,u,v),lp;
140   minpoly = x2+1;
141   ideal i = u5-v4,zv-u2,zu3-v3,z2u-v2,z3-uv,yv-zu,yu-z2,yz-v,y2-u,u-xy2;
142   weight(i);
143   stdfglm(i,"(a(2,3,4,5),dp)"); //uses fglm from "(a(2,3,4,5),dp)" to "lp"
144}
145
146/////////////////////////////////////////////////////////////////////////////
147
148proc stdhilb(def i,list #)
149"SYNTAX: @code{stdhilb (} ideal_expression @code{)} @*
150         @code{stdhilb (} module_expression @code{)} @*
151         @code{stdhilb (} ideal_expression, intvec_expression @code{)}@*
152         @code{stdhilb (} module_expression, intvec_expression @code{)}@*
153         @code{stdhilb (} ideal_expression@code{,} list of string_expressions,
154               and intvec_expression @code{)} @*
155TYPE:    type of the first argument
156PURPOSE: Compute a Groebner basis of the ideal/module in the basering by
157         using the Hilbert driven Groebner basis algorithm.
158         If an argument of type string, stating @code{\"std\"} resp. @code{\"slimgb\"},
159         is given, the standard basis computation uses @code{std} or
160         @code{slimgb}, otherwise a heuristically chosen method (default)@*
161         If an optional second argument w of type intvec is given, w is used
162         as variable weights. If w is not given, it is computed as w[i] =
163         deg(var(i)). If the ideal is homogeneous w.r.t. w then the
164         Hilbert series is computed w.r.t. to these weights.
165THEORY:  If the ideal is not homogeneous compute first a Groebner basis
166         of the homogenization [w.r.t. the weights w] of the ideal/module,
167         then the Hilbert function and, finally, a Groebner basis in the
168         original ring by using the computed Hilbert function. If the given
169         w does not coincide with the variable weights of the basering, the
170         result may not be a groebner basis in the original ring.
171NOTE:    'Homogeneous' means weighted homogeneous with respect to the weights
172         w[i] of the variables var(i) of the basering. Parameters are not
173         converted to variables.
174SEE ALSO: stdfglm, std, slimgb, groebner
175KEYWORDS: Hilbert function
176EXAMPLE: example stdhilb;  shows an example"
177{
178
179//--------------------- save data from basering --------------------------
180  def P=basering;
181  int nr;
182  if (typeof(i)=="ideal") { nr=1;}
183  else                    { nr= nrows(i); }    //nr=1 if i is an ideal
184  ideal Qideal = ideal(P);      //defining the quotient ideal if P is a qring
185  int was_qring;                //remembers if basering was a qring
186  int is_homog =homog(i);       //check for homogeneity of i and Qideal
187  if (size(Qideal) > 0)
188  {
189     was_qring = 1;
190  }
191
192  // save ordering of basering P for later use
193  list ord_P = ring_list(P)[3];    //ordering of basering in ringlist
194  string ordstr_P = ordstr(P);     //ordering of basering as string
195  int nvarP = nvars(P);
196
197  //save options:
198  intvec gopt = option(get);
199  int p_opt;
200  string s_opt = option();
201  if (find(s_opt, "prot"))  { p_opt = 1; }
202
203//-------------------- check the given method and weights ---------------------
204//Note: stdhilb is used in elim where it is applied to an elimination ordering
205//a(1..1,0..0),wp(w). In such a ring deg(var(k)=0 for all vars corresponding to
206//0 in a(1..1,0..0), hence we cannot identify w via w[k] = deg(var(k));
207//Therefore hilbstd has the option to give ringweights.
208
209  int k;
210  string method;
211  for (k=1; k<=size(#); k++)
212  {
213    if (typeof(#[k]) == "intvec")
214    {
215        intvec w = #[k];         //given ringweights of basering P
216    }
217    if (typeof(#[k]) == "string")
218    {
219      method = method + "," + #[k];
220    }
221  }
222
223  if ( defined(w)!=voice )
224  {
225    intvec w;
226    for(k=nvarP;  k>=1; k--)
227    {
228       w[k] = deg(var(k));     //compute ring weights
229    }
230  }
231
232
233  if (npars(P) > 0)             //clear denominators of parameters
234  {
235    for( k=ncols(i); k>0; k-- )
236    {
237      i[k]=cleardenom(i[k]);
238    }
239  }
240
241//---------- exclude cases to which stdhilb should no be applied  ----------
242//Note that quotient ideal of qring must be homogeneous too
243
244  int neg=1-attrib (P,"global");
245
246  if( //find(ordstr_P,"s") ||// covered by neg
247     find(ordstr_P,"M") || neg )
248  {
249    // if( defined(hi) && is_homog )
250    // {
251    //  if (p_opt){"std with given Hilbert function in basering";}
252    //  return( std(i,hi,w) );
253    //### here we would need Hibert-Samuel function
254    // }
255
256    if (p_opt)
257    {"//-- stdhilb not implemented, we use std in ring:"; string(P);}
258    return( std(i) );
259  }
260
261//------------------------ change to hilbRing ----------------------------
262//The ground field of P and Philb coincide, Philb has an extra variable
263//@ or @(k). Philb is no qring and the predefined ideal/module Id[1] in
264//Philb is homogeneous (it is the homogenized i w.r.t. @ or @(k))
265//Parameters of P are not converted in Philb
266//Philb has only 1 block dp or wp(w)
267
268  list hiRi = hilbRing(i,w);
269  intvec W = hiRi[2];
270  def Philb = hiRi[1];
271  setring Philb;
272
273//-------- compute Hilbert series of homogenized ideal in Philb ---------
274//There are three cases
275
276  string algorithm;       //possibilities: std, slimgb, stdorslimgb
277  //define algorithm:
278  if( find(method,"std") && !find(method,"slimgb") )
279  {
280    algorithm = "std";
281  }
282  if( find(method,"slimgb") && !find(method,"std") )
283  {
284    algorithm = "slimgb";
285  }
286  if( find(method,"std") && find(method,"slimgb") ||
287    (!find(method,"std") && !find(method,"slimgb")) )
288  {
289    algorithm = "stdorslimgb";
290  }
291
292//### geaendert Dez08: es wird std(Id[1]) statt Id[1] aus Philb nach Phelp
293// weitergegeben fuer hilbertgetriebenen std
294
295  if (( algorithm=="std" || ( algorithm=="stdorslimgb" && char(P)>0 ) )
296  && (defined(hi)!=voice))
297  {
298    if (p_opt) {"compute hilbert series with std in ring " + string(Philb);
299                "weights used for hilbert series:",W;}
300    Id[1] = std(Id[1]);
301    intvec hi = hilb( Id[1],1,W );
302  }
303  if (( algorithm=="slimgb" || ( algorithm=="stdorslimgb" && char(P)==0 ) )
304  && (defined(hi)!=voice))
305  {
306    if (p_opt) {"compute hilbert series with slimgb in ring " + string(Philb);
307                "weights used for hilbert series:",W;}
308    Id[1] = qslimgb(Id[1]);
309    intvec hi = hilb( Id[1],1,W );
310  }
311
312  //-------------- we need another intermediate ring Phelp ----------------
313  //In Phelp we change only the ordering from Philb (otherwise it coincides
314  //with Philb). Phelp has in addition to P an extra homogenizing variable
315  //with name @ (resp. @(i) if @ and @(1), ..., @(i-1) are defined) with
316  //ordering an extra last block dp(1).
317  //Phelp has the same ordering as P on common variables. In Phelp
318  //a quotient ideal from P is added to the input
319
320  list BRlist = ring_list(Philb);
321  BRlist[3] = list();
322  int so = size(ord_P);
323  if( ord_P[so][1] =="c" || ord_P[so][1] =="C" )
324  {
325    list moduleord = ord_P[so];
326    so = so-1;
327  }
328  for (k=1; k<=so; k++)
329  {
330    BRlist[3][k] = ord_P[k];
331  }
332
333  BRlist[3][so+1] = list("dp",1);
334  w = w,1;
335
336  if( defined(moduleord)==voice )
337  {
338    BRlist[3][so+2] = moduleord;
339  }
340
341//--- change to extended ring Phelp and compute std with hilbert series ----
342  def Phelp = ring(quotientList(BRlist));
343  setring Phelp;
344  list Id= imap(Philb, Id); def i=Id[1];
345  kill Philb;
346
347  // compute std with Hilbert series
348  option(redThrough);
349  if (w == 1)
350  {
351    if (p_opt){ "std with hilb in " + string(Phelp);}
352    i = std(i, hi);
353  }
354  else
355  {
356    if(p_opt){"std with weighted hilb in "+string(Phelp);}
357    i = std(i, hi, w);
358  }
359
360//-------------------- go back to original ring ---------------------------
361//The main computation is done. Do not forget to simplfy before mapping.
362
363  // subst 1 for homogenizing var
364  if ( p_opt ) { "dehomogenization"; }
365  i = subst(i, var(nvars(basering)), 1);
366
367  if (p_opt) { "simplification"; }
368  i= simplify(i,34);
369
370  setring P;
371  if (p_opt) { "imap to ring "+string(P); }
372  i = imap(Phelp,i);
373  kill Phelp;
374  if( was_qring )
375  {
376    i = NF(i,std(0));
377  }
378  i = simplify(i,34);
379  // compute reduced SB
380  if (find(s_opt, "redSB") > 0)
381  {
382    if (p_opt) { "//interreduction"; }
383    i=interred(i);
384  }
385  attrib(i, "isSB", 1);
386  option(set,gopt);
387  return (i);
388}
389example
390{ "EXAMPLE:"; echo = 2;
391   ring  r = 0,(x,y,z),lp;
392   ideal i = y3+x2,x2y+x2z2,x3-z9,z4-y2-xz;
393   ideal j = stdhilb(i); j;
394
395   ring  r1 = 0,(x,y,z),wp(3,2,1);
396   ideal  i = y3+x2,x2y+x2z2,x3-z9,z4-y2-xz;  //ideal is homogeneous
397   ideal j = stdhilb(i,"std"); j;
398   //this is equivalent to:
399   intvec v = hilb(std(i),1);
400   ideal j1 = std(i,v,intvec(3,2,1)); j1;
401
402   size(NF(j,j1))+size(NF(j1,j));            //j and j1 define the same ideal
403}
404
405///////////////////////////////////////////////////////////////////////////////
406proc quotientList (list RL, list #)
407"SYNTAX: @code{quotientList (} list_expression @code{)} @*
408         @code{quotientList (} list_expression @code{,} string_expression@code{)}
409TYPE:    list
410PURPOSE: define a ringlist, say QL, of the first argument, say RL, which is
411         assumed to be the ringlist of a qring, but where the quotient ideal
412         RL[4] is not a standard basis with respect to the given monomial
413         order in RL[3]. Then QL will be obtained from RL just by replacing
414         RL[4] by a standard of it with respect to this order. RL itself
415         will be returned if size(RL[4]) <= 1 (in which case it is known to be
416         a standard basis w.r.t. any ordering) or if a second argument
417         \"isSB\" of type string is given.
418NOTE:    the command ring(quotientList(RL)) defines a quotient ring correctly
419         and should be used instead of ring(RL) if the quotient ideal RL[4]
420         is not (or not known to be) a standard basis with respect to the
421         monomial ordering specified in RL[3].
422SEE ALSO: ringlist, ring
423EXAMPLE: example quotientList; shows an example"
424{
425  def P = basering;
426  if( size(#) > 0 )
427  {
428    if ( #[1] == "isSB")
429    {
430      return (RL);
431    }
432  }
433  ideal Qideal  = RL[4];  //##Achtung: falls basering Nullteiler hat, kann
434                           //die SB eines Elements mehrere Elemente enthalten
435  if( size(Qideal) <= 0)
436  {
437    return (RL);
438  }
439
440  RL[4] = ideal(0);
441  def Phelp = ring(RL);
442  setring Phelp;
443  ideal Qideal = groebner(fetch(P,Qideal));
444  setring P;
445  RL[4]=fetch(Phelp,Qideal);
446  return (RL);
447}
448example
449{ "EXAMPLE:"; echo = 2;
450   ring P = 0,(y,z,u,v),lp;
451   ideal i = y+u2+uv3, z+uv3;            //i is an lp-SB but not a dp_SB
452   qring Q = std(i);
453   list LQ = ring_list(Q);
454   LQ[3][1][1]="dp";
455   def Q1 = ring(quotientList(LQ));
456   setring Q1;
457   Q1;
458
459   setring Q;
460   ideal q1 = uv3+z, u2+y-z, yv3-zv3-zu; //q1 is a dp-standard basis
461   LQ[4] = q1;
462   def Q2 = ring(quotientList(LQ,"isSB"));
463   setring Q2;
464   Q2;
465}
466
467///////////////////////////////////////////////////////////////////////////////
468proc par2varRing (list #)
469"USAGE:   par2varRing([l]); l list of ideals/modules [default:l=empty list]
470RETURN:  list, say L, with L[1] a ring where the parameters of the
471         basering have been converted to an additional last block of
472         variables, all of weight 1, and ordering dp.
473         If a list l with l[i] an ideal/module is given, then
474         l[i] + minpoly*freemodule(nrows(l[i])) is mapped to an ideal/module
475         in L[1] with name Id[i].
476         If the basering has no parameters then L[1] is the basering.
477EXAMPLE: example par2varRing; shows an example"
478{
479  def P = basering;
480  int npar = npars(P);  //number of parameters
481  int s = size(#);
482  int ii;
483  if ( npar == 0)
484  {
485    dbprint(printlevel-voice+3,"// ** no parameters, ring was not changed");
486    list Id=#;
487    export Id;
488    return(list(P));
489  }
490
491  list rlist = ringlist(P);
492  list parlist = rlist[1];
493  rlist[1] = parlist[1];
494
495  string @Minpoly = string(minpoly);     //check for minpoly:
496  int sm = size(minpoly);
497  //now create new ring
498  list Id=#;
499  int nvar = size(rlist[2]);
500  int nblock = size(rlist[3]);
501  int k;
502  for (k=1; k<=npar; k++)
503  {
504    rlist[2][nvar+k] = parlist[2][k];   //change variable list
505  }
506
507  //converted parameters get one block dp. If module ordering was in front
508  //it stays in front, otherwise it will be moved to the end
509  intvec OW = 1:npar;
510  if( rlist[3][nblock][1] =="c" || rlist[3][nblock][1] =="C" )
511  {
512    rlist[3][nblock+1] = rlist[3][nblock];
513    rlist[3][nblock] = list("dp",OW);
514  }
515  else
516  {
517    rlist[3][nblock+1] = list("dp",OW);
518  }
519
520  def Ppar2var = ring(quotientList(rlist));
521  setring Ppar2var;
522  if ( sm == 0 )
523  {
524    list Id=imap(P,Id);
525    export (Id);
526  }
527  else
528  {
529    if( find(option(),"prot") ){"//add minpoly to input";}
530    execute("poly Minpoly = " + @Minpoly + " ;");
531    list Id=imap(P,Id);
532    for( ii = 1; ii <= s; ii++)
533    {
534      if (typeof(Id[ii])=="module")
535      {
536        Id[ii] = Id[ii],Minpoly*freemodule(nrows(Id[ii]));
537      }
538      else
539      {
540        Id[ii] = Id[ii],Minpoly;
541      }
542    }
543    export (Id);
544  }
545  list Lpar2var = Ppar2var;
546  return(Lpar2var);
547}
548example
549{ "EXAMPLE:"; echo = 2;
550   ring R = (0,x),(y,z,u,v),lp;
551   minpoly = x2+1;
552   ideal i = x3,x2+y+z+u+v,xyzuv-1; i;
553   def P = par2varRing(i)[1]; P;
554   setring(P);
555   Id[1];
556
557   setring R;
558   module m = x3*[1,1,1], (xyzuv-1)*[1,0,1];
559   def Q = par2varRing(m)[1]; Q;
560   setring(Q);
561   print(Id[1]);
562}
563
564//////////////////////////////////////////////////////////////////////////////
565proc hilbRing ( list # )
566"USAGE:   hilbRing([w,l]); w = intvec, l = list of ideals/modules
567RETURN:  list, say L: L[1] is a ring and L[2] an intvec
568         L[1] is a ring with an extra homogenizing variable with name @,
569         resp. @(i) if @ and @(1), ..., @(i-1) are defined.
570         The monomial ordering of L[1] is consists of 1 block: dp if the
571         weights of the variables of the basering, say R, are all 1, resp.
572         wp(w,1) wehre w is either given or the intvec of weights of the
573         variables of R, i.e. w[k]=deg(var(k)).
574         If R is a quotient ring P/Q, then L[1] is not a quotient ring but
575         contains the ideal @Qidealhilb@, the homogenized ideal Q of P.
576         (Parameters of R are not touched).
577         If a list l is given with l[i] an ideal/module, then l[i] is mapped
578         to Id[i], the homogenized l[i]+Q*freemodule(nrows(l[i]) in L[1]
579         (Id[i] = l[i] if l[i] is already homogeneous).
580         L[2] is the intvec (w,1).
581PURPOSE: Prepare a ring for computing the (weighted) hilbert series of
582         an ideal/module with an easy monomial ordering.
583NOTE:    For this purpose we need w[k]=deg(var(k)). However, if the ordering
584         contains an extra weight vector a(v,0..0)) deg(var(k)) returns 0 for
585         k being an index which is 0 in a. Therefore we must compute w
586         beforehand and give it to hilbRing.
587EXAMPLE: example hilbRing; shows an example
588"
589{
590  def P = basering;
591  ideal Qideal = ideal(P);    //defining the quotient ideal if P is a qring
592  if( size(Qideal) != 0 )
593  {
594    int is_qring =1;
595  }
596  list BRlist = ring_list(P);
597  BRlist[4] = ideal(0);      //kill quotient ideal in BRlist
598
599  int nvarP = nvars(P);
600  int s = size(#);
601  int k;
602
603  for(k = 1; k <= s; k++)
604  {
605    if ( typeof(#[k]) == "intvec" )
606    {
607       intvec w = #[k];      //given weights for the variables
608       # = delete (#,k);
609    }
610  }
611
612  s = size(#);
613  list nr,Id;
614  Id=#;
615  for(k = 1; k <= s; k++)
616  {
617     if (typeof(#[k])=="module") { nr[k]=nrows(Id[k]); }
618     else                        { nr[k]=1; }
619  }
620
621  if ( defined(w)!=voice )
622  {
623    intvec w;                   //for ringweights of basering P
624    for(k=1;  k<=nvarP; k++)
625    {
626      w[k]=deg(var(k));        //degree of kth variable
627    }
628  }
629  //--------------------- a homogenizing variable is added ------------------
630  // call it @, resp. @(k) if @(1),...,@(k-1) are defined
631  string homvar;
632  if ( defined(@)==0 )
633  {
634    homvar = "@";
635  }
636  else
637  {
638    k=1;
639    while( defined(@(k)) != 0 )
640    {
641      k++;
642    }
643    homvar = "@("+string(k)+")";
644  }
645  BRlist[2][nvarP+1] = homvar;
646  w[nvarP +1]=1;
647
648  //ordering is set to (dp,C) if weights of all variables are 1
649  //resp. to (wp(w,1),C) where w are the ringweights of basering P
650  //homogenizing var gets weight 1:
651
652  BRlist[3] = list();
653  BRlist[3][2]=list("C",intvec(0));  //put module ordering always last
654  if(w==1)
655  {
656    BRlist[3][1]=list("dp",w);
657  }
658  else
659  {
660    BRlist[3][1]=list("wp",w);
661  }
662
663  //-------------- change ring and get ideal from previous ring ---------------
664  def Philb = ring(quotientList(BRlist));
665  kill BRlist;
666  setring Philb;
667  if( defined(is_qring)==voice )
668  {
669    ideal @Qidealhilb@ =  imap(P,Qideal);
670    if ( ! homog(@Qidealhilb@) )
671    {
672       @Qidealhilb@ =  homog( @Qidealhilb@, `homvar` );
673    }
674    export(@Qidealhilb@);
675
676    if( find(option(),"prot") ){"add quotient ideal to input";}
677
678    list Id=imap(P,Id);
679    for(k = 1; k <= s; k++)
680    { //homogenize if necessary
681      if ( ! homog(Id[k]) )
682      {
683         Id[k] =  homog( Id[k], `homvar` );
684      }
685      if (typeof(Id[k])=="module")
686      {
687        Id[k] =  Id[k],@Qidealhilb@*freemodule(nr[k]) ;
688      }
689      else
690      {
691        Id[k] =  Id[k],@Qidealhilb@ ;
692      }
693    }
694  }
695  else
696  {
697    list Id=imap(P,Id);
698    for(k = 1; k <= s; k++)
699    { //homogenize if  necessary
700      if ( ! homog(Id[k]) )
701      {
702         Id[k] =  homog( Id[k], `homvar` );
703      }
704    }
705  }
706  export(Id);
707  list Lhilb = Philb,w;
708  setring(P); return(Lhilb);
709}
710example
711{ "EXAMPLE:"; echo = 2;
712   ring R = 0,(x,y,z,u,v),lp;
713   ideal i = x+y2+z3,xy+xv+yz+zu+uv,xyzuv-1;
714   intvec w = 6,3,2,1,1;
715   hilbRing(i,w);
716   def P = hilbRing(w,i)[1];
717   setring P;
718   Id[1];
719   hilb(std(Id[1]),1);
720
721   ring S =  0,(x,y,z,u,v),lp;
722   qring T = std(x+y2+z3);
723   ideal i = xy+xv+yz+zu+uv,xyzuv-v5;
724   module m = i*[0,1,1] + (xyzuv-v5)*[1,1,0];
725   def Q = hilbRing(m)[1];  Q;
726   setring Q;
727   print(Id[1]);
728}
729
730//////////////////////////////////////////////////////////////////////////////
731proc qslimgb (def i)
732"USAGE:   qslimgb(i); i ideal or module
733RETURN:  same type as input, a standard basis of i computed with slimgb
734NOTE:    Only as long as slimgb does not know qrings qslimgb should be used
735         in case the basering is (possibly) a quotient ring.
736         The quotient ideal is added to the input and slimgb is applied.
737EXAMPLE: example qslimgb; shows an example"
738{
739  def P = basering;
740  ideal Qideal = ideal(P);      //defining the quotient ideal if P is a qring
741  int p_opt;
742  if( find(option(),"prot") )
743  {
744    p_opt=1;
745  }
746  if (size(Qideal) == 0)
747  {
748    if (p_opt) { "slimgb in ring " + string(P); }
749    return(slimgb(i));
750  }
751
752  //case of a qring; since slimgb does not know qrings we
753  //delete the quotient ideal and add it to i
754
755  list BRlist = ring_list(P);
756  BRlist[4] = ideal(0);
757  def Phelp = ring(BRlist);
758  kill BRlist;
759  setring Phelp;
760  // module case:
761  def iq = imap(P,i);
762  if (typeof(iq)=="module")
763  {
764    iq = iq, imap(P,Qideal)*freemodule(nrows(iq));
765  }
766  else
767  {
768    iq = iq, imap(P,Qideal);
769  }
770  if (p_opt)
771  {
772    "slimgb in ring " + string(Phelp);
773    "(with quotient ideal added to input)";
774  }
775  iq = slimgb(iq);
776
777  setring P;
778  if (p_opt) { "//imap to original ring"; }
779  i = imap(Phelp,iq);
780  kill Phelp;
781
782  if (find(option(),"redSB") > 0)
783  {
784    if (p_opt) { "//interreduction"; }
785    i=reduce(i,std(0));
786    i=interred(i);
787  }
788  attrib(i, "isSB", 1);
789  return (i);
790}
791example
792{ "EXAMPLE:"; echo = 2;
793   ring R  = (0,v),(x,y,z,u),dp;
794   qring Q = std(x2-y3);
795   ideal i = x+y2,xy+yz+zu+u*v,xyzu*v-1;
796   ideal j = qslimgb(i); j;
797
798   module m = [x+y2,1,0], [1,1,x2+y2+xyz];
799   print(qslimgb(m));
800}
801
802//////////////////////////////////////////////////////////////////////////////
803proc groebner(def i_par, list #)
804"SYNTAX: @code{groebner (} ideal_expression @code{)} @*
805         @code{groebner (} module_expression @code{)} @*
806         @code{groebner (} ideal_expression@code{,} list of string_expressions
807               @code{)} @*
808         @code{groebner (} ideal_expression@code{,} list of string_expressions
809               and int_expression @code{)}
810TYPE:    type of the first argument
811PURPOSE: computes a standard basis of the first argument @code{I}
812         (ideal or module) by a heuristically chosen method (default)
813         or by a method specified by further arguments of type string.
814         Possible methods are:  @*
815         - the direct methods @code{\"std\"} or @code{\"slimgb\"} without
816           conversion, @*
817         - conversion methods @code{\"hilb\"} or @code{\"fglm\"} where
818           a Groebner basis is first computed with an \"easy\" ordering
819           and then converted to the ordering of the basering by the
820           Hilbert driven Groebner basis computation or by linear algebra.
821           The actual computation of the Groebner basis can be
822           specified by @code{\"std\"} or by @code{\"slimgb\"}
823           (not for all orderings implemented). @*
824         - @code{\"HC\"}: using the \"high corner\" from char p in char 0
825         A further string @code{\"par2var\"} converts parameters to an extra
826         block of variables before a Groebner basis computation (and
827         afterwards back).
828         @code{option(prot)} informs about the chosen method.
829HINT:    Since there exists no uniform best method for computing standard
830         bases, and since the difference in performance of a method on
831         different examples can be huge, it is recommended to test, for hard
832         examples, first various methods on a simplified example (e.g. use
833         characteristic 32003 instead of 0 or substitute a subset of
834         parameters/variables by integers, etc.). @*
835SEE ALSO: stdhilb, stdfglm, std, slimgb, modstd_lib, ffmodstd_lib, nfmodstd_lib
836KEYWORDS: groebner basis computations
837EXAMPLE: example groebner;  shows an example"
838
839{
840//Vorgabe einer Teilmenge aus {hilb,fglm,par2var,std,slimgb}
841//V1: Erste Einstellungen (Jan 2007)
842//V2: Aktuelle Aenderungen (Juni 2008)
843//---------------------------------
844//0. Immer Aufruf von std unabhaengig von der Vorgabe:
845//   gemischte Ordnungen, extra Gewichtsvektor, Matrix Ordnungen
846//   ### Todo: extra Gewichtsvektor sollte nicht immer mit std wirken,
847//   sondern z.B. mit "hilb" arbeiten koennen
848//   ### Todo: es sollte ein Gewichtsvektor mitgegeben werden koennen (oder
849//   berechnet werden), z.B. groebner(I,"hilb",w) oder groebner(I,"withWeights")
850//   wie bei elim in elim.lib
851
852//1. Keine Vorgabe: es wirkt die aktuelle Heuristk:
853//   - Char = p: std
854//V1 - Char = 0: slimgb (im qring wird Quotientenideal zum Input addiert)
855//V2 - Char = 0: std
856//   - 1-Block-Ordnungen/non-commutative: direkt Aufruf von std oder slimgb
857//   - Komplizierte Ordnungen (lp oder > 1 Block): hilb
858//V1 - Parameter werden grundsaetzlich nicht in Variable umgewandelt
859//V2 - Mehr als ein Parameter wird zu Variable konvertiert
860//   - fglm is keine Heuristik, da sonst vorher dim==0 peprueft werden muss
861
862//2. Vorgabe aus {std,slimgb}: es wird wo immer moeglich das Angegebene
863//   gewaehlt (da slimgb keine Hilbertfunktion kennt, wird std verwendet).
864//   Bei slimgb im qring, wird das Quotientenideal zum Ideal addiert.
865//   Bei Angabe von std zusammen mit slimgb (aequivalent zur Angabe von
866//   keinem von beidem) wirkt obige Heuristik.
867
868//3. Nichtleere Vorgabe aus {hilb,fglm,std,slimgb}:
869//   es wird nur das Angegebene und Moegliche sowie das Notwendige verwendet
870//   und bei Wahlmoeglickeit je nach Heuristik.
871//   Z.B. Vorgabe von {hilb} ist aequivalent zu {hilb,std,slimgb} und es wird
872//   hilb und nach Heuristik std oder slimgb verwendet,
873//   (V1: aber nicht par2var)
874//   bei Vorgabe von {hilb,slimgb} wird hilb und wo moeglich slimgb verwendet.
875
876//4. Bei Vorgabe von {par2var} wird par2var immer mit hilb und nach Heuristik
877//   std oder slimgb verwendet. Zu Variablen konvertierte Parameter haben
878//   extra letzten Block und Gewichte 1.
879
880  def P=basering;
881  if ((typeof(i_par)=="vector")||(typeof(i_par)=="module")||(typeof(i_par)=="matrix")) {module i=i_par;}
882  else {ideal i=i_par; } // int, poly, number, ideal
883  kill i_par;
884// check for integer etc coefficients
885  if (attrib(basering,"ring_cf")==1) // either integer or integer,q
886  {
887    if (find(option(),"prot"))  { "calling std for ideals in ring with ring coefficients"; }
888    return (std(i));
889  }
890
891//----------------------- save the given method ---------------------------
892  string method;                //all given methods as a coma separated string
893  int k;
894  for (k=1; k<=size(#); k++)
895  {
896     if (typeof(#[k]) == "string")
897     {
898       method = method + "," + #[k];
899     }
900  }
901// ------------------check for HC-- ---------------------------------------
902if (attrib(P,"global")==0)
903{
904  if ((method=="HC")&&(typeof(i)=="ideal"))
905  {
906    if (char(P)==0)
907    {
908      list L=ring_list(P);
909      L[1]=ZZ/32003;
910      ring S=ring(L);
911      ideal i=imap(P,i);
912      i=std(i);
913      if (vdim(i)!= -1)
914      {
915        poly HC=system(HC);
916        setring P;
917        noether=imap(S,HC);
918        return(std(i));
919      }
920    }
921  }
922}
923
924//--------------------- save data from basering ---------------------------
925  string @Minpoly = string(minpoly);      //minimal polynomial
926  int was_minpoly;             //remembers if there was a minpoly in P
927  if (size(minpoly) > 0)
928  {
929     was_minpoly = 1;
930  }
931
932  ideal Qideal = ideal(P);      //defining the quotient ideal if P is a qring
933  int was_qring;                //remembers if basering was a qring
934  //int is_homog = 1;
935  if (size(Qideal) > 0)
936  {
937     was_qring = 1;
938     //is_homog = homog(Qideal); //remembers if Qideal was homog (homog(0)=1)
939  }
940  list BRlist = ring_list(P);     //ringlist of basering
941
942  // save ordering of basering P for later use
943  list ord_P = BRlist[3];       //should be available in all rings
944  string ordstr_P = ordstr(P);
945  int nvars_P = nvars(P);
946  int npars_P = npars(P);
947  intvec w;                     //for ringweights of basering P
948  for(k=1;  k<=nvars_P; k++)
949  {
950     w[k]=deg(var(k));
951  }
952  int neg=1-attrib (P,"global");
953
954  //save options:
955  intvec opt=option(get);
956  string s_opt = option();
957  int p_opt;
958  if (find(s_opt, "prot"))  { p_opt = 1; }
959
960//------------------ cases where std is always used ------------------------
961//If other methods are not implemented or do not make sense, i.e. for
962//local or mixed orderings, matrix orderings, extra weight vector
963//### Todo: extra weight vector should be allowed for e.g. with "hilb"
964
965  if(  //( find(ordstr_P,"s") > 0 ) || // covered by neg
966       ( find(ordstr_P,"M") > 0 )  || ( find(ordstr_P,"a") > 0 )  || neg )
967  {
968    if (p_opt) { "std in basering"; }
969    return(std(i));
970  }
971
972//now we have:
973//ideal or module, global ordering, no matrix ordering, no extra weight vector
974//The interesting cases start now.
975
976 //------------------ classify the possible settings ---------------------
977  string algorithm;       //possibilities: std, slimgb, stdorslimgb, mathicgb
978  string conversion;      //possibilities: hilb, fglm, hilborfglm, no
979  string partovar;        //possibilities: yes, no
980  string order;           //possibilities: simple, !simple
981  string direct;          //possibilities: yes, no
982
983  //define algorithm:
984  if( (was_minpoly == 0) && (npars_P == 0) && (was_qring == 0) && (attrib (P,"global") == 1) && (char(P) > 0) && (size(BRlist)<=4) )
985  {
986    if( defined(Singmathic) )
987    {
988      algorithm = "mathicgb"; // make it default for any appropriate setting... if mathicgb is available...
989    } else
990    {
991      if( p_opt && find(method,"mathicgb")  ) { "Sorry Singmathic::mathicgb is not available!"; }
992    }
993  }
994  if( find(method,"std") && !find(method,"slimgb") )
995  {
996    algorithm = "std";
997  }
998  if( find(method,"slimgb") && !find(method,"std") )
999  {
1000    algorithm = "slimgb";
1001  }
1002  if( find(method,"std") && find(method,"slimgb") ||
1003      (!find(method,"std") && !find(method,"slimgb")) )
1004  {
1005    algorithm = "stdorslimgb";
1006  }
1007
1008  //define conversion:
1009  if( find(method,"hilb") && !find(method,"fglm") )
1010  {
1011     conversion = "hilb";
1012  }
1013  if( find(method,"fglm") && !find(method,"hilb") )
1014  {
1015    conversion = "fglm";
1016  }
1017  if( find(method,"fglm") && find(method,"hilb") )
1018  {
1019    conversion = "hilborfglm";
1020  }
1021  if( !find(method,"fglm") && !find(method,"hilb") )
1022  {
1023    conversion = "no";
1024  }
1025
1026  //define partovar:
1027  //if( find(method,"par2var") && npars_P > 0 )   //V1
1028  if( find(method,"par2var") || npars_P > 1 )     //V2
1029  {
1030     partovar = "yes";
1031  }
1032  else
1033  {
1034     partovar = "no";
1035  }
1036
1037  //define order:
1038  if (system("nblocks") <= 2)
1039  {
1040    if ( find(ordstr_P,"M")+find(ordstr_P,"lp")+find(ordstr_P,"rp") <= 0 )
1041    {
1042      order = "simple";
1043    }
1044  }
1045
1046  //define direct:
1047  if ( (order=="simple" && (size(method)==0)) ||
1048       (size(BRlist)>4) ||
1049        (order=="simple" && (method==",par2var" && npars_P==0 )) ||
1050         (conversion=="no" && partovar=="no" &&
1051           (algorithm=="std" || algorithm=="slimgb" || algorithm=="mathicgb" ||
1052            (find(method,"std") && find(method,"slimgb"))
1053           )
1054         )
1055     )
1056  {
1057    direct = "yes";
1058  }
1059  else
1060  {
1061    direct = "no";
1062  }
1063
1064  //order=="simple" means that the ordering of the variables consists of one
1065  //block which is not a matrix ordering and not a lexicographical ordering.
1066  //(Note:Singular counts always least 2 blocks, one is for module component):
1067  //Call a method "direct" if conversion=="no" && partovar="no" which means
1068  //that we apply std or slimgb direct in the basering (exception
1069  //as long as slimgb does not know qrings: in a qring of a ring P
1070  //the ideal Qideal is added to the ideal and slimgb is applied in P).
1071  //We apply a direct method if we have a simple monomial ordering, if no
1072  //conversion (fglm or hilb) is specified and if the parameters shall
1073  //not be made to variables
1074  //BRlist (=ringlist of basering) > 4 if the basering is non-commutative
1075//---------------------------- direct methods -----------------------------
1076  if ( algorithm=="mathicgb" )
1077  {
1078    if (p_opt) { algorithm + " in " + string(P); }
1079    return( mathicgb(i) );
1080  }
1081  if ( direct == "yes" )
1082  {
1083  //if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) )   //V1
1084    if ( algorithm=="std" || (algorithm=="stdorslimgb") )                //V2
1085    {
1086      if (p_opt) { "std in " + string(P); }
1087      return(std(i));
1088    }
1089  //if( algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0)) //V1
1090    if ( algorithm=="slimgb" )                                           //V2
1091    {
1092      return(qslimgb(i));
1093    }
1094  }
1095
1096//--------------------------- indirect methods -----------------------------
1097//indirect methods are methods where a conversion is used with a ring change
1098//We are in the following situation:
1099//direct=="no" (i.e. "hilb" or "fglm" or "par2var" is given)
1100//or no method is given and we have a complicated monomial ordering
1101//V1: "par2var" is not a default strategy, it must be explicitly
1102//given in order to be performed.
1103//V2: "par2var" is a default strategy if there are more than 1 parameters
1104
1105//------------ case where no parameters are made to variables  -------------
1106  if (  partovar == "no" && conversion == "hilb"
1107    || (partovar == "no" && conversion == "fglm" )
1108    || (partovar == "no" && conversion == "hilborfglm" )
1109    || (partovar == "no" && conversion == "no" && direct == "no") )
1110  //last case: heuristic
1111  {
1112    if ( conversion=="fglm" )
1113    {
1114    //if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) ) //V1
1115      if ( algorithm=="std" || (algorithm=="stdorslimgb") )              //V2
1116      {
1117        return (stdfglm(i,"std"));
1118      }
1119    //if(algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0))//V1
1120      if( algorithm=="slimgb" )                                          //V2
1121      {
1122        return (stdfglm(i,"slimgb"));
1123      }
1124    }
1125    else
1126    {
1127    //if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) )//V1
1128      if ( algorithm=="std" || (algorithm=="stdorslimgb" ) )            //V2
1129      {
1130        return (stdhilb(i,"std"));
1131      }
1132    //if(algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0))//V1
1133      if ( algorithm=="slimgb" )                                         //V2
1134      {
1135        return (stdhilb(i,"slimgb"));
1136      }
1137    }
1138  }
1139
1140//------------ case where parameters are made to variables  ----------------
1141//define a ring Phelp via par2varRing in which the parameters are variables
1142
1143  else
1144  {
1145    // reset options
1146    option(none);
1147    // turn on options prot, mem, redSB, intStrategy if previously set
1148    if ( find(s_opt, "prot") )
1149      { option(prot); }
1150    if ( find(s_opt, "mem") )
1151      { option(mem); }
1152    if ( find(s_opt, "redSB") )
1153      { option(redSB); }
1154    if ( find(s_opt, "intStrategy") )
1155      { option(intStrategy); }
1156
1157    //first clear denominators of parameters
1158    if (npars_P > 0)
1159    {
1160      for( k=ncols(i); k>0; k-- )
1161      { i[k]=cleardenom(i[k]); }
1162    }
1163
1164    def Phelp = par2varRing(i)[1];   //minpoly is mapped with i
1165    setring Phelp;
1166    def i = Id[1];
1167    //is_homog = homog(i);
1168
1169    //If parameters are converted to ring variables, they appear in an extra
1170    //block. Therefore we use always hilb for this block ordering:
1171    if ( conversion=="fglm" )
1172    {
1173      i = (stdfglm(i));       //only uesful for 1 parameter with minpoly
1174    }
1175    else
1176    {
1177    //if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) )//V1
1178      if ( algorithm=="std" || (algorithm=="stdorslimgb" ))             //V2
1179      {
1180        i = stdhilb(i,"std");
1181      }
1182    //if(algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0))//V1
1183      if ( algorithm=="slimgb" )                                         //V2
1184      {
1185        i = stdhilb(i,"slimgb");
1186      }
1187    }
1188  }
1189
1190//-------------------- go back to original ring ---------------------------
1191//The main computation is done. However, the SB coming from a ring with
1192//extra variables is in general too big. We simplify it before mapping it
1193//to the basering.
1194
1195  if (p_opt) { "//simplification"; }
1196
1197  if (was_minpoly)
1198  {
1199    execute("ideal Minpoly = " + @Minpoly + ";");
1200    attrib(Minpoly,"isSB",1);
1201    i = simplify(NF(i,Minpoly),2);
1202  }
1203
1204  def Li = lead(i);
1205  setring P;
1206  def Li = imap(Phelp,Li);
1207  Li = simplify(Li,32);
1208  intvec vi;
1209  for (k=1; k<=ncols(Li); k++)
1210  {
1211    vi[k] = Li[k]==0;
1212  }
1213
1214  setring Phelp;
1215  for (k=1;  k<=size(i) ;k++)
1216  {
1217    if(vi[k]==1)
1218    {
1219      i[k]=0;
1220    }
1221  }
1222  i = simplify(i,2);
1223
1224  setring P;
1225  if (p_opt) { "//imap to original ring"; }
1226  i = imap(Phelp,i);
1227  kill Phelp;
1228  i = simplify(i,34);
1229
1230  // clean-up time
1231  option(set, opt);
1232  if (find(s_opt, "redSB") > 0)
1233  {
1234    if (p_opt) { "//interreduction"; }
1235    i=interred(i);
1236  }
1237  attrib(i, "isSB", 1);
1238  return (i);
1239}
1240example
1241{ "EXAMPLE: "; echo=2;
1242  intvec opt = option(get);
1243  option(prot);
1244  ring r  = 0,(a,b,c,d),dp;
1245  ideal i = a+b+c+d,ab+ad+bc+cd,abc+abd+acd+bcd,abcd-1;
1246  groebner(i);
1247
1248  ring s  = 0,(a,b,c,d),lp;
1249  ideal i = imap(r,i);
1250  groebner(i,"hilb");
1251
1252  ring R  = (0,a),(b,c,d),lp;
1253  minpoly = a2+1;
1254  ideal i = a+b+c+d,ab+ad+bc+cd,abc+abd+acd+bcd,d2-c2b2;
1255  groebner(i,"par2var","slimgb");
1256
1257  groebner(i,"fglm");          //computes a reduced standard basis
1258
1259  option(set,opt);
1260}
1261
1262//////////////////////////////////////////////////////////////////////////
1263
1264proc res(list #)
1265"@c we do texinfo here:
1266@cindex resolution, computation of
1267@table @code
1268@item @strong{Syntax:}
1269@code{res (} ideal_expression@code{,} int_expression @code{[,} any_expression @code{])}
1270@*@code{res (} module_expression@code{,} int_expression @code{[,} any_expression @code{])}
1271@item @strong{Type:}
1272resolution
1273@item @strong{Purpose:}
1274computes a (possibly minimal) free resolution of an ideal or module using
1275a heuristically chosen method.
1276@* The second (int) argument (say @code{k}) specifies the length of
1277the resolution. If it is not positive then @code{k} is assumed to be the
1278number of variables of the basering.
1279@* If a third argument is given, the returned resolution is minimized.
1280
1281Depending on the input, the returned resolution is computed using the
1282following methods:
1283@table @asis
1284@item @strong{quotient rings:}
1285@code{nres} (classical method using syzygies) , see @ref{nres}.
1286
1287@item @strong{homogeneous ideals and k=0:}
1288@code{lres} (La'Scala's method), see @ref{lres}.
1289
1290@item @strong{not minimized resolution and (homogeneous input with k not 0, or local rings):}
1291@code{sres} (Schreyer's method), see @ref{sres}.
1292
1293@item @strong{all other inputs:}
1294@code{mres} (classical method), see @ref{mres}.
1295@end table
1296@item @strong{Note:}
1297Accessing single elements of a resolution may require some partial
1298computations to be finished and may therefore take some time.
1299@end table
1300@c ref
1301See also
1302@ref{betti};
1303@ref{ideal};
1304@ref{minres};
1305@ref{module};
1306@ref{mres};
1307@ref{nres};
1308@ref{lres};
1309@ref{hres};
1310@ref{sres};
1311@ref{fres};
1312@ref{resolution}.
1313@c ref
1314"
1315{
1316   def P=basering;
1317   if (size(#) < 2)
1318   {
1319     ERROR("res: need at least two arguments: ideal/module, int");
1320   }
1321
1322   def m=#[1]; //the ideal or module
1323   int i=#[2]; //the length of the resolution
1324   if (i< 0) { i=0;}
1325
1326   string varstr_P = varstr(P);
1327
1328   int p_opt;
1329   string s_opt = option();
1330   // set p_opt, if option(prot) is set
1331   if (find(s_opt, "prot"))
1332   {
1333     p_opt = 1;
1334   }
1335
1336   if( (size(ideal(basering)) > 0) || (size(ring_list(P)) > 4) )
1337   {
1338     // the quick hack for qrings - seems to fit most needs
1339     // (lres is not implemented for qrings, sres is not so efficient)
1340     // || non-commutative, since only n/m-res are implemented for NC rings
1341     if (p_opt) { "using nres";}
1342     return(nres(m,i));
1343   }
1344
1345   if(homog(m)==1)
1346   {
1347      resolution re;
1348      if (((i==0) or (i>=nvars(basering))) && (typeof(m) != "module") && (nvars(basering)>1))
1349      {
1350        //LaScala for the homogeneous case and i == 0
1351        if (p_opt) { "using lres";}
1352        re=lres(m,i);
1353        if(size(#)>2)
1354        {
1355           re=minres(re);
1356        }
1357      }
1358      else
1359      {
1360        if(size(#)>2)
1361        {
1362          if (p_opt) { "using mres";}
1363          re=mres(m,i);
1364        }
1365        else
1366        {
1367          if (p_opt) { "using sres";}
1368          re=sres(std(m),i);
1369        }
1370      }
1371      return(re);
1372   }
1373
1374   //mres for the global non homogeneous case
1375   if(find(ordstr(P),"s")==0)
1376   {
1377      ring Phelp = create_ring("+string(char(P))+", "("+varstr_P+")", "(dp,C)", "+string(minpoly)+");
1378      def m=imap(P,m);
1379      if (p_opt) { "using mres in another ring";}
1380      list re=mres(m,i);
1381      setring P;
1382      resolution result=imap(Phelp,re);
1383      if (size(#) > 2) {result = minres(result);}
1384      return(result);
1385   }
1386
1387   //sres for the local case and not minimal resolution
1388   if(size(#)<=2)
1389   {
1390      ring Phelp = create_ring("+string(char(P))+", "("+varstr_P+")", "(ls,c)", "+string(minpoly)+");
1391      def m=imap(P,m);
1392      m=std(m);
1393      if (p_opt) { "using sres in another ring";}
1394      list re=sres(m,i);
1395      setring P;
1396      resolution result=imap(Phelp,re);
1397      return(result);
1398   }
1399
1400   //mres for the local case and minimal resolution
1401   ring Phelp = create_ring("+string(char(P))+", "("+varstr_P+")", "(ls,C)", "+string(minpoly)+");
1402   def m=imap(P,m);
1403    if (p_opt) { "using mres in another ring";}
1404   list re=mres(m,i);
1405   setring P;
1406   resolution result=imap(Phelp,re);
1407   result = minres(result);
1408   return(result);
1409}
1410example
1411{"EXAMPLE:"; echo = 2;
1412  ring r=0,(x,y,z),dp;
1413  ideal i=xz,yz,x3-y3;
1414  def l=res(i,0); // homogeneous ideal: uses lres
1415  l;
1416  print(betti(l), "betti"); // input to betti may be of type resolution
1417  l[2];         // element access may take some time
1418  i=i,x+1;
1419  l=res(i,0);   // inhomogeneous ideal: uses mres
1420  l;
1421  ring rs=0,(x,y,z),ds;
1422  ideal i=imap(r,i);
1423  def l=res(i,0); // local ring not minimized: uses sres
1424  l;
1425  res(i,0,0);     // local ring and minimized: uses mres
1426}
1427/////////////////////////////////////////////////////////////////////////
1428
1429proc quot (def m1,def m2,list #)
1430"SYNTAX: @code{quot (} module_expression@code{,} module_expression @code{)}
1431         @*@code{quot (} module_expression@code{,} module_expression@code{,}
1432            int_expression @code{)}
1433         @*@code{quot (} ideal_expression@code{,} ideal_expression @code{)}
1434         @*@code{quot (} ideal_expression@code{,} ideal_expression@code{,}
1435            int_expression @code{)}
1436TYPE:    ideal
1437SYNTAX:  @code{quot (} module_expression@code{,} ideal_expression @code{)}
1438TYPE:    module
1439PURPOSE: computes the quotient of the 1st and the 2nd argument.
1440         If a 3rd argument @code{n} is given the @code{n}-th method is used
1441         (@code{n}=1...5).
1442SEE ALSO: quotient
1443EXAMPLE: example quot; shows an example"
1444{
1445  if (((typeof(m1)!="ideal") and (typeof(m1)!="module"))
1446     or ((typeof(m2)!="ideal") and (typeof(m2)!="module")))
1447  {
1448    "USAGE:   quot(m1, m2[, n]); m1, m2 two submodules of k^s,";
1449    "         n (optional) integer (1<= n <=5)";
1450    "RETURN:  the quotient of m1 and m2";
1451    "EXAMPLE: example quot; shows an example";
1452    return();
1453  }
1454  if (typeof(m1)!=typeof(m2))
1455  {
1456    return(quotient(m1,m2));
1457  }
1458  if (size(#)>0)
1459  {
1460    if (typeof(#[1])=="int" )
1461    {
1462      return(quot1(m1,m2,#[1]));
1463    }
1464  }
1465  else
1466  {
1467    return(quot1(m1,m2,2));
1468  }
1469}
1470example
1471{ "EXAMPLE:"; echo = 2;
1472  ring r=181,(x,y,z),(c,ls);
1473  ideal id1=maxideal(4);
1474  ideal id2=x2+xyz,y2-z3y,z3+y5xz;
1475  option(prot);
1476  ideal id3=quotient(id1,id2);
1477  id3;
1478  ideal id4=quot(id1,id2,1);
1479  id4;
1480  ideal id5=quot(id1,id2,2);
1481  id5;
1482}
1483
1484static proc quot1 (module m1, module m2,int n)
1485"USAGE:   quot1(m1, m2, n); m1, m2 two submodules of k^s,
1486         n integer (1<= n <=5)
1487RETURN:  the quotient of m1 and m2
1488EXAMPLE: example quot1; shows an example"
1489{
1490  if (n==1)
1491  {
1492    return(quotient1(m1,m2));
1493  }
1494  else
1495  {
1496    if (n==2)
1497    {
1498      return(quotient2(m1,m2));
1499    }
1500    else
1501    {
1502      if (n==3)
1503      {
1504        return(quotient3(m1,m2));
1505      }
1506      else
1507      {
1508        if (n==4)
1509        {
1510          return(quotient4(m1,m2));
1511        }
1512        else
1513        {
1514          if (n==5)
1515          {
1516            return(quotient5(m1,m2));
1517          }
1518          else
1519          {
1520            return(quotient(m1,m2));
1521          }
1522        }
1523      }
1524    }
1525  }
1526}
1527example
1528{ "EXAMPLE:"; echo = 2;
1529  ring r=181,(x,y,z),(c,ls);
1530  ideal id1=maxideal(4);
1531  ideal id2=x2+xyz,y2-z3y,z3+y5xz;
1532  option(prot);
1533  ideal id6=quotient(id1,id2);
1534  id6;
1535  ideal id7=quot1(id1,id2,1);
1536  id7;
1537  ideal id8=quot1(id1,id2,2);
1538  id8;
1539}
1540
1541static proc quotient0(module a,module b)
1542{
1543  module mm=b+a;
1544  resolution rs=lres(mm,0);
1545  list I=list(rs);
1546  matrix M=I[2];
1547  matrix A[1][nrows(M)]=M[1..nrows(M),1];
1548  ideal i=A;
1549  return (i);
1550}
1551proc quotient1(module a,module b)  //17sec
1552"USAGE:   quotient1(m1, m2); m1, m2 two submodules of k^s,
1553RETURN:  the quotient of m1 and m2"
1554{
1555  int i;
1556  a=std(a);
1557  module dummy;
1558  module B=NF(b,a)+dummy;
1559  ideal re=quotient(a,module(B[1]));
1560  for(i=2;i<=ncols(B);i++)
1561  {
1562     re=intersect1(re,quotient(a,module(B[i])));
1563  }
1564  return(re);
1565}
1566proc quotient2(module a,module b)    //13sec
1567"USAGE:   quotient2(m1, m2); m1, m2 two submodules of k^s,
1568RETURN:  the quotient of m1 and m2"
1569{
1570  a=std(a);
1571  module dummy;
1572  module bb=NF(b,a)+dummy;
1573  int i=ncols(bb);
1574  ideal re=quotient(a,module(bb[i]));
1575  bb[i]=0;
1576  module temp;
1577  module temp1;
1578  module bbb;
1579  int mx;
1580  i=i-1;
1581  while (1)
1582  {
1583    if (i==0) break;
1584    temp = a+bb*re;
1585    temp1 = lead(interred(temp));
1586    mx=ncols(a);
1587    if (ncols(temp1)>ncols(a))
1588    {
1589      mx=ncols(temp1);
1590    }
1591    temp1 = matrix(temp1,1,mx)-matrix(lead(a),1,mx);
1592    temp1 = dummy+temp1;
1593    if (deg(temp1[1])<0) break;
1594    re=intersect1(re,quotient(a,module(bb[i])));
1595    bb[i]=0;
1596    i = i-1;
1597  }
1598  return(re);
1599}
1600proc quotient3(module a,module b)   //89sec
1601"USAGE:   quotient3(m1, m2); m1, m2 two submodules of k^s,
1602         only for global rings
1603RETURN:  the quotient of m1 and m2"
1604{
1605  def @newP=basering;
1606  ring @newr = create_ring(ring_list(basering)[1], "("+varstr(basering)+", @t, @w)", "dp", "no_minpoly");
1607  module b=imap(@newP,b);
1608  module a=imap(@newP,a);
1609  int i;
1610  int j=ncols(b);
1611  vector @b;
1612  for(i=1;i<=j;i++)
1613  {
1614     @b=@b+@t^(i-1)*@w^(j-i+1)*b[i];
1615  }
1616  ideal re=quotient(a,module(@b));
1617  setring @newP;
1618  ideal re=imap(@newr,re);
1619  return(re);
1620}
1621proc quotient5(module a,module b)   //89sec
1622"USAGE:   quotient5(m1, m2); m1, m2 two submodules of k^s,
1623         only for global rings
1624RETURN:  the quotient of m1 and m2"
1625{
1626  def @newP=basering;
1627  ring @newr = create_ring(ring_list(basering)[1], "("+varstr(basering)+", @t)", "dp", "no_minpoly");
1628  module b=imap(@newP,b);
1629  module a=imap(@newP,a);
1630  int i;
1631  int j=ncols(b);
1632  vector @b;
1633  for(i=1;i<=j;i++)
1634  {
1635     @b=@b+@t^(i-1)*b[i];
1636  }
1637  @b=homog(@b,@w);
1638  ideal re=quotient(a,module(@b));
1639  setring @newP;
1640  ideal re=imap(@newr,re);
1641  return(re);
1642}
1643proc quotient4(module a,module b)   //95sec
1644"USAGE:   quotient4(m1, m2); m1, m2 two submodules of k^s,
1645         only for global rings
1646RETURN:  the quotient of m1 and m2"
1647{
1648  def @newP=basering;
1649  ring @newr = create_ring(ring_list(basering)[1], "("+varstr(basering)+", @t)", "dp", "no_minpoly");
1650  module b=imap(@newP,b);
1651  module a=imap(@newP,a);
1652  int i;
1653  vector @b=b[1];
1654  for(i=2;i<=ncols(b);i++)
1655  {
1656     @b=@b+@t^(i-1)*b[i];
1657  }
1658  matrix sy=modulo(@b,a);
1659  ideal re=sy;
1660  setring @newP;
1661  ideal re=imap(@newr,re);
1662  return(re);
1663}
1664static proc intersect1(ideal i,ideal j)
1665{
1666  def R=basering;
1667  ring gnir = create_ring(ring_list(basering)[1], "("+varstr(basering)+",@t)", "(C,dp)", "no_minpoly");
1668  ideal i=var(nvars(basering))*imap(R,i)+(var(nvars(basering))-1)*imap(R,j);
1669  ideal j=eliminate(i,var(nvars(basering)));
1670  setring R;
1671  map phi=gnir,maxideal(1);
1672  return(phi(j));
1673}
1674
1675//////////////////////////////////////////////////////////////////
1676///
1677/// sprintf, fprintf printf
1678///
1679proc sprintf(string fmt, list #)
1680"SYNTAX:  @code{sprintf (} string_expression @code{[,} any_expressions
1681               @code{] )}
1682RETURN:   string
1683PURPOSE:  @code{sprintf(fmt,...);} performs output formatting. The first
1684          argument is a format control string. Additional arguments may be
1685          required, depending on the content of the control string. A series
1686          of output characters is generated as directed by the control string;
1687          these characters are returned as a string. @*
1688          The control string @code{fmt} is simply text to be copied,
1689          except that the string may contain conversion specifications.@*
1690          Type @code{help print;} for a listing of valid conversion
1691          specifications. As an addition to the conversions of @code{print},
1692          the @code{%n} and @code{%2} conversion specification does not
1693          consume an additional argument, but simply generates a newline
1694          character.
1695NOTE:     If one of the additional arguments is a list, then it should be
1696          wrapped in an additional @code{list()} command, since passing a list
1697          as an argument flattens the list by one level.
1698SEE ALSO: fprintf, printf, print, string
1699EXAMPLE : example sprintf; shows an example
1700"
1701{
1702  int sfmt = size(fmt);
1703  if (sfmt  <= 1)
1704  {
1705    return (fmt);
1706  }
1707  int next, l, nnext;
1708  string ret;
1709  list formats = "%l", "%s", "%2l", "%2s", "%t", "%;", "%p", "%b", "%n", "%2";
1710  while (1)
1711  {
1712    if (size(#) <= 0)
1713    {
1714      return (ret + fmt);
1715    }
1716    nnext = 0;
1717    while (nnext < sfmt)
1718    {
1719      nnext = find(fmt, "%", nnext + 1);
1720      if (nnext == 0)
1721      {
1722        next = 0;
1723        break;
1724      }
1725      l = 1;
1726      while (l <= size(formats))
1727      {
1728        next = find(fmt, formats[l], nnext);
1729        if (next == nnext) break;
1730        l++;
1731      }
1732      if (next == nnext) break;
1733    }
1734    if (next == 0)
1735    {
1736      return (ret + fmt);
1737    }
1738    if (formats[l] != "%2" && formats[l] != "%n")
1739    {
1740      ret = ret + fmt[1, next - 1] + print(#[1], formats[l]);
1741      # = delete(#, 1);
1742    }
1743    else
1744    {
1745      ret = ret + fmt[1, next - 1] + print("", "%2s");
1746    }
1747    if (size(fmt) <= (next + size(formats[l]) - 1))
1748    {
1749      return (ret);
1750    }
1751    fmt = fmt[next + size(formats[l]), size(fmt)-next-size(formats[l]) + 1];
1752  }
1753}
1754example
1755{ "EXAMPLE:"; echo=2;
1756  ring r=0,(x,y,z),dp;
1757  module m=[1,y],[0,x+z];
1758  intmat M=betti(mres(m,0));
1759  list l = r, m, M;
1760  string s = sprintf("s:%s,%n l:%l", 1, 2); s;
1761  s = sprintf("s:%n%s", l); s;
1762  s = sprintf("s:%2%s", list(l)); s;
1763  s = sprintf("2l:%n%2l", list(l)); s;
1764  s = sprintf("%p", list(l)); s;
1765  s = sprintf("%;", list(l)); s;
1766  s = sprintf("%b", M); s;
1767}
1768
1769proc printf(string fmt, list #)
1770"SYNTAX:  @code{printf (} string_expression @code{[,} any_expressions@code{] )}
1771RETURN:   none
1772PURPOSE:  @code{printf(fmt,...);} performs output formatting. The first
1773          argument is a format control string. Additional arguments may be
1774          required, depending on the content of the control string. A series
1775          of output characters is generated as directed by the control string;
1776          these characters are displayed (i.e., printed to standard out). @*
1777          The control string @code{fmt} is simply text to be copied, except
1778          that the string may contain conversion specifications. @*
1779          Type @code{help print;} for a listing of valid conversion
1780          specifications. As an addition to the conversions of @code{print},
1781          the @code{%n} and @code{%2} conversion specification does not
1782          consume an additional argument, but simply generates a newline
1783          character.
1784NOTE:     If one of the additional arguments is a list, then it should be
1785          enclosed once more into a @code{list()} command, since passing a
1786          list as an argument flattens the list by one level.
1787SEE ALSO: sprintf, fprintf, print, string
1788EXAMPLE : example printf; shows an example
1789"
1790{
1791  write("", sprintf(fmt, #));
1792}
1793example
1794{ "EXAMPLE:"; echo=2;
1795  ring r=0,(x,y,z),dp;
1796  module m=[1,y],[0,x+z];
1797  intmat M=betti(mres(m,0));
1798  list l=r,m,matrix(M);
1799  printf("s:%s,l:%l",1,2);
1800  printf("s:%s",l);
1801  printf("s:%s",list(l));
1802  printf("2l:%2l",list(l));
1803  printf("%p",matrix(M));
1804  printf("%;",matrix(M));
1805  printf("%b",M);
1806}
1807
1808
1809proc fprintf(link l, string fmt, list #)
1810"SYNTAX:  @code{fprintf (} link_expression@code{,} string_expression @code{[,}
1811                any_expressions@code{] )}
1812RETURN:   none
1813PURPOSE:  @code{fprintf(l,fmt,...);} performs output formatting.
1814          The second argument is a format control string. Additional
1815          arguments may be required, depending on the content of the
1816          control string. A series of output characters is generated as
1817          directed by the control string; these characters are
1818          written to the link l.
1819          The control string @code{fmt} is simply text to be copied, except
1820          that the string may contain conversion specifications.@*
1821          Type @code{help print;} for a listing of valid conversion
1822          specifications. As an addition to the conversions of @code{print},
1823          the @code{%n} and @code{%2} conversion specification does not
1824          consume an additional argument, but simply generates a newline
1825          character.
1826NOTE:     If one of the additional arguments is a list, then it should be
1827          enclosed once more into a @code{list()} command, since passing
1828          a list as an argument flattens the list by one level.
1829SEE ALSO: sprintf, printf, print, string
1830EXAMPLE : example fprintf; shows an example
1831"
1832{
1833  write(l, sprintf(fmt, #));
1834}
1835example
1836{ "EXAMPLE:"; echo=2;
1837  ring r=0,(x,y,z),dp;
1838  module m=[1,y],[0,x+z];
1839  intmat M=betti(mres(m,0));
1840  list l=r,m,M;
1841  link li="";   // link to stdout
1842  fprintf(li,"s:%s,l:%l",1,2);
1843  fprintf(li,"s:%s",l);
1844  fprintf(li,"s:%s",list(l));
1845  fprintf(li,"2l:%2l",list(l));
1846  fprintf(li,"%p",list(l));
1847  fprintf(li,"%;",list(l));
1848  fprintf(li,"%b",M);
1849}
1850
1851//////////////////////////////////////////////////////////////////////////
1852
1853/*
1854proc minres(list #)
1855{
1856  if (size(#) == 2)
1857  {
1858    if (typeof(#[1]) == "ideal" || typeof(#[1]) == "module")
1859    {
1860      if (typeof(#[2] == "int"))
1861      {
1862        return (res(#[1],#[2],1));
1863      }
1864    }
1865  }
1866
1867  if (typeof(#[1]) == "resolution")
1868  {
1869    return minimizeres(#[1]);
1870  }
1871  else
1872  {
1873    return minimizeres(#);
1874  }
1875
1876}
1877*/
1878///////////////////////////////////////////////////////////////////////////////
1879
1880proc weightKB(def stc, int dd, list wim)
1881"SYNTAX: @code{weightKB (} module_expression@code{,} int_expression @code{,}
1882            list_expression @code{)}@*
1883         @code{weightKB (} ideal_expression@code{,} int_expression@code{,}
1884            list_expression @code{)}
1885RETURN:  the same as the input type of the first argument
1886PURPOSE: If @code{I,d,wim} denotes the three arguments then weightKB
1887         computes the weighted degree- @code{d} part of a vector space basis
1888         (consisting of monomials) of the quotient ring, resp. of the
1889         quotient module, modulo @code{I} w.r.t. weights given by @code{wim}
1890         The information about the weights is given as a list of two intvec:
1891            @code{wim[1]} weights for all variables (positive),
1892            @code{wim[2]} weights for the module generators.
1893NOTE:    This is a generalization of the command @code{kbase} with the same
1894         first two arguments.
1895SEE ALSO: kbase
1896EXAMPLE: example weightKB; shows an example
1897"
1898{
1899  if(checkww(wim)){ERROR("wrong weights");}
1900  kbclass();
1901  wwtop=wim[1];
1902  stc=interred(lead(stc));
1903  if(typeof(stc)=="ideal")
1904  {
1905    stdtop=stc;
1906    ideal out=widkbase(dd);
1907    delkbclass();
1908    out=simplify(out,2); // delete 0
1909    return(out);
1910  }
1911  list mbase=kbprepare(stc);
1912  module mout;
1913  int im,ii;
1914  if(size(wim)>1){mmtop=wim[2];}
1915  else{mmtop=0;}
1916  for(im=size(mbase);im>0;im--)
1917  {
1918    stdtop=mbase[im];
1919    if(im>size(mmtop)){ii=dd;}
1920    else{ii=dd-mmtop[im];}
1921    mout=mout+widkbase(ii)*gen(im);
1922  }
1923  delkbclass();
1924  mout=simplify(mout,2); // delete 0
1925  return(mout);
1926}
1927example
1928{ "EXAMPLE:"; echo=2;
1929  ring R=0, (x,y), wp(1,2);
1930  weightKB(ideal(0),3,intvec(1,2));
1931}
1932
1933///////////////////////////////////////////////////////////////////////////////
1934
1935proc datetime()
1936"SYNTAX: @code{datetime ()}
1937RETURN:  string
1938PURPOSE: return the current date and time as a string
1939EXAMPLE: example datetime; shows an example
1940"
1941{
1942  return(read("|: date"));
1943}
1944example
1945{ "EXAMPLE:"; echo=2;
1946  datetime();
1947}
1948
1949///////////////////////////////////////////////////////////////////////////////
1950// construct global values
1951static proc kbclass()
1952{
1953  intvec wwtop,mmtop;
1954  export (wwtop,mmtop);
1955  ideal stdtop,kbtop;
1956  export (stdtop,kbtop);
1957}
1958// delete global values
1959static proc delkbclass()
1960{
1961  kill wwtop,mmtop;
1962  kill stdtop,kbtop;
1963}
1964//  select parts of the modul
1965static proc kbprepare(module mstc)
1966{
1967  list rr;
1968  ideal kk;
1969  int i1,i2;
1970  mstc=transpose(mstc);
1971  for(i1=ncols(mstc);i1>0;i1--)
1972  {
1973    kk=0;
1974    for(i2=nrows(mstc[i1]);i2>0;i2--)
1975    {
1976      kk=kk+mstc[i1][i2];
1977    }
1978    rr[i1]=kk;
1979  }
1980  return(rr);
1981}
1982//  check for weights
1983static proc checkww(list vv)
1984{
1985  if(typeof(vv[1])!="intvec"){return(1);}
1986  intvec ww=vv[1];
1987  int mv=nvars(basering);
1988  if(size(ww)<mv){return(1);}
1989  while(mv>0)
1990  {
1991    if(ww[mv]<=0){return(1);}
1992    mv--;
1993  }
1994  if(size(vv)>1)
1995  {
1996    if(typeof(vv[2])!="intvec"){return(1);}
1997  }
1998  return(0);
1999}
2000///////////////////////////////////////////////////////
2001// The "Caller" for ideals
2002//    dd   - the degree of the result
2003static proc widkbase(int dd)
2004{
2005  if((size(stdtop)==1)&&(deg(stdtop[1])==0)){return(0);}
2006  if(dd<=0)
2007  {
2008    if(dd<0){return(0);}
2009    else{return(1);}
2010  }
2011  int m1,m2;
2012  m1=nvars(basering);
2013  while(wwtop[m1]>dd)
2014  {
2015    m1--;
2016    if(m1==0){return(0);}
2017  }
2018  attrib(stdtop,"isSB",1);
2019  poly mo=1;
2020  if(m1==1)
2021  {
2022    m2=dd div wwtop[1];
2023    if((m2*wwtop[1])==dd)
2024    {
2025      mo=var(1)^m2;
2026      if(reduce(mo,stdtop)==mo){return(mo);}
2027      else{return(0);}
2028    }
2029  }
2030  kbtop=0;
2031  m2=dd;
2032  weightmon(m1-1,m2,mo);
2033  while(m2>=wwtop[m1])
2034  {
2035    m2=m2-wwtop[m1];
2036    mo=var(m1)*mo;
2037    if(m2==0)
2038    {
2039      if((mo!=0) and (reduce(mo,stdtop)==mo))
2040      {
2041        kbtop[ncols(kbtop)+1]=mo;
2042        return(kbtop);
2043      }
2044    }
2045    weightmon(m1-1,m2,mo);
2046  }
2047  return(kbtop);
2048}
2049/////////////////////////////////////////////////////////
2050// the recursive procedure
2051//    va     - number of the variable
2052//    drest  - rest of the degree
2053//    mm     - the candidate
2054static proc weightmon(int va, int drest, poly mm)
2055{
2056  if(va==0){return();}
2057  while(wwtop[va]>drest)
2058  {
2059    va--;
2060    if(va==0){return();}
2061  }
2062  int m2;
2063  if(va==1)
2064  {
2065    m2=drest div wwtop[1];
2066    if((m2*wwtop[1])==drest)
2067    {
2068      mm=var(1)^m2*mm;
2069      if ((mm!=0) and (reduce(mm,stdtop)==mm))
2070      {
2071        kbtop[ncols(kbtop)+1]=mm;
2072      }
2073    }
2074    return();
2075  }
2076  m2=drest;
2077  if ((mm!=0) and (reduce(mm,stdtop)==mm))
2078  {
2079    weightmon(va-1,m2,mm);
2080  }
2081  while(m2>=wwtop[va])
2082  {
2083    m2=m2-wwtop[va];
2084    mm=var(va)*mm;
2085    if(m2==0)
2086    {
2087      if ((mm!=0) and (reduce(mm,stdtop)==mm))
2088      {
2089        kbtop[ncols(kbtop)+1]=mm;
2090        return();
2091      }
2092    }
2093     if ((mm!=0) and (reduce(mm,stdtop)==mm))
2094     {
2095       weightmon(va-1,m2,mm);
2096     }
2097  }
2098  return();
2099}
2100example
2101{ "EXAMPLE:"; echo=2;
2102  ring r=0,(x,y,z),dp;
2103  ideal i = x6,y4,xyz;
2104  intvec w = 2,3,6;
2105  weightKB(i, 12, list(w));
2106}
2107
2108///////////////////////////////////////////////////////////////////////////////
2109proc max(def i,list #)
2110"SYNTAX: max (i_1, ..., i_k)
2111TYPE:    same as type of i_1, ..., i_k resp.
2112PURPOSE: returns the maximum for any arguments of a type
2113         for which '>' is defined
2114SEE ALSO: min
2115EXAMPLE: example max; shows an example"
2116{
2117  def maximum = i;
2118  for (int j=1; j<=size(#); j++)
2119  {
2120    if(#[j]>maximum)
2121    {
2122      maximum = #[j];
2123    }
2124  }
2125  return(maximum);
2126}
2127example
2128{ "EXAMPLE:"; echo=2;
2129  // biggest int
2130  max(2,3);
2131  max(1,4,3);
2132  // lexicographically biggest intvec
2133  max(intvec(1,2),intvec(0,1),intvec(1,1));
2134  // polynopmial with biggest leading monomial
2135  ring r = 0,x,dp;
2136  max(x+1,x2+x);
2137}
2138///////////////////////////////////////////////////////////////////////////////
2139proc min(def i,list #)
2140"SYNTAX: min (i_1, ..., i_k)
2141TYPE:    same as type of i_1, ..., i_k resp.
2142PURPOSE: returns the minimum for any arguments of a type
2143         for which '>' is defined
2144SEE ALSO: max
2145EXAMPLE: example min; shows an example"
2146{
2147  def minimum = i;
2148  for (int j=1; j<=size(#); j++)
2149  {
2150    if(#[j]<minimum)
2151    {
2152      minimum = #[j];
2153    }
2154  }
2155  return(minimum);
2156}
2157example
2158{ "EXAMPLE:"; echo=2;
2159  // smallest int
2160  min(2,3);
2161  min(1,4,3);
2162  // lexicographically smallest intvec
2163  min(intvec(1,2),intvec(0,1),intvec(1,1));
2164  // polynopmial with smallest leading monomial
2165  ring r = 0,x,dp;
2166  min(x+1,x2+x);
2167}
2168
2169
2170///////////////////////////////////////////////////////////////////////////////
2171/*
2172                                Versuche:
2173///////////////////////////////////////////////////////////////////////////////
2174proc downsizeSB (def I, list #)
2175"USAGE:   downsizeSB(I [,l]); I ideal, l list of integers [default: l=0]
2176RETURN:  intvec, say v, with v[j] either 1 or 0. We have v[j]=1 if
2177         leadmonom(I[j]) is divisible by some leadmonom(I[k]) or if
2178         leadmonom(i[j]) == leadmonom(i[k]) and l[j] >= l[k], with k!=j.
2179PURPOSE: The procedure is applied in a situation where the standard basis
2180         computation in the basering R is done via a conversion through an
2181         overring Phelp with additional variables and where a direct
2182         imap from Phelp to R is too expensive.
2183         Assume Phelp is created by the procedure @code{par2varRing} or
2184         @code{hilbRing} and IPhelp is a SB in Phelp [ with l[j]=
2185         length(IPhelp(j)) or any other integer reflecting the complexity
2186         of a IPhelp[j] ]. Let I = lead(IPhelp) mapped to R and compute
2187         v = downsizeSB(imap(Phelp,I),l) in R. Then, if Ihelp[j] is deleted
2188         for all j with v[j]=1, we can apply imap to the remaining generators
2189         of Ihelp and still get SB in R  (in general not minimal).
2190EXAMPLE: example downsizeSB; shows an example"
2191{
2192   int k,j;
2193   intvec v,l;
2194   poly M,N,W;
2195   int c=size(I);
2196   if( size(#) != 0 )
2197   {
2198     if ( typeof(#[1]) == "intvec" )
2199     {
2200       l = #[1];
2201     }
2202     else
2203     {
2204        ERROR("// 2nd argument must be an intvec");
2205     }
2206   }
2207
2208   l[c+1]=0;
2209   v[c]=0;
2210
2211   j=0;
2212   while(j<c-1)
2213   {
2214     j++;
2215     M = leadmonom(I[j]);
2216     if( M != 0 )
2217     {
2218        for( k=j+1; k<=c; k++ )
2219        {
2220          N = leadmonom(I[k]);
2221          if( N != 0 )
2222          {
2223             if( (M==N) && (l[j]>l[k]) )
2224             {
2225               I[j]=0;
2226               v[j]=1;
2227               break;
2228             }
2229             if( (M==N) && (l[j]<=l[k]) || N/M != 0 )
2230             {
2231               I[k]=0;
2232               v[k]=1;
2233             }
2234          }
2235        }
2236      }
2237   }
2238   return(v);
2239}
2240example
2241{ "EXAMPLE:"; echo = 2;
2242   ring  r = 0,(x,y,z,t),(dp(3),dp);
2243   ideal i = x+y+z+t,xy+yz+xt+zt,xyz+xyt+xzt+yzt,xyzt-t4;
2244   ideal Id = std(i);
2245   ideal I = lead(Id);  I;
2246   ring S = (0,t),(x,y,z),dp;
2247   downsizeSB(imap(r,I));
2248   //Id[5] can be deleted, we still have a SB of i in the ring S
2249
2250   ring R = (0,x),(y,z,u),lp;
2251   ideal i = x+y+z+u,xy+xu+yz+zu,xyz+xyu+xzu+yzu,xyzu-1;
2252   def Phelp = par2varRing()[1];
2253   setring Phelp;
2254   ideal IPhelp = std(imap(R,i));
2255   ideal I = lead(IPhelp);
2256   setring R;
2257   ideal I = imap(Phelp,I); I;
2258   intvec v = downsizeSB(I); v;
2259}
2260///////////////////////////////////////////////////////////////////////////
2261// PROBLEM: Die Prozedur funktioniert nur fuer Ringe die global bekannt
2262//          sind, also interaktiv, aber nicht aus einer Prozedur.
2263//          Z.B. funktioniert example imapDownsize; nicht
2264
2265proc imapDownsize (string R, string I)
2266"SYNTAX: @code{imapDownsize (} string @code{,} string @code{)} *@
2267         First string must be the string of the name of a ring, second
2268         string must be the string of the name of an object in the ring.
2269TYPE:    same type as the object with name the second string
2270PURPOSE: maps the object given by the second string to the basering.
2271         If R resp. I are the first resp. second string, then
2272         imapDownsize(R,I) is equivalent to simplify(imap(`R`,`I`),34).
2273NOTE:    imapDownsize is usually faster than imap if `I` is large and if
2274         simplify has a great effect, since the procedure maps only those
2275         generators from `I` which are not killed by simplify( - ,34).
2276         This is useful if `I` is a standard bases for a block ordering of
2277         `R` and if some variables from the last block in `R` are mapped
2278         to parameters. Then the returned result is a standard basis in
2279         the basering.
2280SEE ALSO: imap, fetch, map
2281EXAMPLE: example imapDownsize; shows an example"
2282{
2283       def BR = basering;
2284       int k;
2285
2286       setring `R`;
2287       def @leadI@ = lead(`I`);
2288       int s = ncols(@leadI@);
2289       setring BR;
2290       ideal @leadI@ = simplify(imap(`R`,@leadI@),32);
2291       intvec vi;
2292       for (k=1; k<=s; k++)
2293       {
2294         vi[k] = @leadI@[k]==0;
2295       }
2296       kill @leadI@;
2297
2298       setring `R`;
2299       kill @leadI@;
2300       for (k=1;  k<=s; k++)
2301       {
2302           if( vi[k]==1 )
2303           {
2304              `I`[k]=0;
2305           }
2306       }
2307       `I` = simplify(`I`,2);
2308
2309       setring BR;
2310       return(imap(`R`,`I`));
2311}
2312example
2313{ "EXAMPLE:"; echo = 2;
2314   ring  r = 0,(x,y,z,t),(dp(3),dp);
2315   ideal i = x+y+z+t,xy+yz+xt+zt,xyz+xyt+xzt+yzt,xyzt-1;
2316   i = std(i); i;
2317
2318   ring s = (0,t),(x,y,z),dp;
2319   imapDownsize("r","i");     //i[5] is omitted since lead(i[2]) | lead(i[5])
2320}
2321///////////////////////////////////////////////////////////////////////////////
2322//die folgende proc war fuer groebner mit fglm vorgesehen, ist aber zu teuer.
2323//Um die projektive Dimension korrekt zu berechnen, muss man aber teuer
2324//voerher ein SB bzgl. einer Gradordnung berechnen und dann homogenisieren.
2325//Sonst koennen hoeherdimensionale Komponenten in Unendlich entstehen
2326
2327proc projInvariants(ideal i,list #)
2328"SYNTAX: @code{projInvariants (} ideal_expression @code{)} @*
2329         @code{projInvariants (} ideal_expression@code{,} list of string_expres          sions@code{)}
2330TYPE:    list, say L, with L[1] and L[2] of type int and L[3] of type intvec
2331PURPOSE: Computes the (projective) dimension (L[1]), degree (L[2]) and the
2332         first Hilbert series (L[3], as intvec) of the homogenized ideal
2333         in the ring given by the procedure @code{hilbRing} with global
2334         ordering dp (resp. wp if the variables have weights >1)
2335         If an argument of type string @code{\"std\"} resp. @code{\"slimgb\"}
2336         is given, the standard basis computatuion uses @code{std} or
2337         @code{slimgb}, otherwise a heuristically chosen method (default)
2338NOTE:    Homogenized means weighted homogenized with respect to the weights
2339         w[i] of the variables var(i) of the basering. The returned dimension,
2340         degree and Hilbertseries are the respective invariants of the
2341         projective variety defined by the homogenized ideal. The dimension
2342         is equal to the (affine) dimension of the ideal in the basering
2343         (degree and Hilbert series make only sense for homogeneous ideals).
2344SEE ALSO: dim, dmult, hilb
2345KEYWORDS: dimension, degree, Hilbert function
2346EXAMPLE: example projInvariants;  shows an example"
2347{
2348  def P = basering;
2349  int p_opt;
2350  string s_opt = option();
2351  if (find(option(), "prot"))  { p_opt = 1; }
2352
2353//---------------- check method and clear denomintors --------------------
2354  int k;
2355  string method;
2356  for (k=1; k<=size(#); k++)
2357  {
2358     if (typeof(#[k]) == "string")
2359     {
2360       method = method + "," + #[k];
2361     }
2362  }
2363
2364  if (npars(P) > 0)             //clear denominators of parameters
2365  {
2366    for( k=ncols(i); k>0; k-- )
2367    {
2368       i[k]=cleardenom(i[k]);
2369    }
2370  }
2371
2372//------------------------ change to hilbRing ----------------------------
2373     list hiRi = hilbRing(i);
2374     intvec W = hiRi[2];
2375     def Philb = hiRi[1];      //note: Philb is no qring and the predefined
2376     setring Philb;            //ideal Id[1] in Philb is homogeneous
2377     int di, de;               //for dimension, degree
2378     intvec hi;                //for hilbert series
2379
2380//-------- compute Hilbert function of homogenized ideal in Philb ---------
2381//Philb has only 1 block. There are three cases
2382
2383     string algorithm;       //possibilities: std, slimgb, stdorslimgb
2384     //define algorithm:
2385     if( find(method,"std") && !find(method,"slimgb") )
2386     {
2387        algorithm = "std";
2388     }
2389     if( find(method,"slimgb") && !find(method,"std") )
2390     {
2391         algorithm = "slimgb";
2392     }
2393     if( find(method,"std") && find(method,"slimgb") ||
2394         (!find(method,"std") && !find(method,"slimgb")) )
2395     {
2396         algorithm = "stdorslimgb";
2397     }
2398
2399     if ( algorithm=="std" || ( algorithm=="stdorslimgb" && char(P)>0 ) )
2400     {
2401        if (p_opt) {"std in ring " + string(Philb);}
2402        Id[1] = std(Id[1]);
2403        di = dim(Id[1])-1;
2404        de = mult(Id[1]);
2405        hi = hilb( Id[1],1,W );
2406     }
2407     if ( algorithm=="slimgb" || ( algorithm=="stdorslimgb" && char(P)==0 ) )
2408     {
2409        if (p_opt) {"slimgb in ring " + string(Philb);}
2410        Id[1] = slimgb(Id[1]);
2411        di = dim( Id[1] );
2412        if (di > -1)
2413        {
2414           di = di-1;
2415        }
2416        de = mult( Id[1] );
2417        hi = hilb( Id[1],1,W );
2418     }
2419     kill Philb;
2420     list L = di,de,hi;
2421     return(L);
2422}
2423example
2424{ "EXAMPLE:"; echo = 2;
2425   ring r = 32003,(x,y,z),lp;
2426   ideal i = y2-xz,x2-z;
2427   projInvariants(i);
2428
2429   ring R = (0),(x,y,z,u,v),lp;
2430   //minpoly = x2+1;
2431   ideal i = x2+1,x2+y+z+u+v,xyzuv-1;
2432   projInvariants(i);
2433   qring S =std(x2+1);
2434   ideal i = imap(R,i);
2435   projInvariants(i);
2436}
2437
2438*/
2439///////////////////////////////////////////////////////////////////////////////
2440//                           EXAMPLES
2441///////////////////////////////////////////////////////////////////////////////
2442/*
2443example stdfglm;
2444example stdhilb;
2445example groebner;
2446example res;
2447example sprintf;
2448example fprintf;
2449example printf;
2450example weightKB;
2451example qslimgb;
2452example par2varRing;
2453*/
2454static proc mod_init()
2455{
2456  if(!defined(Singmathic))
2457  {
2458    load("singmathic.so","try");
2459  }
2460  //int pagelength=24;
2461  //exportto(Top,pagelength);
2462}
2463
2464///////////////////////////////////////////////////////////////////////////////
2465//   replacement for ring declarations via execute()
2466///////////////////////////////////////////////////////////////////////////////
2467
2468/*
2469 * parses
2470 * "(v1,v2,v3,v4,v5)" to list("v1", "v2", "v3", "v4", "v5"),
2471 * "(dp(3), a(1,2,3), ds(3))" to list("dp(3)", "a(1,2,3)", "ds(3)"), and
2472 * "(1,2,3,4)" to list("1", "2", "3", "4")
2473 */
2474static proc tuple_to_tokens(string s)
2475{
2476  list L;
2477  int index = 1;
2478  int curr = 2;
2479  while (s[curr] == " ")
2480  {
2481    curr++;
2482  }
2483  int next = find(s, ",", curr+1);
2484  int b = find(s, "(", curr+1);
2485  if (b != 0 && b < next)
2486  {
2487    next = find(s, ",", find(s, ")", b+1)+1);
2488  }
2489  while (next != 0)
2490  {
2491    L[index] = string(s[curr, next-curr]);
2492    index++;
2493    curr = next+1;
2494    while (s[curr] == " ")
2495    {
2496      curr++;
2497    }
2498    next = find(s, ",", curr+1);
2499    b = find(s, "(", curr+1);
2500    if (b != 0 && b < next)
2501    {
2502      next = find(s, ",", find(s, ")", b+1)+1);
2503    }
2504  }
2505  L[index] = string(s[curr, size(s)-curr]);
2506  return(L);
2507}
2508
2509/*
2510 * parses
2511 * "0" and "(0)" to 0,
2512 * "32003" and "(32003)" to 32003, and
2513 * "(32003,a,b,c)" to
2514 *     list(32003, list("a", "b", "c"), list(list("lp", 1:3)), ideal(0))
2515 */
2516static proc parse_L1(string l1)
2517{
2518  list tokens;
2519  if (l1[1] != "(")
2520  {
2521    tokens[1] = l1;
2522  }
2523  else
2524  {
2525    tokens = tuple_to_tokens(l1);
2526  }
2527  if (tokens[1] == "real")
2528  {
2529    int p1 = 6;
2530    int p2 = 6;
2531    if (size(tokens) > 1)
2532    {
2533      p1 = int(tokens[2]);
2534      p2 = p1;
2535    }
2536    if (size(tokens) > 2)
2537    {
2538      p2 = int(tokens[3]);
2539    }
2540    return(list(0, list(p1, p2)));
2541  }
2542  if (tokens[1] == "complex")
2543  {
2544    int p1 = 6;
2545    int p2 = 6;
2546    string imag_unit = "i";
2547    if (int(tokens[size(tokens)]) == 0)   // not an integer
2548    {
2549      imag_unit = tokens[size(tokens)];
2550      tokens = delete(tokens, size(tokens));
2551    }
2552    if (size(tokens) > 1)
2553    {
2554      p1 = int(tokens[2]);
2555      p2 = p1;
2556    }
2557    if (size(tokens) > 2)
2558    {
2559      p2 = int(tokens[3]);
2560    }
2561    return(list(0, list(p1, p2), imag_unit));
2562  }
2563  if (size(tokens) == 1)
2564  {
2565    return(int(tokens[1]));
2566  }
2567  list L = int(tokens[1]);
2568  L[2] = list(tokens[2..size(tokens)]);
2569  L[3] = list(list("lp", 1:(size(tokens)-1)));
2570  L[4] = ideal(0);
2571  return(L);
2572}
2573
2574static proc parse_var(string v)
2575{
2576  if (v[1, 4] == "var(" && defined(basering))
2577  {
2578    int i = int(v[5,size(v)-5]);
2579    v = ring_list(basering)[2][i];
2580  }
2581  return(v);
2582}
2583
2584/*
2585 * parses
2586 * "x" to list("x") and
2587 * "(x,y,z)" to list("x", "y", "z")
2588 */
2589static proc parse_L2(string l2)
2590{
2591  if (l2[1] != "(")
2592  {
2593    return(list(parse_var(l2)));
2594  }
2595  list V = tuple_to_tokens(l2);
2596  for (int i = size(V); i > 0; i--)
2597  {
2598    V[i] = parse_var(V[i]);
2599  }
2600  return(V);
2601}
2602
2603/*
2604 * parses
2605 * "dp" to list("dp", 1:n_vars),
2606 * "dp(3)" to list("dp", 1:3),
2607 * "c" to list("c", intvec(0)), and
2608 * "wp(3,4)" to list("wp", intvec(3, 4))
2609 */
2610static proc parse_ordering(string ordering, int n_vars)
2611{
2612  string name;
2613  int b1 = find(ordering, "(", 1);
2614  if (b1 == 0)   // no parentheses
2615  {
2616    name = ordering;
2617    if (name == "C" || name == "c")
2618    {
2619      intvec @w = intvec(0);
2620    }
2621    else
2622    {
2623      intvec @w = 1:n_vars;
2624    }
2625  }
2626  else
2627  {
2628    name = ordering[1, b1-1];
2629    int b2 = find(ordering, ")", b1+1);
2630    int c = find(ordering, ",", b1+1);
2631    if (c == 0)
2632    {
2633      if (name == "L")
2634      {
2635        int @w = int(ordering[b1+1, b2-b1-1]);
2636      }
2637      if (name == "wp" || name == "Wp" || name == "ws" || name == "Ws"
2638          || name == "a")
2639      {
2640        intvec @w = int(ordering[b1+1, b2-b1-1]);
2641      }
2642      if (!defined(@w))   // else
2643      {
2644        intvec @w = 1:int(ordering[b1+1, b2-b1-1]);
2645      }
2646    }
2647    else
2648    {
2649      list W = tuple_to_tokens(ordering[b1, b2-b1+1]);
2650      intvec @w = intvec(int(W[1..size(W)]));
2651    }
2652  }
2653  return(list(name, @w));
2654}
2655
2656static proc parse_L3(string l3, int n_vars)
2657{
2658  if (l3[1] != "(")
2659  {
2660    list L =  parse_ordering(l3, n_vars);
2661    return(list(L));
2662  }
2663  // block orderings
2664  list L = tuple_to_tokens(l3);
2665  for (int i = size(L); i > 0; i--)
2666  {
2667    L[i] = parse_ordering(L[i], n_vars);
2668  }
2669  return(L);
2670}
2671
2672proc create_ring(def l1, def l2, def l3, list #)
2673"USAGE:  create_ring(l1, l2, l3[, l4, \"no_minpoly\"]);
2674         l1 int or list, l2 list or string, l3 list or string, l4 ideal
2675RETURN:  ring(list(l1, l2, l3, l4))
2676NOTE:    l1, l2, l3, l4 are assumed to be the four entries of ring_list(R)
2677         where R is the ring to be returned.
2678         @* Optional arguments: If l4 is not given, it is assumend to be
2679         ideal(0). If \"no_minpoly\" is given, then the minimal polynomial
2680         in l1, if present, is set to 0.
2681         @* Shortcuts: Strings such as \"0\", \"(32003)\" or \"(0,a,b,c)\" can
2682         be given as l1. Indexed parameters as in \"(0,a(1..3))\" are
2683         not supported. Strings such as \"(x,y,z)\" can be given as l2.
2684         Indexed variables as in \"(x(1..3),y,z)\" are not supported.
2685         Strings representing orderings such as \"dp\" or \"(lp(3), ds(2))\"
2686         can be given as l3, except matrix orderings given by
2687         \"M([intmat_expression])\".
2688EXAMPLE: example create_ring; shows an example
2689"
2690{
2691  /* setup */
2692  list L; L[4]=def(0);
2693  int kill_ring;
2694  if (!defined(basering))
2695  {
2696    ring R;
2697    kill_ring = 1;
2698  }
2699
2700  /* read optional arguments */
2701  ideal l4;
2702  int no_minpoly;
2703  if (size(#) > 0)
2704  {
2705    if (typeof(#[1]) == "ideal")
2706    {
2707      ideal l4 = #[1];
2708      # = delete(#, 1);
2709    }
2710    if (typeof(#[1]) == "string")
2711    {
2712      if (#[1] == "no_minpoly")
2713      {
2714        no_minpoly = 1;
2715      }
2716    }
2717  }
2718
2719  /* L[1] */
2720  if (typeof(l1) == "list")
2721  {
2722    if (no_minpoly)
2723    {
2724      if (typeof(l1) == "list")
2725      {
2726        if (size(l1) == 4)
2727        {
2728          if (typeof(l1[4]) == "ideal")
2729          {
2730            l1[4] = ideal(0);
2731          }
2732        }
2733      }
2734    }
2735  }
2736  if (typeof(l1) == "string")
2737  {
2738    L[1] = parse_L1(l1);
2739  }
2740  else
2741  {
2742    L[1] = l1;
2743  }
2744
2745  /* L[2] */
2746  if (typeof(l2) == "list")
2747  {
2748    L[2] = l2;
2749  }
2750  else
2751  {
2752    L[2] = parse_L2(l2);
2753  }
2754
2755  /* L[3] */
2756  if (typeof(l3) == "list")
2757  {
2758    L[3] = l3;
2759  }
2760  else
2761  {
2762    L[3] = parse_L3(l3, size(L[2]));
2763  }
2764
2765  /* L[4] */
2766  L[4] = l4;
2767
2768  /* return ring */
2769  def S = ring(L);
2770  if (kill_ring)
2771  {
2772    kill(R);
2773  }
2774  return(S);
2775}
2776example
2777{
2778  "EXAMPLE:"; echo = 2;
2779  ring R = (0,a), x, lp;
2780  ring_list(R);
2781  minpoly = a^2+1;
2782  qring Q = ideal(x^3-2);
2783  ring S = create_ring(ring_list(Q)[1], "(x,y,t)", "dp", "no_minpoly");
2784  basering;
2785}
Note: See TracBrowser for help on using the repository browser.