source: git/Singular/LIB/dmod.lib @ 341696

spielwiese
Last change on this file since 341696 was 341696, checked in by Hans Schönemann <hannes@…>, 14 years ago
Adding Id property to all files git-svn-id: file:///usr/local/Singular/svn/trunk@12231 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100755
File size: 154.0 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="$Id$";
3category="Noncommutative";
4info="
5LIBRARY: dmod.lib     Algorithms for algebraic D-modules
6AUTHORS: Viktor Levandovskyy,     levandov@math.rwth-aachen.de
7@*             Jorge Martin Morales,    jorge@unizar.es
8
9THEORY: Let K be a field of characteristic 0. Given a polynomial ring
10@*      R = K[x_1,...,x_n] and a polynomial F in R,
11@*      one is interested in the R[1/F]-module of rank one, generated by
12@*      the symbol F^s for a symbolic discrete variable s.
13@* In fact, the module R[1/F]*F^s has a structure of a D(R)[s]-module, where D(R)
14@* is an n-th Weyl algebra K<x_1,...,x_n,d_1,...,d_n | d_j x_j = x_j d_j +1> and
15@* D(R)[s] = D(R) tensored with K[s] over K.
16@* Constructively, one needs to find a left ideal I = I(F^s) in D(R), such
17@* that K[x_1,...,x_n,1/F]*F^s is isomorphic to D(R)/I as a D(R)-module.
18@* We often write just D for D(R) and D[s] for D(R)[s].
19@* One is interested in the following data:
20@* - Ann F^s = I = I(F^s) in D(R)[s], denoted by LD in the output
21@* - global Bernstein polynomial in K[s], denoted by bs,
22@* - its minimal integer root s0, the list of all roots of bs, which are known
23@*   to be rational, with their multiplicities, which is denoted by BS
24@* - Ann F^s0 = I(F^s0) in D(R), denoted by LD0 in the output
25@*   (LD0 is a holonomic ideal in D(R))
26@* - Ann^(1) F^s in D(R)[s], denoted by LD1 (logarithmic derivations)
27@* - an operator in D(R)[s], denoted by PS, such that the functional equality
28@*     PS*F^(s+1) = bs*F^s holds in K[x_1,...,x_n,1/F]*F^s.
29
30REFERENCES:
31@* We provide the following implementations of algorithms:
32@* (OT) the classical Ann F^s algorithm from Oaku and Takayama (Journal of
33@* Pure and Applied Math., 1999),
34@* (LOT) Levandovskyy's modification of the Oaku-Takayama algorithm (ISSAC 2007)
35@* (BM) the Ann F^s algorithm by Briancon and Maisonobe (Remarques sur
36@*        l'ideal de Bernstein associe a des polynomes, preprint, 2002)
37@* (LM08) V. Levandovskyy and J. Martin-Morales, ISSAC 2008
38@* (C) Countinho, A Primer of Algebraic D-Modules,
39@* (SST) Saito, Sturmfels, Takayama 'Groebner Deformations of Hypergeometric
40@*         Differential Equations', Springer, 2000
41
42
43GUIDE:
44@* - Ann F^s = I(F^s) = LD in D(R)[s] can be computed by Sannfs [BM, OT, LOT]
45@* - Ann^(1) F^s in D(R)[s] can be computed by Sannfslog
46@* - global Bernstein polynomial bs in K[s] can be computed by bernsteinBM
47@* - Ann F^s0 = I(F^s0) = LD0 in D(R) can be computed by annfs0, annfs, annfsBM,
48@*    annfsOT, annfsLOT, annfs2, annfsRB etc.
49@* - all the relevant data to F^s (LD, LD0, bs, PS) are computed by operatorBM
50@* - operator PS can be computed via operatorModulo or operatorBM
51@*
52@* - annihilator of F^{s1} for a number s1 is computed with annfspecial
53@* - annihilator of F_1^s_1 * ... * F_p^s_p is computed with annfsBMI
54@* - computing the multiplicity of a rational number r in the Bernstein poly
55@*   of a given ideal goes with checkRoot
56@* - check, whether a given univariate polynomial divides the Bernstein poly
57@*   goes with checkFactor
58
59
60MAIN PROCEDURES:
61
62annfs(F[,S,eng]);       compute Ann F^s0 in D and Bernstein polynomial for a poly F
63annfspecial(I, F, m, n);  compute Ann F^n from Ann F^s for a polynomial F and a number n
64Sannfs(F[,S,eng]);      compute Ann F^s in D[s] for a polynomial F
65Sannfslog(F[,eng]);     compute Ann^(1) F^s in D[s] for a polynomial F
66bernsteinBM(F[,eng]);   compute global Bernstein polynomial for a polynomial F (algorithm of Briancon-Maisonobe)
67operatorBM(F[,eng]);    compute Ann F^s, Ann F^s0, BS and PS for a polynomial F (algorithm of Briancon-Maisonobe)
68operatorModulo(F, I, b); compute PS via the modulo approach
69annfsParamBM(F[,eng]);  compute the generic Ann F^s (algorithm by Briancon and Maisonobe) and exceptional parametric constellations for a polynomial F with parametric coefficients
70annfsBMI(F[,eng]);      compute Ann F^s and Bernstein ideal for a polynomial F=f1*..*fP (multivariate algorithm of Briancon-Maisonobe)
71checkRoot(F,a[,S,eng]); check if a given rational is a root of the global Bernstein polynomial of F and compute its multiplicity
72annfsBM(F[,eng]);          compute Ann F^s0 in D and Bernstein polynomial for a polynomial F (algorithm of Briancon-Maisonobe)
73annfsLOT(F[,eng]);         compute Ann F^s0 in D and Bernstein polynomial for a polynomial F (Levandovskyy modification of the Oaku-Takayama algorithm)
74annfsOT(F[,eng]);          compute Ann F^s0 in D and Bernstein polynomial for a polynomial F (algorithm of Oaku-Takayama)
75SannfsBM(F[,eng]);         compute Ann F^s in D[s] for a polynomial F (algorithm of Briancon-Maisonobe)
76SannfsBFCT(F[,eng]);      compute Ann F^s in D[s] for a polynomial F (algorithm of Briancon-Maisonobe, other output ordering)
77SannfsLOT(F[,eng]);        compute Ann F^s in D[s] for a polynomial F (Levandovskyy modification of the Oaku-Takayama algorithm)
78SannfsOT(F[,eng]);         compute Ann F^s in D[s] for a polynomial F (algorithm of Oaku-Takayama)
79annfs0(I,F [,eng]);          compute Ann F^s0 in D and Bernstein polynomial from the known Ann F^s in D[s]
80annfs2(I,F [,eng]);           compute Ann F^s0 in D and Bernstein polynomial from the known Ann F^s in D[s] by using a trick of Noro
81annfsRB(I,F [,eng]);          compute Ann F^s0 in D and Bernstein polynomial from the known Ann F^s in D[s] by reduceB strategy of Macaulay
82checkRoot1(I,F,a[,eng]);   check whether a rational is a root of the global Bernstein polynomial of F from the known Ann F^s in D[s]
83checkRoot2(I,F,a[,eng]);   check whether a rational is a root of the global Bernstein polynomial of F and compute its multiplicity from the known Ann F^s in D[s]
84checkFactor(I,F,q[,eng]); check whether a polynomial q in K[s] is a factor of the global Bernstein polynomial of F from the known Ann F^s in D[s]
85
86AUXILIARY PROCEDURES:
87
88arrange(p);           create a poly, describing a full hyperplane arrangement
89reiffen(p,q);         create a poly, describing a Reiffen curve
90isHolonomic(M);   check whether a module is holonomic
91convloc(L);         replace global orderings with local in the ringlist L
92minIntRoot(P,fact); minimal integer root among the roots of a maximal ideal P
93varNum(s);          the number of the variable with the name s
94isRational(n);  check whether n is a rational number
95
96SEE ALSO: gmssing_lib, bfun_lib, dmodapp_lib
97";
98
99LIB "matrix.lib"; // for submat
100LIB "nctools.lib"; // makeModElimRing etc.
101LIB "elim.lib"; // for nselect
102LIB "qhmoduli.lib"; // for Max
103LIB "gkdim.lib";
104LIB "gmssing.lib";
105LIB "control.lib";  // for genericity
106LIB "dmodapp.lib"; // for e.g. engine
107LIB "poly.lib";
108
109proc testdmodlib()
110{
111  /* tests all procs for consistency */
112  /* adding the new proc, add it here */
113
114  "MAIN PROCEDURES:";
115  example annfs;
116  example Sannfs;
117  example Sannfslog;
118  example bernsteinBM;
119  example operatorBM;
120  example annfspecial;
121  example annfsParamBM;
122  example annfsBMI;
123  example checkRoot;
124  example annfs0;
125  example annfs2;
126  example annfsRB;
127  example annfs2;
128  example operatorModulo;
129  "SECONDARY D-MOD PROCEDURES:";
130  example annfsBM;
131  example annfsLOT;
132  example annfsOT;
133  example SannfsBM;
134  example SannfsLOT;
135  example SannfsOT;
136  example SannfsBFCT;
137  example checkRoot1;
138  example checkRoot2;
139  example checkFactor;
140}
141
142
143
144// new top-level procedures
145proc annfs(poly F, list #)
146"USAGE:  annfs(f [,S,eng]);  f a poly, S a string, eng an optional int
147RETURN:  ring
148PURPOSE: compute the D-module structure of basering[1/f]*f^s with the algorithm
149@*  given in S and with the Groebner basis engine given in ''eng''
150NOTE:  activate the output ring with the @code{setring} command.
151@*    String S; S can be one of the following:
152@*    'bm' (default) - for the algorithm of Briancon and Maisonobe,
153@*    'ot'  - for the algorithm of Oaku and Takayama,
154@*    'lot' - for the Levandovskyy's modification of the algorithm of OT.
155@*  If eng <>0, @code{std} is used for Groebner basis computations,
156@*  otherwise and by default @code{slimgb} is used.
157@*  In the output ring:
158@*  - the ideal LD (which is a Groebner basis) is the needed D-module structure,
159@*  - the list  BS contains roots and multiplicities of a BS-polynomial of f.
160DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
161@*          if @code{printlevel}>=2, all the debug messages will be printed.
162EXAMPLE: example annfs; shows examples
163"
164{
165  int eng = 0;
166  int chs = 0; // choice
167  string algo = "bm";
168  string st;
169  if ( size(#)>0 )
170  {
171   if ( typeof(#[1]) == "string" )
172   {
173     st = string(#[1]);
174     if ( (st == "BM") || (st == "Bm") || (st == "bM") ||(st == "bm"))
175     {
176       algo = "bm";
177       chs  = 1;
178     }
179     if ( (st == "OT") || (st == "Ot") || (st == "oT") || (st == "ot"))
180     {
181       algo = "ot";
182       chs  = 1;
183     }
184     if ( (st == "LOT") || (st == "lOT") || (st == "Lot") || (st == "lot"))
185     {
186       algo = "lot";
187       chs  = 1;
188     }
189     if (chs != 1)
190     {
191       // incorrect value of S
192       print("Incorrect algorithm given, proceed with the default BM");
193       algo = "bm";
194     }
195     // second arg
196     if (size(#)>1)
197     {
198       // exists 2nd arg
199       if ( typeof(#[2]) == "int" )
200       {
201         // the case: given alg, given engine
202         eng = int(#[2]);
203       }
204       else
205       {
206         eng = 0;
207       }
208     }
209     else
210     {
211       // no second arg
212       eng = 0;
213     }
214   }
215   else
216   {
217     if ( typeof(#[1]) == "int" )
218     {
219     // the case: default alg, engine
220     eng = int(#[1]);
221     //      algo = "bm";  //is already set
222     }
223     else
224     {
225       // incorr. 1st arg
226       algo = "bm";
227     }
228   }
229  }
230
231   // size(#)=0, i.e. there is no algorithm and no engine given
232   //  eng = 0; algo = "bm";  //are already set
233   // int ppl = printlevel-voice+2;
234
235  int old_printlevel = printlevel;
236  printlevel=printlevel+1;
237  def save = basering;
238  if ( algo=="ot")
239  {
240    def @A = annfsOT(F,eng);
241  }
242  else
243  {
244    if ( algo=="lot")
245    {
246      def @A = annfsLOT(F,eng);
247    }
248    else
249    {
250      // bm = default
251      def @A = annfsBM(F,eng);
252    }
253  }
254  printlevel = old_printlevel;
255  return(@A);
256}
257example
258{
259  "EXAMPLE:"; echo = 2;
260  ring r = 0,(x,y,z),Dp;
261  poly F = z*x^2+y^3;
262  def A  = annfs(F); // here, the default BM algorithm will be used
263  setring A; // the Weyl algebra in (x,y,z,Dx,Dy,Dz)
264  LD; //the annihilator of F^{-1} over A
265  BS; // roots with multiplicities of BS polynomial
266}
267
268
269proc Sannfs(poly F, list #)
270"USAGE:  Sannfs(f [,S,eng]);  f a poly, S a string, eng an optional int
271RETURN:  ring
272PURPOSE: compute the D-module structure of basering[f^s] with the algorithm
273@*  given in S and with the Groebner basis engine given in eng
274NOTE:    activate the output ring with the @code{setring} command.
275@*       The value of a string S can be
276@*       'bm' (default) - for the algorithm of  Briancon and Maisonobe,
277@*       'lot' - for the Levandovskyy's modification of the algorithm of OT,
278@*       'ot'  - for the algorithm of Oaku and Takayama.
279@*       If eng <>0, @code{std} is used for Groebner basis computations,
280@*       otherwise, and by default @code{slimgb} is used.
281@*       In the output ring:
282@*       - the ideal LD is the needed D-module structure.
283DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
284@*          if @code{printlevel}>=2, all the debug messages will be printed.
285EXAMPLE: example Sannfs; shows examples
286"
287{
288  int eng = 0;
289  int chs = 0; // choice
290  string algo = "bm";
291  string st;
292  if ( size(#)>0 )
293  {
294   if ( typeof(#[1]) == "string" )
295   {
296     st = string(#[1]);
297     if ( (st == "BM") || (st == "Bm") || (st == "bM") ||(st == "bm"))
298     {
299       algo = "bm";
300       chs  = 1;
301     }
302     if ( (st == "OT") || (st == "Ot") || (st == "oT") || (st == "ot"))
303     {
304       algo = "ot";
305       chs  = 1;
306     }
307     if ( (st == "LOT") || (st == "lOT") || (st == "Lot") || (st == "lot"))
308     {
309       algo = "lot";
310       chs  = 1;
311     }
312     if (chs != 1)
313     {
314       // incorrect value of S
315       print("Incorrect algorithm given, proceed with the default BM");
316       algo = "bm";
317     }
318     // second arg
319     if (size(#)>1)
320     {
321       // exists 2nd arg
322       if ( typeof(#[2]) == "int" )
323       {
324         // the case: given alg, given engine
325         eng = int(#[2]);
326       }
327       else
328       {
329         eng = 0;
330       }
331     }
332     else
333     {
334       // no second arg
335       eng = 0;
336     }
337   }
338   else
339   {
340     if ( typeof(#[1]) == "int" )
341     {
342     // the case: default alg, engine
343     eng = int(#[1]);
344     //      algo = "bm";  //is already set
345     }
346     else
347     {
348       // incorr. 1st arg
349       algo = "bm";
350     }
351   }
352  }
353  // size(#)=0, i.e. there is no algorithm and no engine given
354  //  eng = 0; algo = "bm";  //are already set
355  // int ppl = printlevel-voice+2;
356  printlevel=printlevel+1;
357  def save = basering;
358  if ( algo=="ot")
359  {
360    def @A = SannfsOT(F,eng);
361  }
362  else
363  {
364    if ( algo=="lot")
365    {
366      def @A = SannfsLOT(F,eng);
367    }
368    else
369    {
370      // bm = default
371      def @A = SannfsBM(F,eng);
372    }
373  }
374  printlevel=printlevel-1;
375  return(@A);
376}
377example
378{
379  "EXAMPLE:"; echo = 2;
380  ring r = 0,(x,y,z),Dp;
381  poly F = x^3+y^3+z^3;
382  printlevel = 0;
383  def A  = Sannfs(F); // here, the default BM algorithm will be used
384  setring A;
385  LD;
386}
387
388proc Sannfslog (poly F, list #)
389"USAGE:  Sannfslog(f [,eng]);  f a poly, eng an optional int
390RETURN:  ring
391PURPOSE: compute the D-module structure of basering[1/f]*f^s
392NOTE:    activate the output ring with the @code{setring} command.
393@*   In the output ring D[s], the ideal LD1 is generated by the elements
394@*   in Ann F^s in D[s], coming from logarithmic derivations.
395@*       If eng <>0, @code{std} is used for Groebner basis computations,
396@*       otherwise, and by default @code{slimgb} is used.
397DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
398@*          if @code{printlevel}>=2, all the debug messages will be printed.
399EXAMPLE: example Sannfslog; shows examples
400"
401{
402  int eng = 0;
403  if ( size(#)>0 )
404  {
405    if ( typeof(#[1]) == "int" )
406    {
407      eng = int(#[1]);
408    }
409  }
410  int ppl = printlevel-voice+2;
411  def save = basering;
412  int N = nvars(basering);
413  int Nnew = 2*N+1;
414  int i;
415  string s;
416  list RL = ringlist(basering);
417  list L, Lord;
418  list tmp;
419  intvec iv;
420  L[1] = RL[1]; // char
421  L[4] = RL[4]; // char, minpoly
422  // check whether vars have admissible names
423  list Name = RL[2];
424  for (i=1; i<=N; i++)
425  {
426    if (Name[i] == "s")
427    {
428      ERROR("Variable names should not include s");
429    }
430  }
431  // the ideal I
432  ideal I = -F, jacob(F);
433  dbprint(ppl,"// -1-1- starting the computation of syz(-F,_Dx(F))");
434  dbprint(ppl-1, I);
435  matrix M = syz(I);
436  M = transpose(M);  // it is more usefull working with columns
437  dbprint(ppl,"// -1-2- the module syz(-F,_Dx(F)) has been computed");
438  dbprint(ppl-1, M);
439  // ------------ the ring @R ------------
440  // _x, _Dx, s;  elim.ord for _x,_Dx.
441  // now, create the names for new vars
442  list DName;
443  for (i=1; i<=N; i++)
444  {
445    DName[i] = "D"+Name[i]; // concat
446  }
447  tmp[1] = "s";
448  list NName;
449  for (i=1; i<=N; i++)
450  {
451    NName[2*i-1] = Name[i];
452    NName[2*i] = DName[i];
453    //NName[2*i-1] = DName[i];
454    //NName[2*i] = Name[i];
455  }
456  NName[Nnew] = tmp[1];
457  L[2] = NName;
458  tmp = 0;
459  // block ord (a(1,1),a(0,0,1,1),...,dp);
460  //list("a",intvec(1,1)), list("a",intvec(0,0,1,1)), ...
461  tmp[1] = "a";  // string
462  for (i=1; i<=N; i++)
463  {
464    iv[2*i-1] = 1;
465    iv[2*i]   = 1;
466    tmp[2]    = iv;  iv = 0;  // intvec
467    Lord[i]   = tmp;
468  }
469  //list("dp",intvec(1,1,1,1,1,...))
470  s = "iv=";
471  for (i=1; i<=Nnew; i++)
472  {
473    s = s+"1,";
474  }
475  s[size(s)]=";";
476  execute(s);
477  kill s;
478  tmp[1] = "dp";  // string
479  tmp[2] = iv;    // intvec
480  Lord[N+1] = tmp;
481  //list("C",intvec(0))
482  tmp[1] = "C";  // string
483  iv = 0;
484  tmp[2] = iv;   // intvec
485  Lord[N+2] = tmp;
486  tmp = 0;
487  L[3]    = Lord;
488  // we are done with the list. Now add a Plural part
489  def @R@ = ring(L);
490  setring @R@;
491  matrix @D[Nnew][Nnew];
492  for (i=1; i<=N; i++)
493  {
494    @D[2*i-1,2*i]=1;
495    //@D[2*i-1,2*i]=-1;
496  }
497  def @R = nc_algebra(1,@D);
498  setring @R;
499  kill @R@;
500  dbprint(ppl,"// -2-1- the ring @R(_x,_Dx,s) is ready");
501  dbprint(ppl-1, @R);
502  matrix M = imap(save,M);
503  // now, create the vector [-s,_Dx]
504  vector v = [-s];  // now s is a variable
505  for (i=1; i<=N; i++)
506  {
507    v = v + var(2*i)*gen(i+1);
508    //v = v + var(2*i-1)*gen(i+1);
509  }
510  ideal J = ideal(M*v);
511  // make leadcoeffs positive
512  for (i=1; i<= ncols(J); i++)
513  {
514    if ( leadcoef(J[i])<0 )
515    {
516      J[i] = -J[i];
517    }
518  }
519  ideal LD1 = J;
520  kill J;
521  export LD1;
522  return(@R);
523}
524example
525{
526  "EXAMPLE:"; echo = 2;
527  ring r = 0,(x,y),Dp;
528  poly F = x^4+y^5+x*y^4;
529  printlevel = 0;
530  def A  = Sannfslog(F);
531  setring A;
532  LD1;
533}
534
535
536// alternative code for SannfsBM, renamed from annfsBM to ALTannfsBM
537// is superfluos - will not be included in the official documentation
538static proc ALTannfsBM (poly F, list #)
539"USAGE:  ALTannfsBM(f [,eng]);  f a poly, eng an optional int
540RETURN:  ring
541PURPOSE: compute the annihilator ideal of f^s in D[s], where D is the Weyl
542@*   algebra, according to the algorithm by Briancon and Maisonobe
543NOTE:  activate the output ring with the @code{setring} command. In this ring,
544@*       - the ideal LD is the annihilator of f^s.
545@*       If eng <>0, @code{std} is used for Groebner basis computations,
546@*       otherwise, and by default @code{slimgb} is used.
547DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
548@*          if @code{printlevel}>=2, all the debug messages will be printed.
549EXAMPLE: example ALTannfsBM; shows examples
550"
551{
552  int eng = 0;
553  if ( size(#)>0 )
554  {
555    if ( typeof(#[1]) == "int" )
556    {
557      eng = int(#[1]);
558    }
559  }
560  // returns a list with a ring and an ideal LD in it
561  int ppl = printlevel-voice+2;
562  //  printf("plevel :%s, voice: %s",printlevel,voice);
563  def save = basering;
564  int N = nvars(basering);
565  int Nnew = 2*N+2;
566  int i,j;
567  string s;
568  list RL = ringlist(basering);
569  list L, Lord;
570  list tmp;
571  intvec iv;
572  L[1] = RL[1];  //char
573  L[4] = RL[4];  //char, minpoly
574  // check whether vars have admissible names
575  list Name  = RL[2];
576  list RName;
577  RName[1] = "t";
578  RName[2] = "s";
579  for (i=1; i<=N; i++)
580  {
581    for(j=1; j<=size(RName); j++)
582    {
583      if (Name[i] == RName[j])
584      {
585        ERROR("Variable names should not include t,s");
586      }
587    }
588  }
589  // now, create the names for new vars
590  list DName;
591  for (i=1; i<=N; i++)
592  {
593    DName[i] = "D"+Name[i];  //concat
594  }
595  tmp[1] = "t";
596  tmp[2] = "s";
597  list NName = tmp + Name + DName;
598  L[2]   = NName;
599  // Name, Dname will be used further
600  kill NName;
601  // block ord (lp(2),dp);
602  tmp[1]  = "lp"; // string
603  iv      = 1,1;
604  tmp[2]  = iv; //intvec
605  Lord[1] = tmp;
606  // continue with dp 1,1,1,1...
607  tmp[1]  = "dp"; // string
608  s       = "iv=";
609  for (i=1; i<=Nnew; i++)
610  {
611    s = s+"1,";
612  }
613  s[size(s)]= ";";
614  execute(s);
615  kill s;
616  tmp[2]    = iv;
617  Lord[2]   = tmp;
618  tmp[1]    = "C";
619  iv        = 0;
620  tmp[2]    = iv;
621  Lord[3]   = tmp;
622  tmp       = 0;
623  L[3]      = Lord;
624  // we are done with the list
625  def @R@ = ring(L);
626  setring @R@;
627  matrix @D[Nnew][Nnew];
628  @D[1,2]=t;
629  for(i=1; i<=N; i++)
630  {
631    @D[2+i,N+2+i]=1;
632  }
633  // L[5] = matrix(UpOneMatrix(Nnew));
634  // L[6] = @D;
635  def @R = nc_algebra(1,@D);
636  setring @R;
637  kill @R@;
638  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
639  dbprint(ppl-1, @R);
640  // create the ideal I
641  poly  F = imap(save,F);
642  ideal I = t*F+s;
643  poly p;
644  for(i=1; i<=N; i++)
645  {
646    p = t;  //t
647    p = diff(F,var(2+i))*p;
648    I = I, var(N+2+i) + p;
649  }
650  // -------- the ideal I is ready ----------
651  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
652  dbprint(ppl-1, I);
653  ideal J = engine(I,eng);
654  ideal K = nselect(J,1);
655  kill I,J;
656  dbprint(ppl,"// -1-3- t is eliminated");
657  dbprint(ppl-1, K);  //K is without t
658  // create Dn[s], where Dn is the ordinary Weyl Algebra, and put the result into it,
659  // thus creating the ring @R2
660  // keep: N, i,j,s, tmp, RL
661  setring save;
662  Nnew = 2*N+1;
663  // list RL = ringlist(save);  //is defined earlier
664  kill Lord, tmp, iv;
665  L = 0;
666  list Lord, tmp;
667  intvec iv;
668  L[1] = RL[1];
669  L[4] = RL[4];  //char, minpoly
670  // check whether vars have admissible names -> done earlier
671  // list Name = RL[2]
672  // DName is defined earlier
673  tmp[1] = "s";
674  list NName = Name + DName + tmp;
675  L[2] = NName;
676  // dp ordering;
677  string s = "iv=";
678  for (i=1; i<=Nnew; i++)
679  {
680    s = s+"1,";
681  }
682  s[size(s)] = ";";
683  execute(s);
684  kill s;
685  tmp     = 0;
686  tmp[1]  = "dp";  //string
687  tmp[2]  = iv;    //intvec
688  Lord[1] = tmp;
689  tmp[1]  = "C";
690  iv      = 0;
691  tmp[2]  = iv;
692  Lord[2] = tmp;
693  tmp     = 0;
694  L[3]    = Lord;
695  // we are done with the list
696  // Add: Plural part
697  def @R2@ = ring(L);
698  setring @R2@;
699  matrix @D[Nnew][Nnew];
700  for (i=1; i<=N; i++)
701  {
702    @D[i,N+i]=1;
703  }
704  def @R2 = nc_algebra(1,@D);
705  setring @R2;
706  kill @R2@;
707  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready");
708  dbprint(ppl-1, @R2);
709  ideal K = imap(@R,K);
710  option(redSB);
711  //dbprint(ppl,"// -2-2- the final cosmetic std");
712  //K = engine(K,eng);  //std does the job too
713  // total cleanup
714  kill @R;
715  ideal LD = K;
716  export LD;
717  return(@R2);
718}
719example
720{
721  "EXAMPLE:"; echo = 2;
722  ring r = 0,(x,y,z,w),Dp;
723  poly F = x^3+y^3+z^2*w;
724  printlevel = 0;
725  def A = ALTannfsBM(F);
726  setring A;
727  LD;
728}
729
730proc bernsteinBM(poly F, list #)
731"USAGE:  bernsteinBM(f [,eng]);  f a poly, eng an optional int
732RETURN:  list (of roots of the Bernstein polynomial b and their multiplicies)
733PURPOSE: compute the global Bernstein-Sato polynomial for a hypersurface,
734@* defined by f, according to the algorithm by Briancon and Maisonobe
735NOTE:    If eng <>0, @code{std} is used for Groebner basis computations,
736@*       otherwise, and by default @code{slimgb} is used.
737DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
738@*          if @code{printlevel}>=2, all the debug messages will be printed.
739EXAMPLE: example bernsteinBM; shows examples
740"
741{
742  int eng = 0;
743  if ( size(#)>0 )
744  {
745    if ( typeof(#[1]) == "int" )
746    {
747      eng = int(#[1]);
748    }
749  }
750  // returns a list with a ring and an ideal LD in it
751  int ppl = printlevel-voice+2;
752  //  printf("plevel :%s, voice: %s",printlevel,voice);
753  def save = basering;
754  int N = nvars(basering);
755  int Nnew = 2*N+2;
756  int i,j;
757  string s;
758  list RL = ringlist(basering);
759  list L, Lord;
760  list tmp;
761  intvec iv;
762  L[1] = RL[1];  //char
763  L[4] = RL[4];  //char, minpoly
764  // check whether vars have admissible names
765  list Name  = RL[2];
766  list RName;
767  RName[1] = "t";
768  RName[2] = "s";
769  for (i=1; i<=N; i++)
770  {
771    for(j=1; j<=size(RName); j++)
772    {
773      if (Name[i] == RName[j])
774      {
775        ERROR("Variable names should not include t,s");
776      }
777    }
778  }
779  // now, create the names for new vars
780  list DName;
781  for (i=1; i<=N; i++)
782  {
783    DName[i] = "D"+Name[i];  //concat
784  }
785  tmp[1] = "t";
786  tmp[2] = "s";
787  list NName = tmp + Name + DName;
788  L[2]   = NName;
789  // Name, Dname will be used further
790  kill NName;
791  // block ord (lp(2),dp);
792  tmp[1]  = "lp"; // string
793  iv      = 1,1;
794  tmp[2]  = iv; //intvec
795  Lord[1] = tmp;
796  // continue with dp 1,1,1,1...
797  tmp[1]  = "dp"; // string
798  s       = "iv=";
799  for (i=1; i<=Nnew; i++)
800  {
801    s = s+"1,";
802  }
803  s[size(s)]= ";";
804  execute(s);
805  kill s;
806  tmp[2]    = iv;
807  Lord[2]   = tmp;
808  tmp[1]    = "C";
809  iv        = 0;
810  tmp[2]    = iv;
811  Lord[3]   = tmp;
812  tmp       = 0;
813  L[3]      = Lord;
814  // we are done with the list
815  def @R@ = ring(L);
816  setring @R@;
817  matrix @D[Nnew][Nnew];
818  @D[1,2]=t;
819  for(i=1; i<=N; i++)
820  {
821    @D[2+i,N+2+i]=1;
822  }
823  // L[5] = matrix(UpOneMatrix(Nnew));
824  // L[6] = @D;
825  def @R = nc_algebra(1,@D);
826  setring @R;
827  kill @R@;
828  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
829  dbprint(ppl-1, @R);
830  // create the ideal I
831  poly  F = imap(save,F);
832  ideal I = t*F+s;
833  poly p;
834  for(i=1; i<=N; i++)
835  {
836    p = t;  //t
837    p = diff(F,var(2+i))*p;
838    I = I, var(N+2+i) + p;
839  }
840  // -------- the ideal I is ready ----------
841  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
842  dbprint(ppl-1, I);
843  ideal J = engine(I,eng);
844  ideal K = nselect(J,1);
845  kill I,J;
846  dbprint(ppl,"// -1-3- t is eliminated");
847  dbprint(ppl-1, K);  //K is without t
848  // ----------- the ring @R2 ------------
849  // _x, _Dx,s;  elim.ord for _x,_Dx.
850  // keep: N, i,j,s, tmp, RL
851  setring save;
852  Nnew = 2*N+1;
853  kill Lord, tmp, iv, RName;
854  list Lord, tmp;
855  intvec iv;
856  L[1] = RL[1];
857  L[4] = RL[4];  //char, minpoly
858  // check whether vars hava admissible names -> done earlier
859  // now, create the names for new var
860  tmp[1] = "s";
861  // DName is defined earlier
862  list NName = Name + DName + tmp;
863  L[2] = NName;
864  tmp = 0;
865  // block ord (dp(N),dp);
866  string s = "iv=";
867  for (i=1; i<=Nnew-1; i++)
868  {
869    s = s+"1,";
870  }
871  s[size(s)]=";";
872  execute(s);
873  tmp[1] = "dp";  //string
874  tmp[2] = iv;    //intvec
875  Lord[1] = tmp;
876  // continue with dp 1,1,1,1...
877  tmp[1] = "dp";  //string
878  s[size(s)] = ",";
879  s = s+"1;";
880  execute(s);
881  kill s;
882  kill NName;
883  tmp[2]  = iv;
884  Lord[2] = tmp;
885  tmp[1]  = "C";
886  iv      = 0;
887  tmp[2]  = iv;
888  Lord[3] = tmp;
889  tmp     = 0;
890  L[3]    = Lord;
891  // we are done with the list. Now add a Plural part
892  def @R2@ = ring(L);
893  setring @R2@;
894  matrix @D[Nnew][Nnew];
895  for (i=1; i<=N; i++)
896  {
897    @D[i,N+i]=1;
898  }
899  def @R2 = nc_algebra(1,@D);
900  setring @R2;
901  kill @R2@;
902  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready");
903  dbprint(ppl-1, @R2);
904  ideal MM = maxideal(1);
905  MM = 0,s,MM;
906  map R01 = @R, MM;
907  ideal K = R01(K);
908  kill @R, R01;
909  poly F = imap(save,F);
910  K = K,F;
911  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
912  dbprint(ppl-1, K);
913  ideal M = engine(K,eng);
914  ideal K2 = nselect(M,1..Nnew-1);
915  kill K,M;
916  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
917  dbprint(ppl-1, K2);
918  // the ring @R3 and the search for minimal negative int s
919  ring @R3 = 0,s,dp;
920  dbprint(ppl,"// -3-1- the ring @R3(s) is ready");
921  ideal K3 = imap(@R2,K2);
922  kill @R2;
923  poly p = K3[1];
924  dbprint(ppl,"// -3-2- factorization");
925  list P = factorize(p);          //with constants and multiplicities
926  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
927  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
928  {
929    bs[i-1] = P[1][i];
930    m[i-1]  = P[2][i];
931  }
932  // "--------- b-function factorizes into ---------";  P;
933  //int sP = minIntRoot(bs,1);
934  //dbprint(ppl,"// -3-3- minimal integer root found");
935  //dbprint(ppl-1, sP);
936  // convert factors to a list of their roots and multiplicities
937  bs =  normalize(bs);
938  bs = -subst(bs,s,0);
939  setring save;
940  ideal bs = imap(@R3,bs);
941  kill @R3;
942  list BS = bs,m;
943  return(BS);
944}
945example
946{
947  "EXAMPLE:"; echo = 2;
948  ring r = 0,(x,y,z,w),Dp;
949  poly F = x^3+y^3+z^2*w;
950  printlevel = 0;
951  bernsteinBM(F);
952}
953
954// some changes
955proc annfsBM (poly F, list #)
956"USAGE:  annfsBM(f [,eng]);  f a poly, eng an optional int
957RETURN:  ring
958PURPOSE: compute the D-module structure of basering[1/f]*f^s, according
959@* to the algorithm by Briancon and Maisonobe
960NOTE:    activate the output ring with the @code{setring} command. In this ring,
961@*       - the ideal LD (which is a Groebner basis) is the needed D-module structure,
962@*         which is obtained by substituting the minimal integer root of a Bernstein
963@*         polynomial into the s-parametric ideal;
964@*       - the list BS is the list of roots and multiplicities of a Bernstein polynomial of f.
965@*       If eng <>0, @code{std} is used for Groebner basis computations,
966@*       otherwise, and by default @code{slimgb} is used.
967DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
968@*          if @code{printlevel}>=2, all the debug messages will be printed.
969EXAMPLE: example annfsBM; shows examples
970"
971{
972  int eng = 0;
973  if ( size(#)>0 )
974  {
975    if ( typeof(#[1]) == "int" )
976    {
977      eng = int(#[1]);
978    }
979  }
980  // returns a list with a ring and an ideal LD in it
981  int ppl = printlevel-voice+2;
982  //  printf("plevel :%s, voice: %s",printlevel,voice);
983  def save = basering;
984  int N = nvars(basering);
985  int Nnew = 2*N+2;
986  int i,j;
987  string s;
988  list RL = ringlist(basering);
989  list L, Lord;
990  list tmp;
991  intvec iv;
992  L[1] = RL[1];  //char
993  L[4] = RL[4];  //char, minpoly
994  // check whether vars have admissible names
995  list Name  = RL[2];
996  list RName;
997  RName[1] = "t";
998  RName[2] = "s";
999  for (i=1; i<=N; i++)
1000  {
1001    for(j=1; j<=size(RName); j++)
1002    {
1003      if (Name[i] == RName[j])
1004      {
1005        ERROR("Variable names should not include t,s");
1006      }
1007    }
1008  }
1009  // now, create the names for new vars
1010  list DName;
1011  for (i=1; i<=N; i++)
1012  {
1013    DName[i] = "D"+Name[i];  //concat
1014  }
1015  tmp[1] = "t";
1016  tmp[2] = "s";
1017  list NName = tmp + Name + DName;
1018  L[2]   = NName;
1019  // Name, Dname will be used further
1020  kill NName;
1021  // block ord (lp(2),dp);
1022  tmp[1]  = "lp"; // string
1023  iv      = 1,1;
1024  tmp[2]  = iv; //intvec
1025  Lord[1] = tmp;
1026  // continue with dp 1,1,1,1...
1027  tmp[1]  = "dp"; // string
1028  s       = "iv=";
1029  for (i=1; i<=Nnew; i++)
1030  {
1031    s = s+"1,";
1032  }
1033  s[size(s)]= ";";
1034  execute(s);
1035  kill s;
1036  tmp[2]    = iv;
1037  Lord[2]   = tmp;
1038  tmp[1]    = "C";
1039  iv        = 0;
1040  tmp[2]    = iv;
1041  Lord[3]   = tmp;
1042  tmp       = 0;
1043  L[3]      = Lord;
1044  // we are done with the list
1045  def @R@ = ring(L);
1046  setring @R@;
1047  matrix @D[Nnew][Nnew];
1048  @D[1,2]=t;
1049  for(i=1; i<=N; i++)
1050  {
1051    @D[2+i,N+2+i]=1;
1052  }
1053  // L[5] = matrix(UpOneMatrix(Nnew));
1054  // L[6] = @D;
1055  def @R = nc_algebra(1,@D);
1056  setring @R;
1057  kill @R@;
1058  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
1059  dbprint(ppl-1, @R);
1060  // create the ideal I
1061  poly  F = imap(save,F);
1062  ideal I = t*F+s;
1063  poly p;
1064  for(i=1; i<=N; i++)
1065  {
1066    p = t;  //t
1067    p = diff(F,var(2+i))*p;
1068    I = I, var(N+2+i) + p;
1069  }
1070  // -------- the ideal I is ready ----------
1071  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
1072  dbprint(ppl-1, I);
1073  ideal J = engine(I,eng);
1074  ideal K = nselect(J,1);
1075  kill I,J;
1076  dbprint(ppl,"// -1-3- t is eliminated");
1077  dbprint(ppl-1, K);  //K is without t
1078  setring save;
1079  // ----------- the ring @R2 ------------
1080  // _x, _Dx,s;  elim.ord for _x,_Dx.
1081  // keep: N, i,j,s, tmp, RL
1082  Nnew = 2*N+1;
1083  kill Lord, tmp, iv, RName;
1084  list Lord, tmp;
1085  intvec iv;
1086  L[1] = RL[1];
1087  L[4] = RL[4];  //char, minpoly
1088  // check whether vars hava admissible names -> done earlier
1089  // now, create the names for new var
1090  tmp[1] = "s";
1091  // DName is defined earlier
1092  list NName = Name + DName + tmp;
1093  L[2] = NName;
1094  tmp = 0;
1095  // block ord (dp(N),dp);
1096  string s = "iv=";
1097  for (i=1; i<=Nnew-1; i++)
1098  {
1099    s = s+"1,";
1100  }
1101  s[size(s)]=";";
1102  execute(s);
1103  tmp[1] = "dp";  //string
1104  tmp[2] = iv;    //intvec
1105  Lord[1] = tmp;
1106  // continue with dp 1,1,1,1...
1107  tmp[1] = "dp";  //string
1108  s[size(s)] = ",";
1109  s = s+"1;";
1110  execute(s);
1111  kill s;
1112  kill NName;
1113  tmp[2]  = iv;
1114  Lord[2] = tmp;
1115  tmp[1]  = "C";
1116  iv      = 0;
1117  tmp[2]  = iv;
1118  Lord[3] = tmp;
1119  tmp     = 0;
1120  L[3]    = Lord;
1121  // we are done with the list. Now add a Plural part
1122  def @R2@ = ring(L);
1123  setring @R2@;
1124  matrix @D[Nnew][Nnew];
1125  for (i=1; i<=N; i++)
1126  {
1127    @D[i,N+i]=1;
1128  }
1129  def @R2 = nc_algebra(1,@D);
1130  setring @R2;
1131  kill @R2@;
1132  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready");
1133  dbprint(ppl-1, @R2);
1134  ideal MM = maxideal(1);
1135  MM = 0,s,MM;
1136  map R01 = @R, MM;
1137  ideal K = R01(K);
1138  poly F = imap(save,F);
1139  K = K,F;
1140  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
1141  dbprint(ppl-1, K);
1142  ideal M = engine(K,eng);
1143  ideal K2 = nselect(M,1..Nnew-1);
1144  kill K,M;
1145  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
1146  dbprint(ppl-1, K2);
1147  // the ring @R3 and the search for minimal negative int s
1148  ring @R3 = 0,s,dp;
1149  dbprint(ppl,"// -3-1- the ring @R3(s) is ready");
1150  ideal K3 = imap(@R2,K2);
1151  poly p = K3[1];
1152  dbprint(ppl,"// -3-2- factorization");
1153  list P = factorize(p);          //with constants and multiplicities
1154  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1155  for (i=2; i<= size(P[1]); i++)  //we ignore P[1][1] (constant) and P[2][1] (its mult.)
1156  {
1157    bs[i-1] = P[1][i];
1158    m[i-1]  = P[2][i];
1159  }
1160  // "--------- b-function factorizes into ---------";  P;
1161  int sP = minIntRoot(bs,1);
1162  dbprint(ppl,"// -3-3- minimal integer root found");
1163  dbprint(ppl-1, sP);
1164  // convert factors to a list of their roots
1165  bs = normalize(bs);
1166  bs = -subst(bs,s,0);
1167  list BS = bs,m;
1168  //TODO: sort BS!
1169  // --------- substitute s found in the ideal ---------
1170  // --------- going back to @R and substitute ---------
1171  setring @R;
1172  ideal K2 = subst(K,s,sP);
1173  kill K;
1174  // create the ordinary Weyl algebra and put the result into it,
1175  // thus creating the ring @R4
1176  // keep: N, i,j,s, tmp, RL
1177  setring save;
1178  Nnew = 2*N;
1179  // list RL = ringlist(save);  //is defined earlier
1180  kill Lord, tmp, iv;
1181  L = 0;
1182  list Lord, tmp;
1183  intvec iv;
1184  L[1] = RL[1];
1185  L[4] = RL[4];  //char, minpoly
1186  // check whether vars have admissible names -> done earlier
1187  // list Name = RL[2]M
1188  // DName is defined earlier
1189  list NName = Name + DName;
1190  L[2] = NName;
1191  // dp ordering;
1192  string s = "iv=";
1193  for (i=1; i<=Nnew; i++)
1194  {
1195    s = s+"1,";
1196  }
1197  s[size(s)] = ";";
1198  execute(s);
1199  kill s;
1200  tmp     = 0;
1201  tmp[1]  = "dp";  //string
1202  tmp[2]  = iv;    //intvec
1203  Lord[1] = tmp;
1204  tmp[1]  = "C";
1205  iv      = 0;
1206  tmp[2]  = iv;
1207  Lord[2] = tmp;
1208  tmp     = 0;
1209  L[3]    = Lord;
1210  // we are done with the list
1211  // Add: Plural part
1212  def @R4@ = ring(L);
1213  setring @R4@;
1214  matrix @D[Nnew][Nnew];
1215  for (i=1; i<=N; i++)
1216  {
1217    @D[i,N+i]=1;
1218  }
1219  def @R4 = nc_algebra(1,@D);
1220  setring @R4;
1221  kill @R4@;
1222  dbprint(ppl,"// -4-1- the ring @R4(_x,_Dx) is ready");
1223  dbprint(ppl-1, @R4);
1224  ideal K4 = imap(@R,K2);
1225  option(redSB);
1226  dbprint(ppl,"// -4-2- the final cosmetic std");
1227  K4 = engine(K4,eng);  //std does the job too
1228  // total cleanup
1229  kill @R;
1230  kill @R2;
1231  list BS = imap(@R3,BS);
1232  export BS;
1233  kill @R3;
1234  ideal LD = K4;
1235  export LD;
1236  return(@R4);
1237}
1238example
1239{
1240  "EXAMPLE:"; echo = 2;
1241  ring r = 0,(x,y,z),Dp;
1242  poly F = z*x^2+y^3;
1243  printlevel = 0;
1244  def A = annfsBM(F);
1245  setring A;
1246  LD;
1247  BS;
1248}
1249
1250
1251// replacing s with -s-1 => data is shorter
1252// analogue of annfs0
1253proc annfs2(ideal I, poly F, list #)
1254"USAGE:  annfs2(I, F [,eng]);  I an ideal, F a poly, eng an optional int
1255RETURN:  ring
1256PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra,
1257@*       based on the output of Sannfs-like procedure
1258@*       annfs2 uses shorter expressions in the variable s (the idea of Noro).
1259NOTE: activate the output ring with the @code{setring} command. In this ring,
1260@*      - the ideal LD (which is a Groebner basis) is the annihilator of f^s,
1261@*      - the list BS contains the roots with multiplicities of the BS polynomial.
1262@*    If eng <>0, @code{std} is used for Groebner basis computations,
1263@*    otherwise and by default @code{slimgb} is used.
1264DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
1265@*       if @code{printlevel}>=2, all the debug messages will be printed.
1266EXAMPLE: example annfs2; shows examples
1267"
1268{
1269  int eng = 0;
1270  if ( size(#)>0 )
1271  {
1272    if ( typeof(#[1]) == "int" )
1273    {
1274      eng = int(#[1]);
1275    }
1276  }
1277  def @R2 = basering;
1278  // we're in D_n[s], where the elim ord for s is set
1279  ideal J = NF(I,std(F));
1280  // make leadcoeffs positive
1281  int i;
1282  J = subst(J,s,-s-1);
1283  for (i=1; i<= ncols(J); i++)
1284  {
1285    if (leadcoef(J[i]) <0 )
1286    {
1287      J[i] = -J[i];
1288    }
1289  }
1290  J = J,F;
1291  ideal M = engine(J,eng);
1292  int Nnew = nvars(@R2);
1293  ideal K2 = nselect(M,1..Nnew-1);
1294  int ppl = printlevel-voice+2;
1295  dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering");
1296  dbprint(ppl-1, K2);
1297  // the ring @R3 and the search for minimal negative int s
1298  ring @R3 = 0,s,dp;
1299  dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready");
1300  ideal K3 = imap(@R2,K2);
1301  poly p = K3[1];
1302  dbprint(ppl,"// -2-2- factorization");
1303  //  ideal P = factorize(p,1);  //without constants and multiplicities
1304  //  "--------- b-function factorizes into ---------";   P;
1305  // convert factors to the list of their roots with mults
1306  // assume all factors are linear
1307  //  ideal BS = normalize(P);
1308  //  BS = subst(BS,s,0);
1309  //  BS = -BS;
1310  list P = factorize(p);          //with constants and multiplicities
1311  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1312  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
1313  {
1314    bs[i-1] = P[1][i]; bs[i-1] = subst(bs[i-1],s,-s-1);
1315    m[i-1]  = P[2][i];
1316  }
1317  int sP = minIntRoot(bs,1);
1318  bs =  normalize(bs);
1319  bs = -subst(bs,s,0);
1320  dbprint(ppl,"// -2-3- minimal integer root found");
1321  dbprint(ppl-1, sP);
1322 //TODO: sort BS!
1323  // --------- substitute s found in the ideal ---------
1324  // --------- going back to @R and substitute ---------
1325  setring @R2;
1326  K2 = subst(I,s,sP);
1327  // create the ordinary Weyl algebra and put the result into it,
1328  // thus creating the ring @R5
1329  // keep: N, i,j,s, tmp, RL
1330  Nnew = Nnew - 1; // former 2*N;
1331  // list RL = ringlist(save);  // is defined earlier
1332  //  kill Lord, tmp, iv;
1333  list L = 0;
1334  list Lord, tmp;
1335  intvec iv;
1336  list RL = ringlist(basering);
1337  L[1] = RL[1];
1338  L[4] = RL[4];  //char, minpoly
1339  // check whether vars have admissible names -> done earlier
1340  // list Name = RL[2]M
1341  // DName is defined earlier
1342  list NName; // = RL[2]; // skip the last var 's'
1343  for (i=1; i<=Nnew; i++)
1344  {
1345    NName[i] =  RL[2][i];
1346  }
1347  L[2] = NName;
1348  // dp ordering;
1349  string s = "iv=";
1350  for (i=1; i<=Nnew; i++)
1351  {
1352    s = s+"1,";
1353  }
1354  s[size(s)] = ";";
1355  execute(s);
1356  tmp     = 0;
1357  tmp[1]  = "dp";  // string
1358  tmp[2]  = iv;  // intvec
1359  Lord[1] = tmp;
1360  kill s;
1361  tmp[1]  = "C";
1362  iv = 0;
1363  tmp[2]  = iv;
1364  Lord[2] = tmp;
1365  tmp     = 0;
1366  L[3]    = Lord;
1367  // we are done with the list
1368  // Add: Plural part
1369  def @R4@ = ring(L);
1370  setring @R4@;
1371  int N = Nnew/2;
1372  matrix @D[Nnew][Nnew];
1373  for (i=1; i<=N; i++)
1374  {
1375    @D[i,N+i]=1;
1376  }
1377  def @R4 = nc_algebra(1,@D);
1378  setring @R4;
1379  kill @R4@;
1380  dbprint(ppl,"// -3-1- the ring @R4 is ready");
1381  dbprint(ppl-1, @R4);
1382  ideal K4 = imap(@R2,K2);
1383  option(redSB);
1384  dbprint(ppl,"// -3-2- the final cosmetic std");
1385  K4 = engine(K4,eng);  // std does the job too
1386  // total cleanup
1387  ideal bs = imap(@R3,bs);
1388  kill @R3;
1389  list BS = bs,m;
1390  export BS;
1391  ideal LD = K4;
1392  export LD;
1393  return(@R4);
1394}
1395example
1396{ "EXAMPLE:"; echo = 2;
1397  ring r = 0,(x,y,z),Dp;
1398  poly F = x^3+y^3+z^3;
1399  printlevel = 0;
1400  def A = SannfsBM(F);
1401  setring A;
1402  LD;
1403  poly F = imap(r,F);
1404  def B  = annfs2(LD,F);
1405  setring B;
1406  LD;
1407  BS;
1408}
1409
1410// try to replace s with -s-1 => data is shorter as in annfs2
1411// and use Macaulay's reduceB strategy, that is add
1412// not F but <F,dF/dx1,...,dF/dxN>; the resulting B-function
1413// has to be multiplied with (s+1) at the very end
1414proc annfsRB(ideal I, poly F, list #)
1415"USAGE:  annfsRB(I, F [,eng]);  I an ideal, F a poly, eng an optional int
1416RETURN:  ring
1417PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra,
1418@* based on the output of Sannfs like procedure
1419NOTE:    activate the output ring with the @code{setring} command. In this ring,
1420@*       - the ideal LD (which is a Groebner basis) is the annihilator of f^s,
1421@*       - the list BS contains the roots with multiplicities of a Bernstein polynomial of f.
1422@*       If eng <>0, @code{std} is used for Groebner basis computations,
1423@*       otherwise and by default @code{slimgb} is used.
1424@*       This procedure follows the 'reduceB' strategy, used in Macaulay2.
1425DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
1426@*       if @code{printlevel}>=2, all the debug messages will be printed.
1427EXAMPLE: example annfsRB; shows examples
1428"
1429{
1430  int eng = 0;
1431  if ( size(#)>0 )
1432  {
1433    if ( typeof(#[1]) == "int" )
1434    {
1435      eng = int(#[1]);
1436    }
1437  }
1438  def @R2 = basering;
1439  int ppl = printlevel-voice+2;
1440  // we're in D_n[s], where the elim ord for s is set
1441  // switch to comm. ring in X's and compute the GB of Tjurina ideal
1442  dbprint(ppl,"// -1-0- creating K[x] and Tjurina ideal");
1443  list nL = ringlist(@R2);
1444  list temp,t2;
1445  temp[1] = nL[1];
1446  temp[4] = nL[4];
1447  int @n = int((nvars(@R2)-1)/2); // # of x's
1448  int i;
1449  for (i=1; i<=@n; i++)
1450  {
1451    t2[i] = nL[2][i];
1452  }
1453  temp[2] = t2;
1454  t2 = 0;
1455  t2[1] = nL[3][1]; // more weights than vars?
1456  t2[2] = nL[3][3];
1457  temp[3] = t2;
1458  def @R22 = ring(temp);
1459  setring @R22;
1460  poly F = imap(@R2,F);
1461  ideal J = F;
1462  for (i=1; i<=@n; i++)
1463  {
1464    J = J, diff(F,var(i));
1465  }
1466  J = engine(J,eng);
1467  dbprint(ppl,"// -1-1- finished computing the GB of Tjurina ideal");
1468  dbprint(ppl-1, J);
1469  setring @R2;
1470  ideal JF = imap(@R22,J);
1471  kill @R22;
1472  attrib(JF,"isSB",1); // embedded comm ring is used
1473  ideal J = NF(I,JF);
1474  dbprint(ppl,"// -1-2- finished computing the NF of I w.r.t. Tjurina ideal");
1475  dbprint(ppl-1, J2);
1476  // make leadcoeffs positive
1477  J = subst(J,s,-s-1);
1478  for (i=1; i<= ncols(J); i++)
1479  {
1480    if (leadcoef(J[i]) <0 )
1481    {
1482      J[i] = -J[i];
1483    }
1484  }
1485  J = J,JF;
1486  ideal M = engine(J,eng);
1487  int Nnew = nvars(@R2);
1488  ideal K2 = nselect(M,1..Nnew-1);
1489  dbprint(ppl,"// -2-0- _x,_Dx are eliminated in basering");
1490  dbprint(ppl-1, K2);
1491  // the ring @R3 and the search for minimal negative int s
1492  ring @R3 = 0,s,dp;
1493  dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready");
1494  ideal K3 = imap(@R2,K2);
1495  poly p = K3[1];
1496  p = s*p; // mult with the lost (s+1) factor
1497  dbprint(ppl,"// -2-2- factorization");
1498  //  ideal P = factorize(p,1);  //without constants and multiplicities
1499  //  "--------- b-function factorizes into ---------";   P;
1500  // convert factors to the list of their roots with mults
1501  // assume all factors are linear
1502  //  ideal BS = normalize(P);
1503  //  BS = subst(BS,s,0);
1504  //  BS = -BS;
1505  list P = factorize(p);          //with constants and multiplicities
1506  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1507  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
1508  {
1509    bs[i-1] = P[1][i]; bs[i-1] = subst(bs[i-1],s,-s-1);
1510    m[i-1]  = P[2][i];
1511  }
1512  int sP = minIntRoot(bs,1);
1513  bs =  normalize(bs);
1514  bs = -subst(bs,s,0);
1515  dbprint(ppl,"// -2-3- minimal integer root found");
1516  dbprint(ppl-1, sP);
1517 //TODO: sort BS!
1518  // --------- substitute s found in the ideal ---------
1519  // --------- going back to @R and substitute ---------
1520  setring @R2;
1521  K2 = subst(I,s,sP);
1522  // create the ordinary Weyl algebra and put the result into it,
1523  // thus creating the ring @R5
1524  // keep: N, i,j,s, tmp, RL
1525  Nnew = Nnew - 1; // former 2*N;
1526  // list RL = ringlist(save);  // is defined earlier
1527  //  kill Lord, tmp, iv;
1528  list L = 0;
1529  list Lord, tmp;
1530  intvec iv;
1531  list RL = ringlist(basering);
1532  L[1] = RL[1];
1533  L[4] = RL[4];  //char, minpoly
1534  // check whether vars have admissible names -> done earlier
1535  // list Name = RL[2]M
1536  // DName is defined earlier
1537  list NName; // = RL[2]; // skip the last var 's'
1538  for (i=1; i<=Nnew; i++)
1539  {
1540    NName[i] =  RL[2][i];
1541  }
1542  L[2] = NName;
1543  // dp ordering;
1544  string s = "iv=";
1545  for (i=1; i<=Nnew; i++)
1546  {
1547    s = s+"1,";
1548  }
1549  s[size(s)] = ";";
1550  execute(s);
1551  tmp     = 0;
1552  tmp[1]  = "dp";  // string
1553  tmp[2]  = iv;  // intvec
1554  Lord[1] = tmp;
1555  kill s;
1556  tmp[1]  = "C";
1557  iv = 0;
1558  tmp[2]  = iv;
1559  Lord[2] = tmp;
1560  tmp     = 0;
1561  L[3]    = Lord;
1562  // we are done with the list
1563  // Add: Plural part
1564  def @R4@ = ring(L);
1565  setring @R4@;
1566  int N = Nnew/2;
1567  matrix @D[Nnew][Nnew];
1568  for (i=1; i<=N; i++)
1569  {
1570    @D[i,N+i]=1;
1571  }
1572  def @R4 = nc_algebra(1,@D);
1573  setring @R4;
1574  kill @R4@;
1575  dbprint(ppl,"// -3-1- the ring @R4 is ready");
1576  dbprint(ppl-1, @R4);
1577  ideal K4 = imap(@R2,K2);
1578  option(redSB);
1579  dbprint(ppl,"// -3-2- the final cosmetic std");
1580  K4 = engine(K4,eng);  // std does the job too
1581  // total cleanup
1582  ideal bs = imap(@R3,bs);
1583  kill @R3;
1584  list BS = bs,m;
1585  export BS;
1586  ideal LD = K4;
1587  export LD;
1588  return(@R4);
1589}
1590example
1591{ "EXAMPLE:"; echo = 2;
1592  ring r = 0,(x,y,z),Dp;
1593  poly F = x^3+y^3+z^3;
1594  printlevel = 0;
1595  def A = SannfsBM(F); setring A;
1596  LD; // s-parametric ahhinilator
1597  poly F = imap(r,F);
1598  def B  = annfsRB(LD,F); setring B;
1599  LD;
1600  BS;
1601}
1602
1603proc operatorBM(poly F, list #)
1604"USAGE:  operatorBM(f [,eng]);  f a poly, eng an optional int
1605RETURN:  ring
1606PURPOSE: compute the B-operator and other relevant data for Ann F^s,
1607@*  using e.g. algorithm by Briancon and Maisonobe for Ann F^s and BS.
1608NOTE:    activate the output ring with the @code{setring} command. In the output ring D[s]
1609@*       - the polynomial F is the same as the input,
1610@*       - the ideal LD is the annihilator of f^s in Dn[s],
1611@*       - the ideal LD0 is the needed D-mod structure, where LD0 = LD|s=s0,
1612@*       - the polynomial bs is the global Bernstein polynomial of f in the variable s,
1613@*       - the list BS contains all the roots with multiplicities of the global Bernstein polynomial of f,
1614@*       - the polynomial PS is an operator in Dn[s] such that PS*f^(s+1) = bs*f^s.
1615@*       If eng <>0, @code{std} is used for Groebner basis computations,
1616@*       otherwise and by default @code{slimgb} is used.
1617DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
1618@*       if @code{printlevel}>=2, all the debug messages will be printed.
1619EXAMPLE: example operatorBM; shows examples
1620"
1621{
1622  int eng = 0;
1623  if ( size(#)>0 )
1624  {
1625    if ( typeof(#[1]) == "int" )
1626    {
1627      eng = int(#[1]);
1628    }
1629  }
1630  // returns a list with a ring and an ideal LD in it
1631  int ppl = printlevel-voice+2;
1632  //  printf("plevel :%s, voice: %s",printlevel,voice);
1633  def save = basering;
1634  int N = nvars(basering);
1635  int Nnew = 2*N+2;
1636  int i,j;
1637  string s;
1638  list RL = ringlist(basering);
1639  list L, Lord;
1640  list tmp;
1641  intvec iv;
1642  L[1] = RL[1];  //char
1643  L[4] = RL[4];  //char, minpoly
1644  // check whether vars have admissible names
1645  list Name  = RL[2];
1646  list RName;
1647  RName[1] = "t";
1648  RName[2] = "s";
1649  for (i=1; i<=N; i++)
1650  {
1651    for(j=1; j<=size(RName); j++)
1652    {
1653      if (Name[i] == RName[j])
1654      {
1655        ERROR("Variable names should not include t,s");
1656      }
1657    }
1658  }
1659  // now, create the names for new vars
1660  list DName;
1661  for (i=1; i<=N; i++)
1662  {
1663    DName[i] = "D"+Name[i];  //concat
1664  }
1665  tmp[1] = "t";
1666  tmp[2] = "s";
1667  list NName = tmp + Name + DName;
1668  L[2]   = NName;
1669  // Name, Dname will be used further
1670  kill NName;
1671  // block ord (lp(2),dp);
1672  tmp[1]  = "lp"; // string
1673  iv      = 1,1;
1674  tmp[2]  = iv; //intvec
1675  Lord[1] = tmp;
1676  // continue with dp 1,1,1,1...
1677  tmp[1]  = "dp"; // string
1678  s       = "iv=";
1679  for (i=1; i<=Nnew; i++)
1680  {
1681    s = s+"1,";
1682  }
1683  s[size(s)]= ";";
1684  execute(s);
1685  kill s;
1686  tmp[2]    = iv;
1687  Lord[2]   = tmp;
1688  tmp[1]    = "C";
1689  iv        = 0;
1690  tmp[2]    = iv;
1691  Lord[3]   = tmp;
1692  tmp       = 0;
1693  L[3]      = Lord;
1694  // we are done with the list
1695  def @R@ = ring(L);
1696  setring @R@;
1697  matrix @D[Nnew][Nnew];
1698  @D[1,2]=t;
1699  for(i=1; i<=N; i++)
1700  {
1701    @D[2+i,N+2+i]=1;
1702  }
1703  // L[5] = matrix(UpOneMatrix(Nnew));
1704  // L[6] = @D;
1705  def @R = nc_algebra(1,@D);
1706  setring @R;
1707  kill @R@;
1708  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
1709  dbprint(ppl-1, @R);
1710  // create the ideal I
1711  poly  F = imap(save,F);
1712  ideal I = t*F+s;
1713  poly p;
1714  for(i=1; i<=N; i++)
1715  {
1716    p = t;  //t
1717    p = diff(F,var(2+i))*p;
1718    I = I, var(N+2+i) + p;
1719  }
1720  // -------- the ideal I is ready ----------
1721  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
1722  dbprint(ppl-1, I);
1723  ideal J = engine(I,eng);
1724  ideal K = nselect(J,1);
1725  kill I,J;
1726  dbprint(ppl,"// -1-3- t is eliminated");
1727  dbprint(ppl-1, K);  //K is without t
1728  setring save;
1729  // ----------- the ring @R2 ------------
1730  // _x, _Dx,s;  elim.ord for _x,_Dx.
1731  // keep: N, i,j,s, tmp, RL
1732  Nnew = 2*N+1;
1733  kill Lord, tmp, iv, RName;
1734  list Lord, tmp;
1735  intvec iv;
1736  L[1] = RL[1];
1737  L[4] = RL[4];  //char, minpoly
1738  // check whether vars hava admissible names -> done earlier
1739  // now, create the names for new var
1740  tmp[1] = "s";
1741  // DName is defined earlier
1742  list NName = Name + DName + tmp;
1743  L[2] = NName;
1744  tmp = 0;
1745  // block ord (dp(N),dp);
1746  string s = "iv=";
1747  for (i=1; i<=Nnew-1; i++)
1748  {
1749    s = s+"1,";
1750  }
1751  s[size(s)]=";";
1752  execute(s);
1753  tmp[1] = "dp";  //string
1754  tmp[2] = iv;    //intvec
1755  Lord[1] = tmp;
1756  // continue with dp 1,1,1,1...
1757  tmp[1] = "dp";  //string
1758  s[size(s)] = ",";
1759  s = s+"1;";
1760  execute(s);
1761  kill s;
1762  kill NName;
1763  tmp[2]  = iv;
1764  Lord[2] = tmp;
1765  tmp[1]  = "C";
1766  iv      = 0;
1767  tmp[2]  = iv;
1768  Lord[3] = tmp;
1769  tmp     = 0;
1770  L[3]    = Lord;
1771  // we are done with the list. Now add a Plural part
1772  def @R2@ = ring(L);
1773  setring @R2@;
1774  matrix @D[Nnew][Nnew];
1775  for (i=1; i<=N; i++)
1776  {
1777    @D[i,N+i]=1;
1778  }
1779  def @R2 = nc_algebra(1,@D);
1780  setring @R2;
1781  kill @R2@;
1782  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready");
1783  dbprint(ppl-1, @R2);
1784  ideal MM = maxideal(1);
1785  MM = 0,s,MM;
1786  map R01 = @R, MM;
1787  ideal K = R01(K);
1788  poly F = imap(save,F);
1789  K = K,F;
1790  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
1791  dbprint(ppl-1, K);
1792  ideal M = engine(K,eng);
1793  ideal K2 = nselect(M,1..Nnew-1);
1794  kill K,M;
1795  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
1796  dbprint(ppl-1, K2);
1797  // the ring @R3 and the search for minimal negative int s
1798  ring @R3 = 0,s,dp;
1799  dbprint(ppl,"// -3-1- the ring @R3(s) is ready");
1800  ideal K3 = imap(@R2,K2);
1801  kill @R2;
1802  poly p = K3[1];
1803  dbprint(ppl,"// -3-2- factorization");
1804  list P = factorize(p);          //with constants and multiplicities
1805  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1806  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
1807  {
1808    bs[i-1] = P[1][i];
1809    m[i-1]  = P[2][i];
1810  }
1811  // "--------- b-function factorizes into ---------";  P;
1812  int sP = minIntRoot(bs,1);
1813  dbprint(ppl,"// -3-3- minimal integer root found");
1814  dbprint(ppl-1, sP);
1815  // convert factors to a list of their roots with multiplicities
1816  bs = normalize(bs);
1817  bs = -subst(bs,s,0);
1818  list BS = bs,m;
1819  //TODO: sort BS!
1820  // --------- substitute s found in the ideal ---------
1821  // --------- going back to @R and substitute ---------
1822  setring @R;
1823  ideal K2 = subst(K,s,sP);
1824  // create Dn[s], where Dn is the ordinary Weyl algebra, and put the result into it,
1825  // thus creating the ring @R4
1826  // keep: N, i,j,s, tmp, RL
1827  setring save;
1828  Nnew = 2*N+1;
1829  // list RL = ringlist(save);  //is defined earlier
1830  kill Lord, tmp, iv;
1831  L = 0;
1832  list Lord, tmp;
1833  intvec iv;
1834  L[1] = RL[1];
1835  L[4] = RL[4];  //char, minpoly
1836  // check whether vars have admissible names -> done earlier
1837  // list Name = RL[2]
1838  // DName is defined earlier
1839  tmp[1] = "s";
1840  list NName = Name + DName + tmp;
1841  L[2] = NName;
1842  // dp ordering;
1843  string s = "iv=";
1844  for (i=1; i<=Nnew; i++)
1845  {
1846    s = s+"1,";
1847  }
1848  s[size(s)] = ";";
1849  execute(s);
1850  kill s;
1851  tmp     = 0;
1852  tmp[1]  = "dp";  //string
1853  tmp[2]  = iv;    //intvec
1854  Lord[1] = tmp;
1855  tmp[1]  = "C";
1856  iv      = 0;
1857  tmp[2]  = iv;
1858  Lord[2] = tmp;
1859  tmp     = 0;
1860  L[3]    = Lord;
1861  // we are done with the list
1862  // Add: Plural part
1863  def @R4@ = ring(L);
1864  setring @R4@;
1865  matrix @D[Nnew][Nnew];
1866  for (i=1; i<=N; i++)
1867  {
1868    @D[i,N+i]=1;
1869  }
1870  def @R4 = nc_algebra(1,@D);
1871  setring @R4;
1872  kill @R4@;
1873  dbprint(ppl,"// -4-1- the ring @R4(_x,_Dx,s) is ready");
1874  dbprint(ppl-1, @R4);
1875  ideal LD0 = imap(@R,K2);
1876  ideal LD  = imap(@R,K);
1877  kill @R;
1878  poly bs = imap(@R3,p);
1879  list BS = imap(@R3,BS);
1880  kill @R3;
1881  bs = normalize(bs);
1882  poly F = imap(save,F);
1883  dbprint(ppl,"// -4-2- starting the computation of PS via lift");
1884//better liftstd, I didn't knot it works also for Plural, liftslimgb?
1885// liftstd may give extra coeffs in the resulting ideal
1886  matrix T = lift(F+LD,bs);
1887  poly PS = T[1,1];
1888  dbprint(ppl,"// -4-3- an operator PS found, PS*f^(s+1) = b(s)*f^s");
1889  dbprint(ppl-1,PS);
1890  option(redSB);
1891  dbprint(ppl,"// -4-4- the final cosmetic std");
1892  LD0 = engine(LD0,eng);  //std does the job too
1893  LD  = engine(LD,eng);
1894  export F,LD,LD0,bs,BS,PS;
1895  return(@R4);
1896}
1897example
1898{
1899  "EXAMPLE:"; echo = 2;
1900  ring r = 0,(x,y,z),Dp;
1901  poly F = x^3+y^3+z^3;
1902  printlevel = 0;
1903  def A = operatorBM(F);
1904  setring A;
1905  F; // the original polynomial itself
1906  LD; // generic annihilator
1907  LD0; // annihilator
1908  bs; // normalized Bernstein poly
1909  BS; // roots and multiplicities of the Bernstein poly
1910  PS; // the operator, s.t. PS*F^{s+1} = bs*F^s mod LD
1911  reduce(PS*F-bs,LD); // check the property of PS
1912}
1913
1914// more interesting:
1915//  ring r = 0,(x,y,z,w),Dp;
1916//  poly F = x^3+y^3+z^2*w;
1917
1918// need: (c,<) ordering for such comp's
1919
1920proc operatorModulo(poly F, ideal I, poly b)
1921"USAGE:  operatorModulo(f,I,b);  f a poly, I an ideal, b a poly
1922RETURN:  poly
1923PURPOSE: compute the B-operator from the polynomial f,
1924@*           ideal I = Ann f^s and Bernstein-Sato polynomial b
1925@*           using modulo i.e. kernel of module homomorphism
1926NOTE:  The computations take place in the ring, similar to the one
1927@*       returned by Sannfs procedure.
1928@*     Note, that operator is not completely reduced wrt Ann f^{s+1}.
1929@*     If printlevel=1, progress debug messages will be printed,
1930@*     if printlevel>=2, all the debug messages will be printed.
1931EXAMPLE: example operatorModulo; shows examples
1932"
1933{
1934  int ppl = printlevel-voice+2;
1935  def save = basering;
1936  // change the ordering on the currRing
1937  def mering = makeModElimRing(save);
1938  setring mering;
1939  poly b = imap(save, b);
1940  poly F = imap(save, F);
1941  ideal I = imap(save, I);
1942  matrix N = matrix(I); // ann f^s
1943  //  matrix K = hom_kernel(AA,M,N);
1944  // option(noreturnSB)?
1945  /// matrix K = modulo(AA,N); // too slow: do it with slim!
1946    module M = b,-F;
1947    dbprint(ppl,"starting modulo computation");
1948    module K = moduloSlim(M,N);
1949    dbprint(ppl,"finished modulo computation");
1950    //    K = transpose(K);
1951//     matrix M[3][s+2] = F,-b,I[1..s], 1,0:(s+1),0,1,0:(s);
1952//     module GM = slimgb(M);
1953//     module GMT = transpose(G);
1954//     GMT = GMT[2],GMT[3]; // modulo matrix
1955//     module K = GMT[2];
1956//     GMT = transpose(GMT);
1957//     K = transpose(K);
1958//     matrix K = GMT;
1959//////////////////////////////////////////////////
1960//  now select those elts whose 0's entry is nonzero
1961// if there is constant => done
1962// if not => compute GB and get it
1963    module L;
1964    ideal J;
1965    int i;
1966    poly t; number n;
1967    for(i=1; i<=ncols(K); i++)
1968    {
1969      if (K[1,i]!=0)
1970      {
1971        L = L,K[i];
1972        if ( leadmonom(K[1,i]) == 1)
1973        {
1974          t = K[2,i];
1975          n = leadcoef(K[1,i]);
1976          t = t/n;
1977          break;
1978          //          return(t);
1979        }
1980      }
1981    }
1982    if (n!=0)
1983    {
1984      // constant found
1985      setring save; poly t = imap(mering,t); kill mering;
1986      return(t);
1987    }
1988    dbprint(ppl,"no explicit constant. Start one more GB computation");
1989    // else: compute GB and do the same
1990    L = L[2..ncols(L)];
1991    K  = slimgb(L);
1992    dbprint(ppl,"finished GB computation");
1993    for(i=1; i<=ncols(K); i++)
1994    {
1995      if (K[1,i]!=0)
1996      {
1997        if ( leadmonom(K[1,i]) == 1)
1998        {
1999          t = K[2,i];
2000          n = leadcoef(K[1,i]);
2001          t = t/n;
2002//          break;
2003          setring save; poly t = imap(mering,t); kill mering;
2004          return(t);
2005        }
2006      }
2007    }
2008
2009    // we are here if no constant found
2010    "ERROR: must never get here!";
2011    return(0);
2012//     for(i=1; i<=nrows(K); i++)
2013//     {
2014//       if (K[i,2]!=0)
2015//       {
2016//         if ( leadmonom(K[i,2]) == 1)
2017//         {
2018//           t = K[i,1];
2019//           n = leadcoef(K[i,2]);
2020//           t = t/n;
2021// //        J = J, K[i][2];
2022//           break;
2023//         }
2024//      }
2025//   }
2026//   ideal J = groebner(subst(I,s,s+1)); // for NF
2027//   t = NF(t,J);
2028//   "candidate:"; t;
2029//   J = subst(J,s,s-1);
2030//   // test:
2031//   if ( NF(t*F-b,J) !=0)
2032//   {
2033//     "Problem: PS does not work on F";
2034//   }
2035//   return(t);
2036}
2037example
2038{
2039  "EXAMPLE:"; echo = 2;
2040  //  LIB "dmod.lib"; option(prot); option(mem);
2041  ring r = 0,(x,y),Dp;
2042  poly F = x^3+y^3+x*y^3;
2043  def A = Sannfs(F); // here we get LD = ann f^s
2044  setring A;
2045  poly F = imap(r,F);
2046  def B = annfs0(LD,F); // to obtain BS polynomial
2047  list BS = imap(B,BS);   poly bs = fl2poly(BS,"s");
2048  poly PS = operatorModulo(F,LD,bs);
2049  LD = groebner(LD);
2050  PS = NF(PS,subst(LD,s,s+1));; // reduction modulo Ann s^{s+1}
2051  size(PS);
2052  lead(PS);
2053  reduce(PS*F-bs,LD); // check the defining property of PS
2054}
2055
2056proc annfsParamBM (poly F, list #)
2057"USAGE:  annfsParamBM(f [,eng]);  f a poly, eng an optional int
2058RETURN:  ring
2059PURPOSE: compute the generic Ann F^s and exceptional parametric constellations
2060@* of a polynomial with parametric coefficients with the BM algorithm
2061NOTE:    activate the output ring with the @code{setring} command. In this ring,
2062@*       - the ideal LD is the D-module structure oa Ann F^s
2063@*       - the ideal Param contains special parameters as entries
2064@*       If eng <>0, @code{std} is used for Groebner basis computations,
2065@*       otherwise, and by default @code{slimgb} is used.
2066DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
2067@*          if @code{printlevel}>=2, all the debug messages will be printed.
2068EXAMPLE: example annfsParamBM; shows examples
2069"
2070{
2071  //PURPOSE: compute the list of all possible Bernstein-Sato polynomials for a polynomial with parametric coefficients, according to the algorithm by Briancon and Maisonobe
2072  // @*       - the list BS is the list of roots and multiplicities of a Bernstein polynomial of f.
2073  // ***** not implented yet ****
2074  int eng = 0;
2075  if ( size(#)>0 )
2076  {
2077    if ( typeof(#[1]) == "int" )
2078    {
2079      eng = int(#[1]);
2080    }
2081  }
2082  // returns a list with a ring and an ideal LD in it
2083  int ppl = printlevel-voice+2;
2084  //  printf("plevel :%s, voice: %s",printlevel,voice);
2085  def save = basering;
2086  int N = nvars(basering);
2087  int Nnew = 2*N+2;
2088  int i,j;
2089  string s;
2090  list RL = ringlist(basering);
2091  list L, Lord;
2092  list tmp;
2093  intvec iv;
2094  L[1] = RL[1];  //char
2095  L[4] = RL[4];  //char, minpoly
2096  // check whether vars have admissible names
2097  list Name  = RL[2];
2098  list RName;
2099  RName[1] = "t";
2100  RName[2] = "s";
2101  for (i=1; i<=N; i++)
2102  {
2103    for(j=1; j<=size(RName); j++)
2104    {
2105      if (Name[i] == RName[j])
2106      {
2107        ERROR("Variable names should not include t,s");
2108      }
2109    }
2110  }
2111  // now, create the names for new vars
2112  list DName;
2113  for (i=1; i<=N; i++)
2114  {
2115    DName[i] = "D"+Name[i];  //concat
2116  }
2117  tmp[1] = "t";
2118  tmp[2] = "s";
2119  list NName = tmp + Name + DName;
2120  L[2]   = NName;
2121  // Name, Dname will be used further
2122  kill NName;
2123  // block ord (lp(2),dp);
2124  tmp[1]  = "lp"; // string
2125  iv      = 1,1;
2126  tmp[2]  = iv; //intvec
2127  Lord[1] = tmp;
2128  // continue with dp 1,1,1,1...
2129  tmp[1]  = "dp"; // string
2130  s       = "iv=";
2131  for (i=1; i<=Nnew; i++)
2132  {
2133    s = s+"1,";
2134  }
2135  s[size(s)]= ";";
2136  execute(s);
2137  kill s;
2138  tmp[2]    = iv;
2139  Lord[2]   = tmp;
2140  tmp[1]    = "C";
2141  iv        = 0;
2142  tmp[2]    = iv;
2143  Lord[3]   = tmp;
2144  tmp       = 0;
2145  L[3]      = Lord;
2146  // we are done with the list
2147  def @R@ = ring(L);
2148  setring @R@;
2149  matrix @D[Nnew][Nnew];
2150  @D[1,2]=t;
2151  for(i=1; i<=N; i++)
2152  {
2153    @D[2+i,N+2+i]=1;
2154  }
2155  // L[5] = matrix(UpOneMatrix(Nnew));
2156  // L[6] = @D;
2157  def @R = nc_algebra(1,@D);
2158  setring @R;
2159  kill @R@;
2160  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
2161  dbprint(ppl-1, @R);
2162  // create the ideal I
2163  poly  F = imap(save,F);
2164  ideal I = t*F+s;
2165  poly p;
2166  for(i=1; i<=N; i++)
2167  {
2168    p = t;  //t
2169    p = diff(F,var(2+i))*p;
2170    I = I, var(N+2+i) + p;
2171  }
2172  // -------- the ideal I is ready ----------
2173  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
2174  dbprint(ppl-1, I);
2175  ideal J = engine(I,eng);
2176  ideal K = nselect(J,1);
2177  dbprint(ppl,"// -1-3- t is eliminated");
2178  dbprint(ppl-1, K);  //K is without t
2179  // ----- looking for special parameters -----
2180  dbprint(ppl,"// -2-1- starting the computation of the transformation matrix (via lift)");
2181  J = normalize(J);
2182  matrix T = lift(I,J);  //try also with liftstd
2183  kill I,J;
2184  dbprint(ppl,"// -2-2- the transformation matrix has been computed");
2185  dbprint(ppl-1, T);  //T is the transformation matrix
2186  dbprint(ppl,"// -2-3- genericity does the job");
2187  list lParam = genericity(T);
2188  int ip = size(lParam);
2189  int cip;
2190  string sParam;
2191  if (sParam[1]=="-") { sParam=""; } //genericity returns "-"
2192  // if no parameters exist in a basering
2193  for (cip=1; cip <= ip; cip++)
2194  {
2195    sParam = sParam + "," +lParam[cip];
2196  }
2197  if (size(sParam) >=2)
2198  {
2199    sParam = sParam[2..size(sParam)]; // removes the 1st colon
2200  }
2201  export sParam;
2202  kill T;
2203  dbprint(ppl,"// -2-4- the special parameters has been computed");
2204  dbprint(ppl, sParam);
2205  // create Dn[s], where Dn is the ordinary Weyl Algebra, and put the result into it,
2206  // thus creating the ring @R2
2207  // keep: N, i,j,s, tmp, RL
2208  setring save;
2209  Nnew = 2*N+1;
2210  // list RL = ringlist(save);  //is defined earlier
2211  kill Lord, tmp, iv;
2212  L = 0;
2213  list Lord, tmp;
2214  intvec iv;
2215  L[1] = RL[1];
2216  L[4] = RL[4];  //char, minpoly
2217  // check whether vars have admissible names -> done earlier
2218  // list Name = RL[2]M
2219  // DName is defined earlier
2220  tmp[1] = "s";
2221  list NName = Name + DName + tmp;
2222  L[2] = NName;
2223  // dp ordering;
2224  string s = "iv=";
2225  for (i=1; i<=Nnew; i++)
2226  {
2227    s = s+"1,";
2228  }
2229  s[size(s)] = ";";
2230  execute(s);
2231  kill s;
2232  tmp     = 0;
2233  tmp[1]  = "dp";  //string
2234  tmp[2]  = iv;    //intvec
2235  Lord[1] = tmp;
2236  tmp[1]  = "C";
2237  iv      = 0;
2238  tmp[2]  = iv;
2239  Lord[2] = tmp;
2240  tmp     = 0;
2241  L[3]    = Lord;
2242  // we are done with the list
2243  // Add: Plural part
2244  def @R2@ = ring(L);
2245  setring @R2@;
2246  matrix @D[Nnew][Nnew];
2247  for (i=1; i<=N; i++)
2248  {
2249    @D[i,N+i]=1;
2250  }
2251  def @R2 = nc_algebra(1,@D);
2252  setring @R2;
2253  kill @R2@;
2254  dbprint(ppl,"// -3-1- the ring @R2(_x,_Dx,s) is ready");
2255  dbprint(ppl-1, @R2);
2256  ideal K = imap(@R,K);
2257  kill @R;
2258  option(redSB);
2259  dbprint(ppl,"// -3-2- the final cosmetic std");
2260  K = engine(K,eng);  //std does the job too
2261  ideal LD = K;
2262  export LD;
2263  if (sParam[1] == ",")
2264  {
2265    sParam = sParam[2..size(sParam)];
2266  }
2267  //  || ((sParam[1] == " ") && (sParam[2] == ",")))
2268  execute("ideal Param ="+sParam+";");
2269  export Param;
2270  kill sParam;
2271  return(@R2);
2272}
2273example
2274{
2275  "EXAMPLE:"; echo = 2;
2276  ring r = (0,a,b),(x,y),Dp;
2277  poly F = x^2 - (y-a)*(y-b);
2278  printlevel = 0;
2279  def A = annfsParamBM(F);  setring A;
2280  LD;
2281  Param;
2282  setring r;
2283  poly G = x2-(y-a)^2; // try the exceptional value b=a of parameters
2284  def B = annfsParamBM(G); setring B;
2285  LD;
2286  Param;
2287}
2288
2289// *** the following example is nice, but too complicated for the documentation ***
2290//   ring r = (0,a),(x,y,z),Dp;
2291//   poly F = x^4+y^4+z^2+a*x*y*z;
2292//   printlevel = 2; //0
2293//   def A = annfsParamBM(F);
2294//   setring A;
2295//   LD;
2296//   Param;
2297
2298
2299proc annfsBMI(ideal F, list #)
2300"USAGE:  annfsBMI(F [,eng]);  F an ideal, eng an optional int
2301RETURN:  ring
2302PURPOSE: compute the D-module structure of basering[1/f]*f^s where
2303@* f = F[1]*..*F[P], according to the algorithm by Briancon and Maisonobe.
2304NOTE:    activate the output ring with the @code{setring} command. In this ring,
2305@*       - the ideal LD is the needed D-mod structure,
2306@*       - the list BS is the Bernstein ideal of a polynomial f = F[1]*..*F[P].
2307@*       If eng <>0, @code{std} is used for Groebner basis computations,
2308@*       otherwise, and by default @code{slimgb} is used.
2309@*       If printlevel=1, progress debug messages will be printed,
2310@*       if printlevel>=2, all the debug messages will be printed.
2311EXAMPLE: example annfsBMI; shows examples
2312"
2313{
2314  int eng = 0;
2315  if ( size(#)>0 )
2316  {
2317    if ( typeof(#[1]) == "int" )
2318    {
2319      eng = int(#[1]);
2320    }
2321  }
2322  // returns a list with a ring and an ideal LD in it
2323  int ppl = printlevel-voice+2;
2324  //  printf("plevel :%s, voice: %s",printlevel,voice);
2325  def save = basering;
2326  int N = nvars(basering);
2327  int P = size(F);  //if F has some generators which are zero, int P = ncols(I);
2328  int Nnew = 2*N+2*P;
2329  int i,j;
2330  string s;
2331  list RL = ringlist(basering);
2332  list L, Lord;
2333  list tmp;
2334  intvec iv;
2335  L[1] = RL[1];  //char
2336  L[4] = RL[4];  //char, minpoly
2337  // check whether vars have admissible names
2338  list Name  = RL[2];
2339  list RName;
2340  for (j=1; j<=P; j++)
2341  {
2342    RName[j] = "t("+string(j)+")";
2343    RName[j+P] = "s("+string(j)+")";
2344  }
2345  for(i=1; i<=N; i++)
2346  {
2347    for(j=1; j<=size(RName); j++)
2348    {
2349      if (Name[i] == RName[j])
2350      { ERROR("Variable names should not include t(i),s(i)"); }
2351    }
2352  }
2353  // now, create the names for new vars
2354  list DName;
2355  for(i=1; i<=N; i++)
2356  {
2357    DName[i] = "D"+Name[i];  //concat
2358  }
2359  list NName = RName + Name + DName;
2360  L[2]   = NName;
2361  // Name, Dname will be used further
2362  kill NName;
2363  // block ord (lp(P),dp);
2364  tmp[1] = "lp";  //string
2365  s      = "iv=";
2366  for (i=1; i<=2*P; i++)
2367  {
2368    s = s+"1,";
2369  }
2370  s[size(s)]= ";";
2371  execute(s);
2372  tmp[2] = iv;  //intvec
2373  Lord[1] = tmp;
2374  // continue with dp 1,1,1,1...
2375  tmp[1] = "dp";  //string
2376  s      = "iv=";
2377  for (i=1; i<=Nnew; i++)  //actually i<=2*N
2378  {
2379    s = s+"1,";
2380  }
2381  s[size(s)]= ";";
2382  execute(s);
2383  kill s;
2384  tmp[2]  = iv;
2385  Lord[2] = tmp;
2386  tmp[1]  = "C";
2387  iv      = 0;
2388  tmp[2]  = iv;
2389  Lord[3] = tmp;
2390  tmp     = 0;
2391  L[3]    = Lord;
2392  // we are done with the list
2393  def @R@ = ring(L);
2394  setring @R@;
2395  matrix @D[Nnew][Nnew];
2396  for (i=1; i<=P; i++)
2397  {
2398    @D[i,i+P] = t(i);
2399  }
2400  for(i=1; i<=N; i++)
2401  {
2402    @D[2*P+i,2*P+N+i] = 1;
2403  }
2404  // L[5] = matrix(UpOneMatrix(Nnew));
2405  // L[6] = @D;
2406  def @R = nc_algebra(1,@D);
2407  setring @R;
2408  kill @R@;
2409  dbprint(ppl,"// -1-1- the ring @R(_t,_s,_x,_Dx) is ready");
2410  dbprint(ppl-1, @R);
2411  // create the ideal I
2412  ideal  F = imap(save,F);
2413  ideal I = t(1)*F[1]+s(1);
2414  for (j=2; j<=P; j++)
2415  {
2416    I = I, t(j)*F[j]+s(j);
2417  }
2418  poly p,q;
2419  for (i=1; i<=N; i++)
2420  {
2421    p=0;
2422    for (j=1; j<=P; j++)
2423    {
2424      q = t(j);
2425      q = diff(F[j],var(2*P+i))*q;
2426      p = p + q;
2427    }
2428    I = I, var(2*P+N+i) + p;
2429  }
2430  // -------- the ideal I is ready ----------
2431  dbprint(ppl,"// -1-2- starting the elimination of "+string(t(1..P))+" in @R");
2432  dbprint(ppl-1, I);
2433  ideal J = engine(I,eng);
2434  ideal K = nselect(J,1..P);
2435  kill I,J;
2436  dbprint(ppl,"// -1-3- all t(i) are eliminated");
2437  dbprint(ppl-1, K);  //K is without t(i)
2438  // ----------- the ring @R2 ------------
2439  // _x, _Dx,s;  elim.ord for _x,_Dx.
2440  // keep: N, i,j,s, tmp, RL
2441  setring save;
2442  Nnew = 2*N+P;
2443  kill Lord, tmp, iv, RName;
2444  list Lord, tmp;
2445  intvec iv;
2446  L[1] = RL[1];  //char
2447  L[4] = RL[4];  //char, minpoly
2448  // check whether vars hava admissible names -> done earlier
2449  // now, create the names for new var
2450  for (j=1; j<=P; j++)
2451  {
2452    tmp[j] = "s("+string(j)+")";
2453  }
2454  // DName is defined earlier
2455  list NName = Name + DName + tmp;
2456  L[2] = NName;
2457  tmp = 0;
2458  // block ord (dp(N),dp);
2459  string s = "iv=";
2460  for (i=1; i<=Nnew-P; i++)
2461  {
2462    s = s+"1,";
2463  }
2464  s[size(s)]=";";
2465  execute(s);
2466  tmp[1] = "dp";  //string
2467  tmp[2] = iv;    //intvec
2468  Lord[1] = tmp;
2469  // continue with dp 1,1,1,1...
2470  tmp[1] = "dp";  //string
2471  s[size(s)] = ",";
2472  for (j=1; j<=P; j++)
2473  {
2474    s = s+"1,";
2475  }
2476  s[size(s)]=";";
2477  execute(s);
2478  kill s;
2479  kill NName;
2480  tmp[2]  = iv;
2481  Lord[2] = tmp;
2482  tmp[1]  = "C";
2483  iv      = 0;
2484  tmp[2]  = iv;
2485  Lord[3] = tmp;
2486  tmp     = 0;
2487  L[3]    = Lord;
2488  // we are done with the list. Now add a Plural part
2489  def @R2@ = ring(L);
2490  setring @R2@;
2491  matrix @D[Nnew][Nnew];
2492  for (i=1; i<=N; i++)
2493  {
2494    @D[i,N+i]=1;
2495  }
2496  def @R2 = nc_algebra(1,@D);
2497  setring @R2;
2498  kill @R2@;
2499  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,_s) is ready");
2500  dbprint(ppl-1, @R2);
2501//  ideal MM = maxideal(1);
2502//  MM = 0,s,MM;
2503//  map R01 = @R, MM;
2504//  ideal K = R01(K);
2505  ideal F = imap(save,F);  // maybe ideal F = R01(I); ?
2506  ideal K = imap(@R,K);    // maybe ideal K = R01(I); ?
2507  poly f=1;
2508  for (j=1; j<=P; j++)
2509  {
2510    f = f*F[j];
2511  }
2512  K = K,f;       // to compute B (Bernstein-Sato ideal)
2513  //j=2;         // for example
2514  //K = K,F[j];  // to compute Bj (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha)
2515  //K = K,F;     // to compute Bsigma (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha)
2516  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
2517  dbprint(ppl-1, K);
2518  ideal M = engine(K,eng);
2519  ideal K2 = nselect(M,1..Nnew-P);
2520  kill K,M;
2521  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
2522  dbprint(ppl-1, K2);
2523  // the ring @R3 and factorize
2524  ring @R3 = 0,s(1..P),dp;
2525  dbprint(ppl,"// -3-1- the ring @R3(_s) is ready");
2526  ideal K3 = imap(@R2,K2);
2527  if (size(K3)==1)
2528  {
2529    poly p = K3[1];
2530    dbprint(ppl,"// -3-2- factorization");
2531    // Warning: now P is an integer
2532    list Q = factorize(p);         //with constants and multiplicities
2533    ideal bs; intvec m;
2534    for (i=2; i<=size(Q[1]); i++)  //we delete Q[1][1] and Q[2][1]
2535    {
2536      bs[i-1] = Q[1][i];
2537      m[i-1]  = Q[2][i];
2538    }
2539    //  "--------- Q-ideal factorizes into ---------";  list(bs,m);
2540    list BS = bs,m;
2541  }
2542  else
2543  {
2544    // conjecture: the Bernstein ideal is principal
2545    dbprint(ppl,"// -3-2- the Bernstein ideal is not principal");
2546    ideal BS = K3;
2547  }
2548  // create the ring @R4(_x,_Dx,_s) and put the result into it,
2549  // _x, _Dx,s;  ord "dp".
2550  // keep: N, i,j,s, tmp, RL
2551  setring save;
2552  Nnew = 2*N+P;
2553  // list RL = ringlist(save);  //is defined earlier
2554  kill Lord, tmp, iv;
2555  L = 0;
2556  list Lord, tmp;
2557  intvec iv;
2558  L[1] = RL[1];  //char
2559  L[4] = RL[4];  //char, minpoly
2560  // check whether vars hava admissible names -> done earlier
2561  // now, create the names for new var
2562  for (j=1; j<=P; j++)
2563  {
2564    tmp[j] = "s("+string(j)+")";
2565  }
2566  // DName is defined earlier
2567  list NName = Name + DName + tmp;
2568  L[2] = NName;
2569  tmp = 0;
2570  // dp ordering;
2571  string s = "iv=";
2572  for (i=1; i<=Nnew; i++)
2573  {
2574    s = s+"1,";
2575  }
2576  s[size(s)]=";";
2577  execute(s);
2578  kill s;
2579  kill NName;
2580  tmp[1] = "dp";  //string
2581  tmp[2] = iv;    //intvec
2582  Lord[1] = tmp;
2583  tmp[1]  = "C";
2584  iv      = 0;
2585  tmp[2]  = iv;
2586  Lord[2] = tmp;
2587  tmp     = 0;
2588  L[3]    = Lord;
2589  // we are done with the list. Now add a Plural part
2590  def @R4@ = ring(L);
2591  setring @R4@;
2592  matrix @D[Nnew][Nnew];
2593  for (i=1; i<=N; i++)
2594  {
2595    @D[i,N+i]=1;
2596  }
2597  def @R4 = nc_algebra(1,@D);
2598  setring @R4;
2599  kill @R4@;
2600  dbprint(ppl,"// -4-1- the ring @R4i(_x,_Dx,_s) is ready");
2601  dbprint(ppl-1, @R4);
2602  ideal K4 = imap(@R,K);
2603  option(redSB);
2604  dbprint(ppl,"// -4-2- the final cosmetic std");
2605  K4 = engine(K4,eng);  //std does the job too
2606  // total cleanup
2607  kill @R;
2608  kill @R2;
2609  def BS = imap(@R3,BS);
2610  export BS;
2611  kill @R3;
2612  ideal LD = K4;
2613  export LD;
2614  return(@R4);
2615}
2616example
2617{
2618  "EXAMPLE:"; echo = 2;
2619  ring r = 0,(x,y),Dp;
2620  ideal F = x,y,x+y;
2621  printlevel = 0;
2622  def A = annfsBMI(F);
2623  setring A;
2624  LD;
2625  BS;
2626}
2627
2628proc annfsOT(poly F, list #)
2629"USAGE:  annfsOT(f [,eng]);  f a poly, eng an optional int
2630RETURN:  ring
2631PURPOSE: compute the D-module structure of basering[1/f]*f^s,
2632@* according to the algorithm by Oaku and Takayama
2633NOTE:    activate the output ring with the @code{setring} command. In this ring,
2634@*       - the ideal LD (which is a Groebner basis) is the needed D-module structure,
2635@*         which is obtained by substituting the minimal integer root of a Bernstein
2636@*         polynomial into the s-parametric ideal;
2637@*       - the list BS contains roots with multiplicities of a Bernstein polynomial of f.
2638@*       If eng <>0, @code{std} is used for Groebner basis computations,
2639@*       otherwise, and by default @code{slimgb} is used.
2640@*       If printlevel=1, progress debug messages will be printed,
2641@*       if printlevel>=2, all the debug messages will be printed.
2642EXAMPLE: example annfsOT; shows examples
2643"
2644{
2645  int eng = 0;
2646  if ( size(#)>0 )
2647  {
2648    if ( typeof(#[1]) == "int" )
2649    {
2650      eng = int(#[1]);
2651    }
2652  }
2653  // returns a list with a ring and an ideal LD in it
2654  int ppl = printlevel-voice+2;
2655  //  printf("plevel :%s, voice: %s",printlevel,voice);
2656  def save = basering;
2657  int N = nvars(basering);
2658  int Nnew = 2*(N+2);
2659  int i,j;
2660  string s;
2661  list RL = ringlist(basering);
2662  list L, Lord;
2663  list tmp;
2664  intvec iv;
2665  L[1] = RL[1]; // char
2666  L[4] = RL[4]; // char, minpoly
2667  // check whether vars have admissible names
2668  list Name  = RL[2];
2669  list RName;
2670  RName[1] = "u";
2671  RName[2] = "v";
2672  RName[3] = "t";
2673  RName[4] = "Dt";
2674  for(i=1;i<=N;i++)
2675  {
2676    for(j=1; j<=size(RName);j++)
2677    {
2678      if (Name[i] == RName[j])
2679      {
2680        ERROR("Variable names should not include u,v,t,Dt");
2681      }
2682    }
2683  }
2684  // now, create the names for new vars
2685  tmp[1]     = "u";
2686  tmp[2]     = "v";
2687  list UName = tmp;
2688  list DName;
2689  for(i=1;i<=N;i++)
2690  {
2691    DName[i] = "D"+Name[i]; // concat
2692  }
2693  tmp    =  0;
2694  tmp[1] = "t";
2695  tmp[2] = "Dt";
2696  list NName = UName +  tmp + Name + DName;
2697  L[2]   = NName;
2698  tmp    = 0;
2699  // Name, Dname will be used further
2700  kill UName;
2701  kill NName;
2702  // block ord (a(1,1),dp);
2703  tmp[1]  = "a"; // string
2704  iv      = 1,1;
2705  tmp[2]  = iv; //intvec
2706  Lord[1] = tmp;
2707  // continue with dp 1,1,1,1...
2708  tmp[1]  = "dp"; // string
2709  s       = "iv=";
2710  for(i=1;i<=Nnew;i++)
2711  {
2712    s = s+"1,";
2713  }
2714  s[size(s)]= ";";
2715  execute(s);
2716  tmp[2]    = iv;
2717  Lord[2]   = tmp;
2718  tmp[1]    = "C";
2719  iv        = 0;
2720  tmp[2]    = iv;
2721  Lord[3]   = tmp;
2722  tmp       = 0;
2723  L[3]      = Lord;
2724  // we are done with the list
2725  def @R@ = ring(L);
2726  setring @R@;
2727  matrix @D[Nnew][Nnew];
2728  @D[3,4]=1;
2729  for(i=1; i<=N; i++)
2730  {
2731    @D[4+i,N+4+i]=1;
2732  }
2733  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
2734  //  L[5] = matrix(UpOneMatrix(Nnew));
2735  //  L[6] = @D;
2736  def @R = nc_algebra(1,@D);
2737  setring @R;
2738  kill @R@;
2739  dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready");
2740  dbprint(ppl-1, @R);
2741  // create the ideal I
2742  poly  F = imap(save,F);
2743  ideal I = u*F-t,u*v-1;
2744  poly p;
2745  for(i=1; i<=N; i++)
2746  {
2747    p = u*Dt; // u*Dt
2748    p = diff(F,var(4+i))*p;
2749    I = I, var(N+4+i) + p;
2750  }
2751  // -------- the ideal I is ready ----------
2752  dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
2753  dbprint(ppl-1, I);
2754  ideal J = engine(I,eng);
2755  ideal K = nselect(J,1..2);
2756  dbprint(ppl,"// -1-3- u,v are eliminated");
2757  dbprint(ppl-1, K);  // K is without u,v
2758  setring save;
2759  // ------------ new ring @R2 ------------------
2760  // without u,v and with the elim.ord for t,Dt
2761  // tensored with the K[s]
2762  // keep: N, i,j,s, tmp, RL
2763  Nnew = 2*N+2+1;
2764  //  list RL = ringlist(save); // is defined earlier
2765  L = 0;  //  kill L;
2766  kill Lord, tmp, iv, RName;
2767  list Lord, tmp;
2768  intvec iv;
2769  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
2770  // check whether vars have admissible names -> done earlier
2771  //  list Name  = RL[2];
2772  list RName;
2773  RName[1] = "t";
2774  RName[2] = "Dt";
2775  // now, create the names for new var (here, s only)
2776  tmp[1]     = "s";
2777  // DName is defined earlier
2778  list NName = RName + Name + DName + tmp;
2779  L[2]   = NName;
2780  tmp    = 0;
2781  // block ord (a(1,1),dp);
2782  tmp[1]  = "a";  iv = 1,1; tmp[2]  = iv; //intvec
2783  Lord[1] = tmp;
2784  // continue with a(1,1,1,1)...
2785  tmp[1]  = "dp"; s  = "iv=";
2786  for(i=1; i<= Nnew; i++)
2787  {
2788    s = s+"1,";
2789  }
2790  s[size(s)]= ";";  execute(s);
2791  kill NName;
2792  tmp[2]    = iv;
2793  Lord[2]   = tmp;
2794  // extra block for s
2795  // tmp[1] = "dp"; iv = 1;
2796  //  s[size(s)]= ",";  s = s + "1,1,1;";  execute(s);  tmp[2]    = iv;
2797  //  Lord[3]   = tmp;
2798  kill s;
2799  tmp[1]    = "C";   iv  = 0; tmp[2] = iv;
2800  Lord[3]   = tmp;   tmp = 0;
2801  L[3]      = Lord;
2802  // we are done with the list. Now, add a Plural part
2803  def @R2@ = ring(L);
2804  setring @R2@;
2805  matrix @D[Nnew][Nnew];
2806  @D[1,2] = 1;
2807  for(i=1; i<=N; i++)
2808  {
2809    @D[2+i,2+N+i] = 1;
2810  }
2811  def @R2 = nc_algebra(1,@D);
2812  setring @R2;
2813  kill @R2@;
2814  dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready");
2815  dbprint(ppl-1, @R2);
2816  ideal MM = maxideal(1);
2817  MM = 0,0,MM;
2818  map R01 = @R, MM;
2819  ideal K = R01(K);
2820  //  ideal K = imap(@R,K); // names of vars are important!
2821  poly G = t*Dt+s+1; // s is a variable here
2822  K = NF(K,std(G)),G;
2823  // -------- the ideal K_(@R2) is ready ----------
2824  dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2");
2825  dbprint(ppl-1, K);
2826  ideal M  = engine(K,eng);
2827  ideal K2 = nselect(M,1..2);
2828  dbprint(ppl,"// -2-3- t,Dt are eliminated");
2829  dbprint(ppl-1, K2);
2830  //  dbprint(ppl-1+1," -2-4- std of K2");
2831  //  option(redSB);  option(redTail);  K2 = std(K2);
2832  //  K2; // without t,Dt, and with s
2833  // -------- the ring @R3 ----------
2834  // _x, _Dx, s; elim.ord for _x,_Dx.
2835  // keep: N, i,j,s, tmp, RL
2836  setring save;
2837  Nnew = 2*N+1;
2838  //  list RL = ringlist(save); // is defined earlier
2839  //  kill L;
2840  kill Lord, tmp, iv, RName;
2841  list Lord, tmp;
2842  intvec iv;
2843  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
2844  // check whether vars have admissible names -> done earlier
2845  //  list Name  = RL[2];
2846  // now, create the names for new var (here, s only)
2847  tmp[1]     = "s";
2848  // DName is defined earlier
2849  list NName = Name + DName + tmp;
2850  L[2]   = NName;
2851  tmp    = 0;
2852  // block ord (a(1,1...),dp);
2853  string  s = "iv=";
2854  for(i=1; i<=Nnew-1; i++)
2855  {
2856    s = s+"1,";
2857  }
2858  s[size(s)]= ";";
2859  execute(s);
2860  tmp[1]  = "a"; // string
2861  tmp[2]  = iv; //intvec
2862  Lord[1] = tmp;
2863  // continue with dp 1,1,1,1...
2864  tmp[1]  = "dp"; // string
2865  s[size(s)]=","; s= s+"1;";
2866  execute(s);
2867  kill s;
2868  kill NName;
2869  tmp[2]    = iv;
2870  Lord[2]   = tmp;
2871  tmp[1]    = "C";  iv  = 0;  tmp[2] = iv;
2872  Lord[3]   = tmp;  tmp = 0;
2873  L[3]      = Lord;
2874  // we are done with the list. Now add a Plural part
2875  def @R3@ = ring(L);
2876  setring @R3@;
2877  matrix @D[Nnew][Nnew];
2878  for(i=1; i<=N; i++)
2879  {
2880    @D[i,N+i]=1;
2881  }
2882  def @R3 = nc_algebra(1,@D);
2883  setring @R3;
2884  kill @R3@;
2885  dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready");
2886  dbprint(ppl-1, @R3);
2887  ideal MM = maxideal(1);
2888  MM = 0,0,MM;
2889  map R12 = @R2, MM;
2890  ideal K = R12(K2);
2891  poly  F = imap(save,F);
2892  K = K,F;
2893  dbprint(ppl,"// -3-2- starting the elimination of _x,_Dx in @R3");
2894  dbprint(ppl-1, K);
2895  ideal M = engine(K,eng);
2896  ideal K3 = nselect(M,1..Nnew-1);
2897  dbprint(ppl,"// -3-3-  _x,_Dx are eliminated in @R3");
2898  dbprint(ppl-1, K3);
2899  // the ring @R4  and the search for minimal negative int s
2900  ring @R4 = 0,(s),dp;
2901  dbprint(ppl,"// -4-1- the ring @R4 is ready");
2902  ideal K4 = imap(@R3,K3);
2903  poly p = K4[1];
2904  dbprint(ppl,"// -4-2- factorization");
2905////  ideal P = factorize(p,1);  // without constants and multiplicities
2906  list P = factorize(p);         // with constants and multiplicities
2907  ideal bs; intvec m;            // the Bernstein polynomial is monic, so we are not interested in constants
2908  for (i=2; i<=size(P[1]); i++)  // we delete P[1][1] and P[2][1]
2909  {
2910    bs[i-1] = P[1][i];
2911    m[i-1]  = P[2][i];
2912  }
2913  //  "------ b-function factorizes into ----------";  P;
2914////  int sP  = minIntRoot(P, 1);
2915  int sP = minIntRoot(bs,1);
2916  dbprint(ppl,"// -4-3- minimal integer root found");
2917  dbprint(ppl-1, sP);
2918  // convert factors to a list of their roots
2919  // assume all factors are linear
2920////  ideal BS = normalize(P);
2921////  BS = subst(BS,s,0);
2922////  BS = -BS;
2923  bs = normalize(bs);
2924  bs = subst(bs,s,0);
2925  bs = -bs;
2926  list BS = bs,m;
2927  // TODO: sort BS!
2928  // ------ substitute s found in the ideal ------
2929  // ------- going back to @R2 and substitute --------
2930  setring @R2;
2931  ideal K3 = subst(K2,s,sP);
2932  // create the ordinary Weyl algebra and put the result into it,
2933  // thus creating the ring @R5
2934  // keep: N, i,j,s, tmp, RL
2935  setring save;
2936  Nnew = 2*N;
2937  //  list RL = ringlist(save); // is defined earlier
2938  kill Lord, tmp, iv;
2939  L = 0;
2940  list Lord, tmp;
2941  intvec iv;
2942  L[1] = RL[1];   L[4] = RL[4]; // char, minpoly
2943  // check whether vars have admissible names -> done earlier
2944  //  list Name  = RL[2];
2945  // DName is defined earlier
2946  list NName = Name + DName;
2947  L[2]   = NName;
2948  // dp ordering;
2949  string   s       = "iv=";
2950  for(i=1;i<=Nnew;i++)
2951  {
2952    s = s+"1,";
2953  }
2954  s[size(s)]= ";";
2955  execute(s);
2956  tmp     = 0;
2957  tmp[1]  = "dp"; // string
2958  tmp[2]  = iv; //intvec
2959  Lord[1] = tmp;
2960  kill s;
2961  tmp[1]    = "C";
2962  iv        = 0;
2963  tmp[2]    = iv;
2964  Lord[2]   = tmp;
2965  tmp       = 0;
2966  L[3]      = Lord;
2967  // we are done with the list
2968  // Add: Plural part
2969  def @R5@ = ring(L);
2970  setring @R5@;
2971  matrix @D[Nnew][Nnew];
2972  for(i=1; i<=N; i++)
2973  {
2974    @D[i,N+i]=1;
2975  }
2976  def @R5 = nc_algebra(1,@D);
2977  setring @R5;
2978  kill @R5@;
2979  dbprint(ppl,"// -5-1- the ring @R5 is ready");
2980  dbprint(ppl-1, @R5);
2981  ideal K5 = imap(@R2,K3);
2982  option(redSB);
2983  dbprint(ppl,"// -5-2- the final cosmetic std");
2984  K5 = engine(K5,eng); // std does the job too
2985  // total cleanup
2986  kill @R;
2987  kill @R2;
2988  kill @R3;
2989////  ideal BS = imap(@R4,BS);
2990  list BS = imap(@R4,BS);
2991  export BS;
2992  ideal LD = K5;
2993  kill @R4;
2994  export LD;
2995  return(@R5);
2996}
2997example
2998{
2999  "EXAMPLE:"; echo = 2;
3000  ring r = 0,(x,y,z),Dp;
3001  poly F = x^2+y^3+z^5;
3002  printlevel = 0;
3003  def A  = annfsOT(F);
3004  setring A;
3005  LD;
3006  BS;
3007}
3008
3009
3010proc SannfsOT(poly F, list #)
3011"USAGE:  SannfsOT(f [,eng]);  f a poly, eng an optional int
3012RETURN:  ring
3013PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the
3014@* 1st step of the algorithm by Oaku and Takayama in the ring D[s]
3015NOTE:    activate the output ring with the @code{setring} command.
3016@*  In the output ring D[s], the ideal LD (which is NOT a Groebner basis)
3017@*  is the needed D-module structure.
3018@*  If eng <>0, @code{std} is used for Groebner basis computations,
3019@*  otherwise, and by default @code{slimgb} is used.
3020@*  If printlevel=1, progress debug messages will be printed,
3021@*  if printlevel>=2, all the debug messages will be printed.
3022EXAMPLE: example SannfsOT; shows examples
3023"
3024{
3025  int eng = 0;
3026  if ( size(#)>0 )
3027  {
3028    if ( typeof(#[1]) == "int" )
3029    {
3030      eng = int(#[1]);
3031    }
3032  }
3033  // returns a list with a ring and an ideal LD in it
3034  int ppl = printlevel-voice+2;
3035  //  printf("plevel :%s, voice: %s",printlevel,voice);
3036  def save = basering;
3037  int N = nvars(basering);
3038  int Nnew = 2*(N+2);
3039  int i,j;
3040  string s;
3041  list RL = ringlist(basering);
3042  list L, Lord;
3043  list tmp;
3044  intvec iv;
3045  L[1] = RL[1]; // char
3046  L[4] = RL[4]; // char, minpoly
3047  // check whether vars have admissible names
3048  list Name  = RL[2];
3049  list RName;
3050  RName[1] = "u";
3051  RName[2] = "v";
3052  RName[3] = "t";
3053  RName[4] = "Dt";
3054  for(i=1;i<=N;i++)
3055  {
3056    for(j=1; j<=size(RName);j++)
3057    {
3058      if (Name[i] == RName[j])
3059      {
3060        ERROR("Variable names should not include u,v,t,Dt");
3061      }
3062    }
3063  }
3064  // now, create the names for new vars
3065  tmp[1]     = "u";
3066  tmp[2]     = "v";
3067  list UName = tmp;
3068  list DName;
3069  for(i=1;i<=N;i++)
3070  {
3071    DName[i] = "D"+Name[i]; // concat
3072  }
3073  tmp    =  0;
3074  tmp[1] = "t";
3075  tmp[2] = "Dt";
3076  list NName = UName +  tmp + Name + DName;
3077  L[2]   = NName;
3078  tmp    = 0;
3079  // Name, Dname will be used further
3080  kill UName;
3081  kill NName;
3082  // block ord (a(1,1),dp);
3083  tmp[1]  = "a"; // string
3084  iv      = 1,1;
3085  tmp[2]  = iv; //intvec
3086  Lord[1] = tmp;
3087  // continue with dp 1,1,1,1...
3088  tmp[1]  = "dp"; // string
3089  s       = "iv=";
3090  for(i=1;i<=Nnew;i++)
3091  {
3092    s = s+"1,";
3093  }
3094  s[size(s)]= ";";
3095  execute(s);
3096  tmp[2]    = iv;
3097  Lord[2]   = tmp;
3098  tmp[1]    = "C";
3099  iv        = 0;
3100  tmp[2]    = iv;
3101  Lord[3]   = tmp;
3102  tmp       = 0;
3103  L[3]      = Lord;
3104  // we are done with the list
3105  def @R@ = ring(L);
3106  setring @R@;
3107  matrix @D[Nnew][Nnew];
3108  @D[3,4]=1;
3109  for(i=1; i<=N; i++)
3110  {
3111    @D[4+i,N+4+i]=1;
3112  }
3113  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
3114  //  L[5] = matrix(UpOneMatrix(Nnew));
3115  //  L[6] = @D;
3116  def @R =  nc_algebra(1,@D);
3117  setring @R;
3118  kill @R@;
3119  dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready");
3120  dbprint(ppl-1, @R);
3121  // create the ideal I
3122  poly  F = imap(save,F);
3123  ideal I = u*F-t,u*v-1;
3124  poly p;
3125  for(i=1; i<=N; i++)
3126  {
3127    p = u*Dt; // u*Dt
3128    p = diff(F,var(4+i))*p;
3129    I = I, var(N+4+i) + p;
3130  }
3131  // -------- the ideal I is ready ----------
3132  dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
3133  dbprint(ppl-1, I);
3134  ideal J = engine(I,eng);
3135  ideal K = nselect(J,1..2);
3136  dbprint(ppl,"// -1-3- u,v are eliminated");
3137  dbprint(ppl-1, K);  // K is without u,v
3138  setring save;
3139  // ------------ new ring @R2 ------------------
3140  // without u,v and with the elim.ord for t,Dt
3141  // tensored with the K[s]
3142  // keep: N, i,j,s, tmp, RL
3143  Nnew = 2*N+2+1;
3144  //  list RL = ringlist(save); // is defined earlier
3145  L = 0;  //  kill L;
3146  kill Lord, tmp, iv, RName;
3147  list Lord, tmp;
3148  intvec iv;
3149  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
3150  // check whether vars have admissible names -> done earlier
3151  //  list Name  = RL[2];
3152  list RName;
3153  RName[1] = "t";
3154  RName[2] = "Dt";
3155  // now, create the names for new var (here, s only)
3156  tmp[1]     = "s";
3157  // DName is defined earlier
3158  list NName = RName + Name + DName + tmp;
3159  L[2]   = NName;
3160  tmp    = 0;
3161  // block ord (a(1,1),dp);
3162  tmp[1]  = "a";  iv = 1,1; tmp[2]  = iv; //intvec
3163  Lord[1] = tmp;
3164  // continue with a(1,1,1,1)...
3165  tmp[1]  = "dp"; s  = "iv=";
3166  for(i=1; i<= Nnew; i++)
3167  {
3168    s = s+"1,";
3169  }
3170  s[size(s)]= ";";  execute(s);
3171  kill NName;
3172  tmp[2]    = iv;
3173  Lord[2]   = tmp;
3174  // extra block for s
3175  // tmp[1] = "dp"; iv = 1;
3176  //  s[size(s)]= ",";  s = s + "1,1,1;";  execute(s);  tmp[2]    = iv;
3177  //  Lord[3]   = tmp;
3178  kill s;
3179  tmp[1]    = "C";   iv  = 0; tmp[2] = iv;
3180  Lord[3]   = tmp;   tmp = 0;
3181  L[3]      = Lord;
3182  // we are done with the list. Now, add a Plural part
3183  def @R2@ = ring(L);
3184  setring @R2@;
3185  matrix @D[Nnew][Nnew];
3186  @D[1,2] = 1;
3187  for(i=1; i<=N; i++)
3188  {
3189    @D[2+i,2+N+i] = 1;
3190  }
3191  def @R2 = nc_algebra(1,@D);
3192  setring @R2;
3193  kill @R2@;
3194  dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready");
3195  dbprint(ppl-1, @R2);
3196  ideal MM = maxideal(1);
3197  MM = 0,0,MM;
3198  map R01 = @R, MM;
3199  ideal K = R01(K);
3200  //  ideal K = imap(@R,K); // names of vars are important!
3201  poly G = t*Dt+s+1; // s is a variable here
3202  K = NF(K,std(G)),G;
3203  // -------- the ideal K_(@R2) is ready ----------
3204  dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2");
3205  dbprint(ppl-1, K);
3206  ideal M  = engine(K,eng);
3207  ideal K2 = nselect(M,1..2);
3208  dbprint(ppl,"// -2-3- t,Dt are eliminated");
3209  dbprint(ppl-1, K2);
3210  K2 = engine(K2,eng);
3211  setring save;
3212  // ----------- the ring @R3 ------------
3213  // _x, _Dx,s;  elim.ord for _x,_Dx.
3214  // keep: N, i,j,s, tmp, RL
3215  Nnew = 2*N+1;
3216  kill Lord, tmp, iv, RName;
3217  list Lord, tmp;
3218  intvec iv;
3219  L[1] = RL[1];
3220  L[4] = RL[4];  // char, minpoly
3221  // check whether vars hava admissible names -> done earlier
3222  // now, create the names for new var
3223  tmp[1] = "s";
3224  // DName is defined earlier
3225  list NName = Name + DName + tmp;
3226  L[2] = NName;
3227  tmp = 0;
3228  // block ord (dp(N),dp);
3229  string s = "iv=";
3230  for (i=1; i<=Nnew-1; i++)
3231  {
3232    s = s+"1,";
3233  }
3234  s[size(s)]=";";
3235  execute(s);
3236  tmp[1] = "dp";  // string
3237  tmp[2] = iv;   // intvec
3238  Lord[1] = tmp;
3239  // continue with dp 1,1,1,1...
3240  tmp[1] = "dp";  // string
3241  s[size(s)] = ",";
3242  s = s+"1;";
3243  execute(s);
3244  kill s;
3245  kill NName;
3246  tmp[2]      = iv;
3247  Lord[2]     = tmp;
3248  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
3249  Lord[3]     = tmp;  tmp = 0;
3250  L[3]        = Lord;
3251  // we are done with the list. Now add a Plural part
3252  def @R3@ = ring(L);
3253  setring @R3@;
3254  matrix @D[Nnew][Nnew];
3255  for (i=1; i<=N; i++)
3256  {
3257    @D[i,N+i]=1;
3258  }
3259  def @R3 = nc_algebra(1,@D);
3260  setring @R3;
3261  kill @R3@;
3262  dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready");
3263  dbprint(ppl-1, @R3);
3264  ideal MM = maxideal(1);
3265  MM = 0,s,MM;
3266  map R01 = @R2, MM;
3267  ideal K2 = R01(K2);
3268  // total cleanup
3269  ideal LD = K2;
3270  // make leadcoeffs positive
3271  for (i=1; i<= ncols(LD); i++)
3272  {
3273    if (leadcoef(LD[i]) <0 )
3274    {
3275      LD[i] = -LD[i];
3276    }
3277  }
3278  export LD;
3279  kill @R;
3280  kill @R2;
3281  return(@R3);
3282}
3283example
3284{
3285  "EXAMPLE:"; echo = 2;
3286  ring r = 0,(x,y,z),Dp;
3287  poly F = x^3+y^3+z^3;
3288  printlevel = 0;
3289  def A  = SannfsOT(F);
3290  setring A;
3291  LD;
3292}
3293
3294proc SannfsBM(poly F, list #)
3295"USAGE:  SannfsBM(f [,eng]);  f a poly, eng an optional int
3296RETURN:  ring
3297PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the
3298@* 1st step of the algorithm by Briancon and Maisonobe in the ring D[s].
3299NOTE:  activate the output ring with the @code{setring} command.
3300@*   In the output ring D[s], the ideal LD (which is NOT a Groebner basis) is
3301@*   the needed D-module structure.
3302@*   If eng <>0, @code{std} is used for Groebner basis computations,
3303@*   otherwise, and by default @code{slimgb} is used.
3304@*   If printlevel=1, progress debug messages will be printed,
3305@*   if printlevel>=2, all the debug messages will be printed.
3306EXAMPLE: example SannfsBM; shows examples
3307"
3308{
3309  int eng = 0;
3310  if ( size(#)>0 )
3311  {
3312    if ( typeof(#[1]) == "int" )
3313    {
3314      eng = int(#[1]);
3315    }
3316  }
3317  // returns a list with a ring and an ideal LD in it
3318  int ppl = printlevel-voice+2;
3319  //  printf("plevel :%s, voice: %s",printlevel,voice);
3320  def save = basering;
3321  int N = nvars(basering);
3322  int Nnew = 2*N+2;
3323  int i,j;
3324  string s;
3325  list RL = ringlist(basering);
3326  list L, Lord;
3327  list tmp;
3328  intvec iv;
3329  L[1] = RL[1]; // char
3330  L[4] = RL[4]; // char, minpoly
3331  // check whether vars have admissible names
3332  list Name  = RL[2];
3333  list RName;
3334  RName[1] = "t";
3335  RName[2] = "s";
3336  for(i=1;i<=N;i++)
3337  {
3338    for(j=1; j<=size(RName);j++)
3339    {
3340      if (Name[i] == RName[j])
3341      {
3342        ERROR("Variable names should not include t,s");
3343      }
3344    }
3345  }
3346  // now, create the names for new vars
3347  list DName;
3348  for(i=1;i<=N;i++)
3349  {
3350    DName[i] = "D"+Name[i]; // concat
3351  }
3352  tmp[1] = "t";
3353  tmp[2] = "s";
3354  list NName = tmp + Name + DName;
3355  L[2]   = NName;
3356  // Name, Dname will be used further
3357  kill NName;
3358  // block ord (lp(2),dp);
3359  tmp[1]  = "lp"; // string
3360  iv      = 1,1;
3361  tmp[2]  = iv; //intvec
3362  Lord[1] = tmp;
3363  // continue with dp 1,1,1,1...
3364  tmp[1]  = "dp"; // string
3365  s       = "iv=";
3366  for(i=1;i<=Nnew;i++)
3367  {
3368    s = s+"1,";
3369  }
3370  s[size(s)]= ";";
3371  execute(s);
3372  kill s;
3373  tmp[2]    = iv;
3374  Lord[2]   = tmp;
3375  tmp[1]    = "C";
3376  iv        = 0;
3377  tmp[2]    = iv;
3378  Lord[3]   = tmp;
3379  tmp       = 0;
3380  L[3]      = Lord;
3381  // we are done with the list
3382  def @R@ = ring(L);
3383  setring @R@;
3384  matrix @D[Nnew][Nnew];
3385  @D[1,2]=t;
3386  for(i=1; i<=N; i++)
3387  {
3388    @D[2+i,N+2+i]=1;
3389  }
3390  //  L[5] = matrix(UpOneMatrix(Nnew));
3391  //  L[6] = @D;
3392  def @R = nc_algebra(1,@D);
3393  setring @R;
3394  kill @R@;
3395  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
3396  dbprint(ppl-1, @R);
3397  // create the ideal I
3398  poly  F = imap(save,F);
3399  ideal I = t*F+s;
3400  poly p;
3401  for(i=1; i<=N; i++)
3402  {
3403    p = t; // t
3404    p = diff(F,var(2+i))*p;
3405    I = I, var(N+2+i) + p;
3406  }
3407  // -------- the ideal I is ready ----------
3408  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
3409  dbprint(ppl-1, I);
3410  ideal J = engine(I,eng);
3411  ideal K = nselect(J,1);
3412  dbprint(ppl,"// -1-3- t is eliminated");
3413  dbprint(ppl-1, K);  // K is without t
3414  K = engine(K,eng);  // std does the job too
3415  // now, we must change the ordering
3416  // and create a ring without t, Dt
3417  //  setring S;
3418  // ----------- the ring @R3 ------------
3419  // _x, _Dx,s;  elim.ord for _x,_Dx.
3420  // keep: N, i,j,s, tmp, RL
3421  Nnew = 2*N+1;
3422  kill Lord, tmp, iv, RName;
3423  list Lord, tmp;
3424  intvec iv;
3425  list L=imap(save,L);
3426  list RL=imap(save,RL);
3427  L[1] = RL[1];
3428  L[4] = RL[4];  // char, minpoly
3429  // check whether vars hava admissible names -> done earlier
3430  // now, create the names for new var
3431  tmp[1] = "s";
3432  // DName is defined earlier
3433  list NName = Name + DName + tmp;
3434  L[2] = NName;
3435  tmp = 0;
3436  // block ord (dp(N),dp);
3437  string s = "iv=";
3438  for (i=1; i<=Nnew-1; i++)
3439  {
3440    s = s+"1,";
3441  }
3442  s[size(s)]=";";
3443  execute(s);
3444  tmp[1] = "dp";  // string
3445  tmp[2] = iv;   // intvec
3446  Lord[1] = tmp;
3447  // continue with dp 1,1,1,1...
3448  tmp[1] = "dp";  // string
3449  s[size(s)] = ",";
3450  s = s+"1;";
3451  execute(s);
3452  kill s;
3453  kill NName;
3454  tmp[2]      = iv;
3455  Lord[2]     = tmp;
3456  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
3457  Lord[3]     = tmp;  tmp = 0;
3458  L[3]        = Lord;
3459  // we are done with the list. Now add a Plural part
3460  def @R2@ = ring(L);
3461  setring @R2@;
3462  matrix @D[Nnew][Nnew];
3463  for (i=1; i<=N; i++)
3464  {
3465    @D[i,N+i]=1;
3466  }
3467  def @R2 = nc_algebra(1,@D);
3468  setring @R2;
3469  kill @R2@;
3470  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
3471  dbprint(ppl-1, @R2);
3472  ideal MM = maxideal(1);
3473  MM = 0,s,MM;
3474  map R01 = @R, MM;
3475  ideal K = R01(K);
3476  // total cleanup
3477  ideal LD = K;
3478  // make leadcoeffs positive
3479  for (i=1; i<= ncols(LD); i++)
3480  {
3481    if (leadcoef(LD[i]) <0 )
3482    {
3483      LD[i] = -LD[i];
3484    }
3485  }
3486  export LD;
3487  kill @R;
3488  return(@R2);
3489}
3490example
3491{
3492  "EXAMPLE:"; echo = 2;
3493  ring r = 0,(x,y,z),Dp;
3494  poly F = x^3+y^3+z^3;
3495  printlevel = 0;
3496  def A = SannfsBM(F);
3497  setring A;
3498  LD;
3499}
3500
3501static proc safeVarName (string s, list #)
3502{
3503  string S;
3504  int cv = 1;
3505  if (size(#)>1)
3506  {
3507    if (#[1]=="v") { cv = 0; S = varstr(basering); }
3508    if (#[1]=="c") { cv = 0; S = charstr(basering); }
3509  }
3510  if (cv) { S = charstr(basering) + "," + varstr(basering); }
3511  S = "," + S + ",";
3512  s = "," + s + ",";
3513  while (find(S,s) <> 0)
3514  {
3515    s[1] = "@";
3516    s = "," + s;
3517  }
3518  s = s[2..size(s)-1];
3519  return(s)
3520}
3521
3522proc SannfsBFCT(poly F, list #)
3523"USAGE:  SannfsBFCT(f [,a,b,c]);  f a poly, a,b,c optional ints
3524RETURN:  ring
3525PURPOSE: compute a Groebner basis either of Ann(f^s)+<f> or of
3526@*       Ann(f^s)+<f,f_1,...,f_n> in D[s]
3527NOTE:    Activate the output ring with the @code{setring} command.
3528@*  This procedure, unlike SannfsBM, returns the ring D[s] with an anti-
3529@*  elimination ordering for s.
3530@*  The output ring contains an ideal @code{LD}, being a Groebner basis
3531@*  either of  Ann(f^s)+<f>, if a=0 (and by default), or of
3532@*  Ann(f^s)+<f,f_1,...,f_n>, otherwise.
3533@*  Here, f_i stands for the i-th  partial derivative of f.
3534@*  If b<>0, @code{std} is used for Groebner basis computations,
3535@*  otherwise, and by default @code{slimgb} is used.
3536@*  If c<>0, @code{std} is used for Groebner basis computations of
3537@*  ideals <I+J> when I is already a Groebner basis of <I>.
3538@*  Otherwise, and by default the engine determined by the switch b is
3539@*  used. Note that in the case c<>0, the choice for b will be
3540@*  overwritten only for the types of ideals mentioned above.
3541@*  This means that if b<>0, specifying c has no effect.
3542DISPLAY: If printlevel=1, progress debug messages will be printed,
3543@*       if printlevel>=2, all the debug messages will be printed.
3544EXAMPLE: example SannfsBFCT; shows examples
3545"
3546{
3547  int addPD,eng,stdsum;
3548  if (size(#)>0)
3549  {
3550    if (typeof(#[1])=="int" || typeof(#[1])=="number")
3551    {
3552      addPD = int(#[1]);
3553    }
3554    if (size(#)>1)
3555    {
3556      if (typeof(#[2])=="int" || typeof(#[2])=="number")
3557      {
3558        eng = int(#[2]);
3559      }
3560      if (size(#)>2)
3561      {
3562        if (typeof(#[3])=="int" || typeof(#[3])=="number")
3563        {
3564          stdsum = int(#[3]);
3565        }
3566      }
3567    }
3568  }
3569  int ppl = printlevel-voice+2;
3570  def save = basering;
3571  int N = nvars(save);
3572  intvec optSave = option(get);
3573  int i,j;
3574  list RL = ringlist(save);
3575  // ----- step 1: compute syzigies
3576  intvec iv;
3577  list L,Lord;
3578  iv = 1:N; Lord[1] = list("dp",iv);
3579  iv = 0;   Lord[2] = list("C",iv);
3580  L = RL;
3581  L[3] = Lord;
3582  def @RM = ring(L);
3583  kill L,Lord;
3584  setring @RM;
3585  option(redSB);
3586  option(redTail);
3587  def RM = makeModElimRing(@RM);
3588  setring RM;
3589  poly F = imap(save,F);
3590  ideal J = jacob(F);
3591  J = F,J;
3592  dbprint(ppl,"// -1-1- Starting the computation of syz(F,_Dx(F))");
3593  dbprint(ppl-1, J);
3594  module M = syz(J);
3595  dbprint(ppl,"// -1-2- The module syz(F,_Dx(F)) has been computed");
3596  dbprint(ppl-1, M);
3597  dbprint(ppl,"// -1-3- Starting GB computation of syz(F,_Dx(F))");
3598  M = engine(M,eng);
3599  dbprint(ppl,"// -1-4- GB computation finished");
3600  dbprint(ppl-1, M);
3601  // ----- step 2: compute part of Ann(F^s)
3602  setring save;
3603  option(set,optSave);
3604  module M = imap(RM,M);
3605  kill optSave,RM;
3606  // ----- create D[s]
3607  int Nnew = 2*N+1;
3608  list L, Lord;
3609  // ----- keep char, minpoly
3610  L[1] = RL[1];
3611  L[4] = RL[4];
3612  // ----- create names for new vars
3613  list Name  = RL[2];
3614  string newVar@s = safeVarName("s");
3615  if (newVar@s[1] == "@")
3616  {
3617    print("Name s already assigned to parameter/ringvar.");
3618    print("Using " + newVar@s + " instead.")
3619  }
3620  list DName;
3621  for (i=1; i<=N; i++)
3622  {
3623    DName[i] = safeVarName("D" + Name[i]);
3624  }
3625  L[2] = list(newVar@s) + Name + DName;
3626  // ----- create ordering
3627  // --- anti-elimination ordering for s
3628  iv = 1;       Lord[1] = list("dp",iv);
3629  iv = 1:(2*N); Lord[2] = list("dp",iv);
3630  iv = 0;       Lord[3] = list("C",iv);
3631  L[3] = Lord;
3632  // ----- create commutative ring
3633  def @Ds = ring(L);
3634  kill L,Lord;
3635  setring @Ds;
3636  // ----- create nc relations
3637   matrix Drel[Nnew][Nnew];
3638  for (i=1; i<=N; i++)
3639  {
3640    Drel[i+1,N+1+i] = 1;
3641  }
3642  def Ds = nc_algebra(1,Drel);
3643  setring Ds;
3644  kill @Ds;
3645  dbprint(ppl,"// -2-1- The ring D[s] is ready");
3646  dbprint(ppl-1, Ds);
3647  matrix M = imap(save,M);
3648  vector v = var(1)*gen(1);
3649  for (i=1; i<=N; i++)
3650  {
3651    v = v + var(i+1+N)*gen(i+1); //[s,_Dx]
3652  }
3653  ideal J = transpose(M)*v;
3654  kill M,v;
3655  dbprint(ppl,"// -2-2- Compute part of Ann(F^s)");
3656  dbprint(ppl-1, J);
3657  J = engine(J,eng);
3658  dbprint(ppl,"// -2-3- GB computation finished");
3659  dbprint(ppl-1, J);
3660  // ----- step 3: the full annihilator
3661  // ----- create D<t,s>
3662  setring save;
3663  Nnew = 2*N+2;
3664  list L, Lord;
3665  // ----- keep char, minpoly
3666  L[1] = RL[1];
3667  L[4] = RL[4];
3668  // ----- create vars
3669  string newVar@t = safeVarName("t");
3670  L[2] = list(newVar@t,newVar@s) + DName + Name;
3671  // ----- create ordering for elimination of t
3672  // block ord (lp(2),dp);
3673  iv = 1,1;    Lord[1] = list("lp",iv);
3674  iv = 1:Nnew; Lord[2] = list("dp",iv);
3675  iv = 0;      Lord[3] = list("C",iv);
3676  L[3] = Lord;
3677  def @Dts = ring(L);
3678  kill RL,L,Lord,Name,DName,newVar@s,newVar@t;
3679  setring @Dts;
3680  // ----- create nc relations
3681  matrix Drel[Nnew][Nnew];
3682  Drel[1,2] = var(1);
3683  for(i=1; i<=N; i++)
3684  {
3685    Drel[2+i,N+2+i]=-1;
3686  }
3687  def Dts = nc_algebra(1,Drel);
3688  setring Dts;
3689  kill @Dts;
3690  dbprint(ppl,"// -3-1- The ring D<t,s> is ready");
3691  dbprint(ppl-1, Dts);
3692  // ----- create the ideal I following BM
3693  poly  F = imap(save,F);
3694  ideal I = var(1)*F + var(2); // = t*F + s
3695  poly p;
3696  for(i=1; i<=N; i++)
3697  {
3698    p = var(1)*diff(F,var(N+2+i)) + var(2+i); // = t*F_i + D_i
3699    I[i+1] = p;
3700  }
3701  // ----- add already computed part to it
3702  ideal MM = var(2);      // s
3703  for (i=1; i<=N; i++)
3704  {
3705    MM[1+i] = var(2+N+i); // _x
3706    MM[1+N+i] = var(2+i); // _Dx
3707  }
3708  map Ds2Dts = Ds,MM;
3709  ideal J = Ds2Dts(J);
3710  attrib(J,"isSB",1);
3711  kill MM,Ds2Dts;
3712  // ----- start the elimination
3713  dbprint(ppl,"// -3-2- Starting the elimination of t in D<t,s>");
3714  dbprint(ppl-1, I);
3715  if (stdsum || eng <> 0)
3716  {
3717    I = std(J,I);
3718  }
3719  else
3720  {
3721    I = J,I;
3722    I = engine(I,eng);
3723  }
3724  kill J;
3725  I = nselect(I,1);
3726  dbprint(ppl,"// -3-3- t is eliminated");
3727  dbprint(ppl-1, I);  // I is without t
3728  // ----- step 4: add F
3729  // ----- back to D[s]
3730  setring Ds;
3731  ideal MM = 0,var(1);      // 0,s
3732  for (i=1; i<=N; i++)
3733  {
3734    MM[2+i]   = var(1+N+i); // _Dx
3735    MM[2+N+i] = var(1+i);   // _x
3736  }
3737  map Dts2Ds = Dts, MM;
3738  ideal LD = Dts2Ds(I);
3739  kill J,Dts,Dts2Ds,MM;
3740  dbprint(ppl,"// -4-1- Starting cosmetic Groebner computation");
3741  LD = engine(LD,eng);
3742  dbprint(ppl,"// -4-2- Finished cosmetic Groebner computation");
3743  dbprint(ppl-1, LD);
3744  // ----- use reduction trick as Macaulay2 does: compute b(s)/(s+1) by adding all partial derivations also
3745  ideal J;
3746  if (addPD)
3747  {
3748    setring @RM;
3749    poly F = imap(save,F);
3750    ideal J = jacob(F);
3751    J = F,J;
3752    dbprint(ppl,"// -4-2-1- Start GB computation <f, f_i>");
3753    J = engine(J,eng);
3754    dbprint(ppl,"// -4-2-2- Finished GB computation <f, f_i>");
3755    dbprint(ppl-1, J);
3756    setring Ds;
3757    J = imap(@RM,J);
3758    attrib(J,"isSB",1);
3759    dbprint(ppl,"// -4-3- Start GB computations for Ann f^s + <f, f_i>");
3760  }
3761  else
3762  {
3763    J = imap(save,F);
3764    dbprint(ppl,"// -4-3- Start GB computations for Ann f^s + <f>");
3765  }
3766  kill @RM;
3767  // ----- the really hard part
3768  if (stdsum || eng <> 0)
3769  {
3770    LD = std(LD,J);
3771  }
3772  else
3773  {
3774    LD = LD,J;
3775    LD = engine(LD,eng);
3776  }
3777  if (addPD) { dbprint(ppl,"// -4-4- Finished GB computations for Ann f^s + <f, f_i>"); }
3778  else       { dbprint(ppl,"// -4-4- Finished GB computations for Ann f^s + <f>"); }
3779  dbprint(ppl-1, LD);
3780  export LD;
3781  return(Ds);
3782}
3783example
3784{
3785  "EXAMPLE:"; echo = 2;
3786  ring r = 0,(x,y,z,w),Dp;
3787  poly F = x^3+y^3+z^3*w;
3788  // compute Ann(F^s)+<F> using slimgb only
3789  def A = SannfsBFCT(F);
3790  setring A; A;
3791  LD;
3792  // the Bernstein-Sato poly of F:
3793  vec2poly(pIntersect(s,LD));
3794  // a fancier example:
3795  def R = reiffen(4,5); setring R;
3796  RC; // the Reiffen curve in 4,5
3797  // compute Ann(RC^s)+<RC,diff(RC,x),diff(RC,y)>
3798  // using std for GB computations of ideals <I+J>
3799  // where I is already a GB of <I>
3800  // and slimgb for other ideals
3801  def B = SannfsBFCT(RC,1,0,1);
3802  setring B;
3803  // the Bernstein-Sato poly of RC:
3804  (s-1)*vec2poly(pIntersect(s,LD));
3805}
3806
3807
3808proc SannfsBFCTstd(poly F, list #)
3809"USAGE:  SannfsBFCTstd(f [,eng]);  f a poly, eng an optional int
3810RETURN:  ring
3811PURPOSE: compute Ann f^s and Groebner basis of Ann f^s+f in D[s]
3812NOTE:    activate the output ring with the @code{setring} command.
3813@*    This procedure, unlike SannfsBM, returns a ring with the degrevlex
3814@*    ordering in all variables.
3815@*    In the ring D[s], the ideal LD (which IS a Groebner basis) is the needed ideal.
3816@*    In this procedure @code{std} is used for Groebner basis computations.
3817DISPLAY: If printlevel=1, progress debug messages will be printed,
3818@*       if printlevel>=2, all the debug messages will be printed.
3819EXAMPLE: example SannfsBFCTstd; shows examples
3820"
3821{
3822  // DEBUG INFO: ordering on the output ring = dp,
3823  // use std(K,F); for reusing the std property of K
3824
3825  int eng = 0;
3826  if ( size(#)>0 )
3827  {
3828    if ( typeof(#[1]) == "int" )
3829    {
3830      eng = int(#[1]);
3831    }
3832  }
3833  // returns a list with a ring and an ideal LD in it
3834  int ppl = printlevel-voice+2;
3835  //  printf("plevel :%s, voice: %s",printlevel,voice);
3836  def save = basering;
3837  int N = nvars(basering);
3838  int Nnew = 2*N+2;
3839  int i,j;
3840  string s;
3841  list RL = ringlist(basering);
3842  list L, Lord;
3843  list tmp;
3844  intvec iv;
3845  L[1] = RL[1]; // char
3846  L[4] = RL[4]; // char, minpoly
3847  // check whether vars have admissible names
3848  list Name  = RL[2];
3849  list RName;
3850  RName[1] = "@t";
3851  RName[2] = "@s";
3852  for(i=1;i<=N;i++)
3853  {
3854    for(j=1; j<=size(RName);j++)
3855    {
3856      if (Name[i] == RName[j])
3857      {
3858        ERROR("Variable names should not include @t,@s");
3859      }
3860    }
3861  }
3862  // now, create the names for new vars
3863  list DName;
3864  for(i=1;i<=N;i++)
3865  {
3866    DName[i] = "D"+Name[i]; // concat
3867  }
3868  tmp[1] = "t";
3869  tmp[2] = "s";
3870  list NName = tmp + DName + Name ;
3871  L[2]   = NName;
3872  // Name, Dname will be used further
3873  kill NName;
3874  // block ord (lp(2),dp);
3875  tmp[1]  = "lp"; // string
3876  iv      = 1,1;
3877  tmp[2]  = iv; //intvec
3878  Lord[1] = tmp;
3879  // continue with dp 1,1,1,1...
3880  tmp[1]  = "dp"; // string
3881  s       = "iv=";
3882  for(i=1;i<=Nnew;i++)
3883  {
3884    s = s+"1,";
3885  }
3886  s[size(s)]= ";";
3887  execute(s);
3888  kill s;
3889  tmp[2]    = iv;
3890  Lord[2]   = tmp;
3891  tmp[1]    = "C";
3892  iv        = 0;
3893  tmp[2]    = iv;
3894  Lord[3]   = tmp;
3895  tmp       = 0;
3896  L[3]      = Lord;
3897  // we are done with the list
3898  def @R@ = ring(L);
3899  setring @R@;
3900  matrix @D[Nnew][Nnew];
3901  @D[1,2]=t;
3902  for(i=1; i<=N; i++)
3903  {
3904    @D[2+i,N+2+i]=-1;
3905  }
3906  //  L[5] = matrix(UpOneMatrix(Nnew));
3907  //  L[6] = @D;
3908  def @R = nc_algebra(1,@D);
3909  setring @R;
3910  kill @R@;
3911  dbprint(ppl,"// -1-1- the ring @R(t,s,_Dx,_x) is ready");
3912  dbprint(ppl-1, @R);
3913  // create the ideal I
3914  poly  F = imap(save,F);
3915  ideal I = t*F+s;
3916  poly p;
3917  for(i=1; i<=N; i++)
3918  {
3919    p = t; // t
3920    p = diff(F,var(N+2+i))*p;
3921    I = I, var(2+i) + p;
3922  }
3923  // -------- the ideal I is ready ----------
3924  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
3925  dbprint(ppl-1, I);
3926  ideal J = engine(I,eng);
3927  ideal K = nselect(J,1);
3928  dbprint(ppl,"// -1-3- t is eliminated");
3929  dbprint(ppl-1, K);  // K is without t
3930  K = engine(K,eng);  // std does the job too
3931  // now, we must change the ordering
3932  // and create a ring without t
3933  //  setring S;
3934  // ----------- the ring @R3 ------------
3935  // _Dx,_x,s;  +fast ord !
3936  // keep: N, i,j,s, tmp, RL
3937  Nnew = 2*N+1;
3938  kill Lord, tmp, iv, RName;
3939  list Lord, tmp;
3940  intvec iv;
3941  list L=imap(save,L);
3942  list RL=imap(save,RL);
3943  L[1] = RL[1];
3944  L[4] = RL[4];  // char, minpoly
3945  // check whether vars hava admissible names -> done earlier
3946  // now, create the names for new var
3947  tmp[1] = "s";
3948  // DName is defined earlier
3949  list NName = DName + Name + tmp;
3950  L[2] = NName;
3951  tmp = 0;
3952  // just dp
3953  // block ord (dp(N),dp);
3954  string s = "iv=";
3955  for (i=1; i<=Nnew; i++)
3956  {
3957    s = s+"1,";
3958  }
3959  s[size(s)]=";";
3960  execute(s);
3961  tmp[1] = "dp";  // string
3962  tmp[2] = iv;   // intvec
3963  Lord[1] = tmp;
3964  kill s;
3965  kill NName;
3966  tmp[1]      = "C";
3967  Lord[2]     = tmp;  tmp = 0;
3968  L[3]        = Lord;
3969  // we are done with the list. Now add a Plural part
3970  def @R2@ = ring(L);
3971  setring @R2@;
3972  matrix @D[Nnew][Nnew];
3973  for (i=1; i<=N; i++)
3974  {
3975    @D[i,N+i]=-1;
3976  }
3977  def @R2 = nc_algebra(1,@D);
3978  setring @R2;
3979  kill @R2@;
3980  dbprint(ppl,"//  -2-1- the ring @R2(_Dx,_x,s) is ready");
3981  dbprint(ppl-1, @R2);
3982  ideal MM = maxideal(1);
3983  MM = 0,s,MM;
3984  map R01 = @R, MM;
3985  ideal K = R01(K);
3986  // total cleanup
3987  poly F = imap(save, F);
3988  //  ideal LD = K,F;
3989  dbprint(ppl,"//  -2-2- start GB computations for Ann f^s + f");
3990  //  dbprint(ppl-1, LD);
3991  ideal LD = std(K,F);
3992  //  LD = engine(LD,eng);
3993  dbprint(ppl,"//  -2-3- finished GB computations for Ann f^s + f");
3994  dbprint(ppl-1, LD);
3995  // make leadcoeffs positive
3996  for (i=1; i<= ncols(LD); i++)
3997  {
3998    if (leadcoef(LD[i]) <0 )
3999    {
4000      LD[i] = -LD[i];
4001    }
4002  }
4003  export LD;
4004  kill @R;
4005  return(@R2);
4006}
4007example
4008{
4009  "EXAMPLE:"; echo = 2;
4010  ring r = 0,(x,y,z,w),Dp;
4011  poly F = x^3+y^3+z^3*w;
4012  printlevel = 0;
4013  def A = SannfsBFCT(F); setring A;
4014  intvec v = 1,2,3,4,5,6,7,8;
4015  // are there polynomials, depending on s only?
4016  nselect(LD,v);
4017  // a fancier example:
4018  def R = reiffen(4,5); setring R;
4019  v = 1,2,3,4;
4020  RC; // the Reiffen curve in 4,5
4021  def B = SannfsBFCT(RC);
4022  setring B;
4023  // Are there polynomials, depending on s only?
4024  nselect(LD,v);
4025  // It is not the case. Are there leading monomials in s only?
4026  nselect(lead(LD),v);
4027}
4028
4029// use a finer ordering
4030
4031proc SannfsLOT(poly F, list #)
4032"USAGE:  SannfsLOT(f [,eng]);  f a poly, eng an optional int
4033RETURN:  ring
4034PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the
4035@* Levandovskyy's modification of the algorithm by Oaku and Takayama in D[s]
4036NOTE:    activate the output ring with the @code{setring} command.
4037@*    In the ring D[s], the ideal LD (which is NOT a Groebner basis) is
4038@*    the needed D-module structure.
4039@*    If eng <>0, @code{std} is used for Groebner basis computations,
4040@*    otherwise, and by default @code{slimgb} is used.
4041@*    If printlevel=1, progress debug messages will be printed,
4042@*    if printlevel>=2, all the debug messages will be printed.
4043EXAMPLE: example SannfsLOT; shows examples
4044"
4045{
4046  int eng = 0;
4047  if ( size(#)>0 )
4048  {
4049    if ( typeof(#[1]) == "int" )
4050    {
4051      eng = int(#[1]);
4052    }
4053  }
4054  // returns a list with a ring and an ideal LD in it
4055  int ppl = printlevel-voice+2;
4056  //  printf("plevel :%s, voice: %s",printlevel,voice);
4057  def save = basering;
4058  int N = nvars(basering);
4059  //  int Nnew = 2*(N+2);
4060  int Nnew = 2*(N+1)+1; //removed u,v; added s
4061  int i,j;
4062  string s;
4063  list RL = ringlist(basering);
4064  list L, Lord;
4065  list tmp;
4066  intvec iv;
4067  L[1] = RL[1]; // char
4068  L[4] = RL[4]; // char, minpoly
4069  // check whether vars have admissible names
4070  list Name  = RL[2];
4071  list RName;
4072//   RName[1] = "u";
4073//   RName[2] = "v";
4074  RName[1] = "t";
4075  RName[2] = "Dt";
4076  for(i=1;i<=N;i++)
4077  {
4078    for(j=1; j<=size(RName);j++)
4079    {
4080      if (Name[i] == RName[j])
4081      {
4082        ERROR("Variable names should not include t,Dt");
4083      }
4084    }
4085  }
4086  // now, create the names for new vars
4087//   tmp[1]     = "u";
4088//   tmp[2]     = "v";
4089//   list UName = tmp;
4090  list DName;
4091  for(i=1;i<=N;i++)
4092  {
4093    DName[i] = "D"+Name[i]; // concat
4094  }
4095  tmp    =  0;
4096  tmp[1] = "t";
4097  tmp[2] = "Dt";
4098  list SName ; SName[1] = "s";
4099  //  list NName = tmp + Name + DName + SName;
4100  list NName = tmp + SName + Name + DName;
4101  L[2]   = NName;
4102  tmp    = 0;
4103  // Name, Dname will be used further
4104  //  kill UName;
4105  kill NName;
4106  // block ord (a(1,1),dp);
4107  tmp[1]  = "a"; // string
4108  iv      = 1,1;
4109  tmp[2]  = iv; //intvec
4110  Lord[1] = tmp;
4111  // continue with a(0,0,1)
4112  tmp[1]  = "a"; // string
4113  iv      = 0,0,1;
4114  tmp[2]  = iv; //intvec
4115  Lord[2] = tmp;
4116  // continue with dp 1,1,1,1...
4117  tmp[1]  = "dp"; // string
4118  s       = "iv=";
4119  for(i=1;i<=Nnew;i++)
4120  {
4121    s = s+"1,";
4122  }
4123  s[size(s)]= ";";
4124  execute(s);
4125  tmp[2]    = iv;
4126  Lord[3]   = tmp;
4127  tmp[1]    = "C";
4128  iv        = 0;
4129  tmp[2]    = iv;
4130  Lord[4]   = tmp;
4131  tmp       = 0;
4132  L[3]      = Lord;
4133  // we are done with the list
4134  def @R@ = ring(L);
4135  setring @R@;
4136  matrix @D[Nnew][Nnew];
4137  @D[1,2]=1;
4138  for(i=1; i<=N; i++)
4139  {
4140    @D[3+i,N+3+i]=1;
4141  }
4142  // ADD [s,t]=-t, [s,Dt]=Dt
4143  @D[1,3] = -var(1);
4144  @D[2,3] = var(2);
4145  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
4146  //  L[5] = matrix(UpOneMatrix(Nnew));
4147  //  L[6] = @D;
4148  def @R = nc_algebra(1,@D);
4149  setring @R;
4150  kill @R@;
4151  dbprint(ppl,"// -1-1- the ring @R(t,Dt,s,_x,_Dx) is ready");
4152  dbprint(ppl-1, @R);
4153  // create the ideal I
4154  poly  F = imap(save,F);
4155  //  ideal I = u*F-t,u*v-1;
4156  ideal I = F-t;
4157  poly p;
4158  for(i=1; i<=N; i++)
4159  {
4160    //    p = u*Dt; // u*Dt
4161    p = Dt;
4162    p = diff(F,var(3+i))*p;
4163    I = I, var(N+3+i) + p;
4164  }
4165  //  I = I, var(1)*var(2) + var(Nnew) +1; // reduce it with t-f!!!
4166  // t*Dt + s +1 reduced with t-f gives f*Dt + s
4167  I = I, F*var(2) + var(3);
4168  // -------- the ideal I is ready ----------
4169  dbprint(ppl,"// -1-2- starting the elimination of t,Dt in @R");
4170  dbprint(ppl-1, I);
4171  ideal J = engine(I,eng);
4172  ideal K = nselect(J,1..2);
4173  dbprint(ppl,"// -1-3- t,Dt are eliminated");
4174  dbprint(ppl-1, K);  // K is without t, Dt
4175  K = engine(K,eng);  // std does the job too
4176  // now, we must change the ordering
4177  // and create a ring without t, Dt
4178  setring save;
4179  // ----------- the ring @R3 ------------
4180  // _x, _Dx,s;  elim.ord for _x,_Dx.
4181  // keep: N, i,j,s, tmp, RL
4182  Nnew = 2*N+1;
4183  kill Lord, tmp, iv, RName;
4184  list Lord, tmp;
4185  intvec iv;
4186  L[1] = RL[1];
4187  L[4] = RL[4];  // char, minpoly
4188  // check whether vars hava admissible names -> done earlier
4189  // now, create the names for new var
4190  tmp[1] = "s";
4191  // DName is defined earlier
4192  list NName = Name + DName + tmp;
4193  L[2] = NName;
4194  tmp = 0;
4195  // block ord (dp(N),dp);
4196  // string s is already defined
4197  s = "iv=";
4198  for (i=1; i<=Nnew-1; i++)
4199  {
4200    s = s+"1,";
4201  }
4202  s[size(s)]=";";
4203  execute(s);
4204  tmp[1] = "dp";  // string
4205  tmp[2] = iv;   // intvec
4206  Lord[1] = tmp;
4207  // continue with dp 1,1,1,1...
4208  tmp[1] = "dp";  // string
4209  s[size(s)] = ",";
4210  s = s+"1;";
4211  execute(s);
4212  kill s;
4213  kill NName;
4214  tmp[2]      = iv;
4215  Lord[2]     = tmp;
4216  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
4217  Lord[3]     = tmp;  tmp = 0;
4218  L[3]        = Lord;
4219  // we are done with the list. Now add a Plural part
4220  def @R2@ = ring(L);
4221  setring @R2@;
4222  matrix @D[Nnew][Nnew];
4223  for (i=1; i<=N; i++)
4224  {
4225    @D[i,N+i]=1;
4226  }
4227  def @R2 = nc_algebra(1,@D);
4228  setring @R2;
4229  kill @R2@;
4230  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
4231  dbprint(ppl-1, @R2);
4232  ideal MM = maxideal(1);
4233  //  MM = 0,s,MM;
4234  MM = 0,0,s,MM[1..size(MM)-1];
4235  map R01 = @R, MM;
4236  ideal K = R01(K);
4237  // total cleanup
4238  ideal LD = K;
4239  // make leadcoeffs positive
4240  for (i=1; i<= ncols(LD); i++)
4241  {
4242    if (leadcoef(LD[i]) <0 )
4243    {
4244      LD[i] = -LD[i];
4245    }
4246  }
4247  export LD;
4248  kill @R;
4249  return(@R2);
4250}
4251example
4252{
4253  "EXAMPLE:"; echo = 2;
4254  ring r = 0,(x,y,z),Dp;
4255  poly F = x^3+y^3+z^3;
4256  printlevel = 0;
4257  def A  = SannfsLOT(F);
4258  setring A;
4259  LD;
4260}
4261
4262/*
4263proc SannfsLOTold(poly F, list #)
4264"USAGE:  SannfsLOT(f [,eng]);  f a poly, eng an optional int
4265RETURN:  ring
4266PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the Levandovskyy's modification of the algorithm by Oaku and Takayama in the ring D[s], where D is the Weyl algebra
4267NOTE:    activate the output ring with the @code{setring} command.
4268@*       In the ring D[s], the ideal LD (which is NOT a Groebner basis) is the needed D-module structure.
4269@*       If eng <>0, @code{std} is used for Groebner basis computations,
4270@*       otherwise, and by default @code{slimgb} is used.
4271@*       If printlevel=1, progress debug messages will be printed,
4272@*       if printlevel>=2, all the debug messages will be printed.
4273EXAMPLE: example SannfsLOT; shows examples
4274"
4275{
4276  int eng = 0;
4277  if ( size(#)>0 )
4278  {
4279    if ( typeof(#[1]) == "int" )
4280    {
4281      eng = int(#[1]);
4282    }
4283  }
4284  // returns a list with a ring and an ideal LD in it
4285  int ppl = printlevel-voice+2;
4286  //  printf("plevel :%s, voice: %s",printlevel,voice);
4287  def save = basering;
4288  int N = nvars(basering);
4289  //  int Nnew = 2*(N+2);
4290  int Nnew = 2*(N+1)+1; //removed u,v; added s
4291  int i,j;
4292  string s;
4293  list RL = ringlist(basering);
4294  list L, Lord;
4295  list tmp;
4296  intvec iv;
4297  L[1] = RL[1]; // char
4298  L[4] = RL[4]; // char, minpoly
4299  // check whether vars have admissible names
4300  list Name  = RL[2];
4301  list RName;
4302//   RName[1] = "u";
4303//   RName[2] = "v";
4304  RName[1] = "t";
4305  RName[2] = "Dt";
4306  for(i=1;i<=N;i++)
4307  {
4308    for(j=1; j<=size(RName);j++)
4309    {
4310      if (Name[i] == RName[j])
4311      {
4312        ERROR("Variable names should not include t,Dt");
4313      }
4314    }
4315  }
4316  // now, create the names for new vars
4317//   tmp[1]     = "u";
4318//   tmp[2]     = "v";
4319//   list UName = tmp;
4320  list DName;
4321  for(i=1;i<=N;i++)
4322  {
4323    DName[i] = "D"+Name[i]; // concat
4324  }
4325  tmp    =  0;
4326  tmp[1] = "t";
4327  tmp[2] = "Dt";
4328  list SName ; SName[1] = "s";
4329  //  list NName = UName +  tmp + Name + DName;
4330  list NName = tmp + Name + DName + SName;
4331  L[2]   = NName;
4332  tmp    = 0;
4333  // Name, Dname will be used further
4334  //  kill UName;
4335  kill NName;
4336  // block ord (a(1,1),dp);
4337  tmp[1]  = "a"; // string
4338  iv      = 1,1;
4339  tmp[2]  = iv; //intvec
4340  Lord[1] = tmp;
4341  // continue with dp 1,1,1,1...
4342  tmp[1]  = "dp"; // string
4343  s       = "iv=";
4344  for(i=1;i<=Nnew;i++)
4345  {
4346    s = s+"1,";
4347  }
4348  s[size(s)]= ";";
4349  execute(s);
4350  tmp[2]    = iv;
4351  Lord[2]   = tmp;
4352  tmp[1]    = "C";
4353  iv        = 0;
4354  tmp[2]    = iv;
4355  Lord[3]   = tmp;
4356  tmp       = 0;
4357  L[3]      = Lord;
4358  // we are done with the list
4359  def @R@ = ring(L);
4360  setring @R@;
4361  matrix @D[Nnew][Nnew];
4362  @D[1,2]=1;
4363  for(i=1; i<=N; i++)
4364  {
4365    @D[2+i,N+2+i]=1;
4366  }
4367  // ADD [s,t]=-t, [s,Dt]=Dt
4368  @D[1,Nnew] = -var(1);
4369  @D[2,Nnew] = var(2);
4370  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
4371  //  L[5] = matrix(UpOneMatrix(Nnew));
4372  //  L[6] = @D;
4373  def @R = nc_algebra(1,@D);
4374  setring @R;
4375  kill @R@;
4376  dbprint(ppl,"// -1-1- the ring @R(t,Dt,_x,_Dx,s) is ready");
4377  dbprint(ppl-1, @R);
4378  // create the ideal I
4379  poly  F = imap(save,F);
4380  //  ideal I = u*F-t,u*v-1;
4381  ideal I = F-t;
4382  poly p;
4383  for(i=1; i<=N; i++)
4384  {
4385    //    p = u*Dt; // u*Dt
4386    p = Dt;
4387    p = diff(F,var(2+i))*p;
4388    I = I, var(N+2+i) + p;
4389  }
4390  //  I = I, var(1)*var(2) + var(Nnew) +1; // reduce it with t-f!!!
4391  // t*Dt + s +1 reduced with t-f gives f*Dt + s
4392  I = I, F*var(2) + var(Nnew);
4393  // -------- the ideal I is ready ----------
4394  dbprint(ppl,"// -1-2- starting the elimination of t,Dt in @R");
4395  dbprint(ppl-1, I);
4396  ideal J = engine(I,eng);
4397  ideal K = nselect(J,1..2);
4398  dbprint(ppl,"// -1-3- t,Dt are eliminated");
4399  dbprint(ppl-1, K);  // K is without t, Dt
4400  K = engine(K,eng);  // std does the job too
4401  // now, we must change the ordering
4402  // and create a ring without t, Dt
4403  setring save;
4404  // ----------- the ring @R3 ------------
4405  // _x, _Dx,s;  elim.ord for _x,_Dx.
4406  // keep: N, i,j,s, tmp, RL
4407  Nnew = 2*N+1;
4408  kill Lord, tmp, iv, RName;
4409  list Lord, tmp;
4410  intvec iv;
4411  L[1] = RL[1];
4412  L[4] = RL[4];  // char, minpoly
4413  // check whether vars hava admissible names -> done earlier
4414  // now, create the names for new var
4415  tmp[1] = "s";
4416  // DName is defined earlier
4417  list NName = Name + DName + tmp;
4418  L[2] = NName;
4419  tmp = 0;
4420  // block ord (dp(N),dp);
4421  // string s is already defined
4422  s = "iv=";
4423  for (i=1; i<=Nnew-1; i++)
4424  {
4425    s = s+"1,";
4426  }
4427  s[size(s)]=";";
4428  execute(s);
4429  tmp[1] = "dp";  // string
4430  tmp[2] = iv;   // intvec
4431  Lord[1] = tmp;
4432  // continue with dp 1,1,1,1...
4433  tmp[1] = "dp";  // string
4434  s[size(s)] = ",";
4435  s = s+"1;";
4436  execute(s);
4437  kill s;
4438  kill NName;
4439  tmp[2]      = iv;
4440  Lord[2]     = tmp;
4441  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
4442  Lord[3]     = tmp;  tmp = 0;
4443  L[3]        = Lord;
4444  // we are done with the list. Now add a Plural part
4445  def @R2@ = ring(L);
4446  setring @R2@;
4447  matrix @D[Nnew][Nnew];
4448  for (i=1; i<=N; i++)
4449  {
4450    @D[i,N+i]=1;
4451  }
4452  def @R2 = nc_algebra(1,@D);
4453  setring @R2;
4454  kill @R2@;
4455  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
4456  dbprint(ppl-1, @R2);
4457  ideal MM = maxideal(1);
4458  MM = 0,s,MM;
4459  map R01 = @R, MM;
4460  ideal K = R01(K);
4461  // total cleanup
4462  ideal LD = K;
4463  // make leadcoeffs positive
4464  for (i=1; i<= ncols(LD); i++)
4465  {
4466    if (leadcoef(LD[i]) <0 )
4467    {
4468      LD[i] = -LD[i];
4469    }
4470  }
4471  export LD;
4472  kill @R;
4473  return(@R2);
4474}
4475example
4476{
4477  "EXAMPLE:"; echo = 2;
4478  ring r = 0,(x,y,z),Dp;
4479  poly F = x^3+y^3+z^3;
4480  printlevel = 0;
4481  def A  = SannfsLOTold(F);
4482  setring A;
4483  LD;
4484}
4485
4486*/
4487
4488proc annfsLOT(poly F, list #)
4489"USAGE:  annfsLOT(F [,eng]);  F a poly, eng an optional int
4490RETURN:  ring
4491PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to
4492@* the Levandovskyy's modification of the algorithm by Oaku and Takayama
4493NOTE:    activate the output ring with the @code{setring} command. In this ring,
4494@*  - the ideal LD (which is a Groebner basis) is the needed D-module structure,
4495@*    which is obtained by substituting the minimal integer root of a Bernstein
4496@*    polynomial into the s-parametric ideal;
4497@*  - the list BS contains the roots with multiplicities of BS polynomial of f.
4498@*    If eng <>0, @code{std} is used for Groebner basis computations,
4499@*    otherwise and by default @code{slimgb} is used.
4500@*    If printlevel=1, progress debug messages will be printed,
4501@*    if printlevel>=2, all the debug messages will be printed.
4502EXAMPLE: example annfsLOT; shows examples
4503"
4504{
4505  int eng = 0;
4506  if ( size(#)>0 )
4507  {
4508    if ( typeof(#[1]) == "int" )
4509    {
4510      eng = int(#[1]);
4511    }
4512  }
4513  printlevel=printlevel+1;
4514  def save = basering;
4515  def @A = SannfsLOT(F,eng);
4516  setring @A;
4517  poly F = imap(save,F);
4518  def B  = annfs0(LD,F,eng);
4519  return(B);
4520}
4521example
4522{
4523  "EXAMPLE:"; echo = 2;
4524  ring r = 0,(x,y,z),Dp;
4525  poly F = z*x^2+y^3;
4526  printlevel = 0;
4527  def A  = annfsLOT(F);
4528  setring A;
4529  LD;
4530  BS;
4531}
4532
4533proc annfs0(ideal I, poly F, list #)
4534"USAGE:  annfs0(I, F [,eng]);  I an ideal, F a poly, eng an optional int
4535RETURN:  ring
4536PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra, based
4537@* on the output of Sannfs-like procedure
4538NOTE:    activate the output ring with the @code{setring} command. In this ring,
4539@* - the ideal LD (which is a Groebner basis) is the annihilator of f^s,
4540@* - the list BS contains the roots with multiplicities of BS polynomial of f.
4541@*  If eng <>0, @code{std} is used for Groebner basis computations,
4542@*  otherwise and by default @code{slimgb} is used.
4543@*  If printlevel=1, progress debug messages will be printed,
4544@*  if printlevel>=2, all the debug messages will be printed.
4545EXAMPLE: example annfs0; shows examples
4546"
4547{
4548  int eng = 0;
4549  if ( size(#)>0 )
4550  {
4551    if ( typeof(#[1]) == "int" )
4552    {
4553      eng = int(#[1]);
4554    }
4555  }
4556  def @R2 = basering;
4557  // we're in D_n[s], where the elim ord for s is set
4558  ideal J = NF(I,std(F));
4559  // make leadcoeffs positive
4560  int i;
4561  for (i=1; i<= ncols(J); i++)
4562  {
4563    if (leadcoef(J[i]) <0 )
4564    {
4565      J[i] = -J[i];
4566    }
4567  }
4568  J = J,F;
4569  ideal M = engine(J,eng);
4570  int Nnew = nvars(@R2);
4571  ideal K2 = nselect(M,1..Nnew-1);
4572  int ppl = printlevel-voice+2;
4573  dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering");
4574  dbprint(ppl-1, K2);
4575  // the ring @R3 and the search for minimal negative int s
4576  ring @R3 = 0,s,dp;
4577  dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready");
4578  ideal K3 = imap(@R2,K2);
4579  poly p = K3[1];
4580  dbprint(ppl,"// -2-2- factorization");
4581  //  ideal P = factorize(p,1);  //without constants and multiplicities
4582  //  "--------- b-function factorizes into ---------";   P;
4583  // convert factors to the list of their roots with mults
4584  // assume all factors are linear
4585  //  ideal BS = normalize(P);
4586  //  BS = subst(BS,s,0);
4587  //  BS = -BS;
4588  list P = factorize(p);          //with constants and multiplicities
4589  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
4590  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
4591  {
4592    bs[i-1] = P[1][i];
4593    m[i-1]  = P[2][i];
4594  }
4595  int sP = minIntRoot(bs,1);
4596  bs =  normalize(bs);
4597  bs = -subst(bs,s,0);
4598  dbprint(ppl,"// -2-3- minimal integer root found");
4599  dbprint(ppl-1, sP);
4600 //TODO: sort BS!
4601  // --------- substitute s found in the ideal ---------
4602  // --------- going back to @R and substitute ---------
4603  setring @R2;
4604  K2 = subst(I,s,sP);
4605  // create the ordinary Weyl algebra and put the result into it,
4606  // thus creating the ring @R5
4607  // keep: N, i,j,s, tmp, RL
4608  Nnew = Nnew - 1; // former 2*N;
4609  // list RL = ringlist(save);  // is defined earlier
4610  //  kill Lord, tmp, iv;
4611  list L = 0;
4612  list Lord, tmp;
4613  intvec iv;
4614  list RL = ringlist(basering);
4615  L[1] = RL[1];
4616  L[4] = RL[4];  //char, minpoly
4617  // check whether vars have admissible names -> done earlier
4618  // list Name = RL[2]M
4619  // DName is defined earlier
4620  list NName; // = RL[2]; // skip the last var 's'
4621  for (i=1; i<=Nnew; i++)
4622  {
4623    NName[i] =  RL[2][i];
4624  }
4625  L[2] = NName;
4626  // dp ordering;
4627  string s = "iv=";
4628  for (i=1; i<=Nnew; i++)
4629  {
4630    s = s+"1,";
4631  }
4632  s[size(s)] = ";";
4633  execute(s);
4634  tmp     = 0;
4635  tmp[1]  = "dp";  // string
4636  tmp[2]  = iv;  // intvec
4637  Lord[1] = tmp;
4638  kill s;
4639  tmp[1]  = "C";
4640  iv = 0;
4641  tmp[2]  = iv;
4642  Lord[2] = tmp;
4643  tmp     = 0;
4644  L[3]    = Lord;
4645  // we are done with the list
4646  // Add: Plural part
4647  def @R4@ = ring(L);
4648  setring @R4@;
4649  int N = Nnew/2;
4650  matrix @D[Nnew][Nnew];
4651  for (i=1; i<=N; i++)
4652  {
4653    @D[i,N+i]=1;
4654  }
4655  def @R4 = nc_algebra(1,@D);
4656  setring @R4;
4657  kill @R4@;
4658  dbprint(ppl,"// -3-1- the ring @R4 is ready");
4659  dbprint(ppl-1, @R4);
4660  ideal K4 = imap(@R2,K2);
4661  option(redSB);
4662  dbprint(ppl,"// -3-2- the final cosmetic std");
4663  K4 = engine(K4,eng);  // std does the job too
4664  // total cleanup
4665  ideal bs = imap(@R3,bs);
4666  kill @R3;
4667  list BS = bs,m;
4668  export BS;
4669  ideal LD = K4;
4670  export LD;
4671  return(@R4);
4672}
4673example
4674{ "EXAMPLE:"; echo = 2;
4675  ring r = 0,(x,y,z),Dp;
4676  poly F = x^3+y^3+z^3;
4677  printlevel = 0;
4678  def A = SannfsBM(F);   setring A;
4679  // alternatively, one can use SannfsOT or SannfsLOT
4680  LD;
4681  poly F = imap(r,F);
4682  def B  = annfs0(LD,F);  setring B;
4683  LD;
4684  BS;
4685}
4686
4687// proc annfsgms(poly F, list #)
4688// "USAGE:  annfsgms(f [,eng]);  f a poly, eng an optional int
4689// ASSUME:  f has an isolated critical point at 0
4690// RETURN:  ring
4691// PURPOSE: compute the D-module structure of basering[1/f]*f^s
4692// NOTE:    activate the output ring with the @code{setring} command. In this ring,
4693// @*       - the ideal LD is the needed D-mod structure,
4694// @*       - the ideal BS is the list of roots of a Bernstein polynomial of f.
4695// @*       If eng <>0, @code{std} is used for Groebner basis computations,
4696// @*       otherwise (and by default) @code{slimgb} is used.
4697// @*       If printlevel=1, progress debug messages will be printed,
4698// @*       if printlevel>=2, all the debug messages will be printed.
4699// EXAMPLE: example annfsgms; shows examples
4700// "
4701// {
4702//   LIB "gmssing.lib";
4703//   int eng = 0;
4704//   if ( size(#)>0 )
4705//   {
4706//     if ( typeof(#[1]) == "int" )
4707//     {
4708//       eng = int(#[1]);
4709//     }
4710//   }
4711//   int ppl = printlevel-voice+2;
4712//   // returns a ring with the ideal LD in it
4713//   def save = basering;
4714//   // compute the Bernstein polynomial from gmssing.lib
4715//   list RL = ringlist(basering);
4716//   // in the descr. of the ordering, replace "p" by "s"
4717//   list NL = convloc(RL);
4718//   // create a ring with the ordering, converted to local
4719//   def @LR = ring(NL);
4720//   setring @LR;
4721//   poly F  = imap(save, F);
4722//   ideal B = bernstein(F)[1];
4723//   // since B may not contain (s+1) [following gmssing.lib]
4724//   // add it!
4725//   B = B,-1;
4726//   B = simplify(B,2+4); // erase zero and repeated entries
4727//   // find the minimal integer value
4728//   int   S = minIntRoot(B,0);
4729//   dbprint(ppl,"// -0- minimal integer root found");
4730//   dbprint(ppl-1,S);
4731//   setring save;
4732//   int N = nvars(basering);
4733//   int Nnew = 2*(N+2);
4734//   int i,j;
4735//   string s;
4736//   //  list RL = ringlist(basering);
4737//   list L, Lord;
4738//   list tmp;
4739//   intvec iv;
4740//   L[1] = RL[1]; // char
4741//   L[4] = RL[4]; // char, minpoly
4742//   // check whether vars have admissible names
4743//   list Name  = RL[2];
4744//   list RName;
4745//   RName[1] = "u";
4746//   RName[2] = "v";
4747//   RName[3] = "t";
4748//   RName[4] = "Dt";
4749//   for(i=1;i<=N;i++)
4750//   {
4751//     for(j=1; j<=size(RName);j++)
4752//     {
4753//       if (Name[i] == RName[j])
4754//       {
4755//         ERROR("Variable names should not include u,v,t,Dt");
4756//       }
4757//     }
4758//   }
4759//   // now, create the names for new vars
4760//   //  tmp[1]     = "u";  tmp[2]     = "v";  tmp[3]     = "t";  tmp[4]     = "Dt";
4761//   list UName = RName;
4762//   list DName;
4763//   for(i=1;i<=N;i++)
4764//   {
4765//     DName[i] = "D"+Name[i]; // concat
4766//   }
4767//   list NName = UName + Name + DName;
4768//   L[2]       = NName;
4769//   tmp        = 0;
4770//   // Name, Dname will be used further
4771//   kill UName;
4772//   kill NName;
4773//   // block ord (a(1,1),dp);
4774//   tmp[1]  = "a"; // string
4775//   iv      = 1,1;
4776//   tmp[2]  = iv; //intvec
4777//   Lord[1] = tmp;
4778//   // continue with dp 1,1,1,1...
4779//   tmp[1]  = "dp"; // string
4780//   s       = "iv=";
4781//   for(i=1; i<=Nnew; i++) // need really all vars!
4782//   {
4783//     s = s+"1,";
4784//   }
4785//   s[size(s)]= ";";
4786//   execute(s);
4787//   tmp[2]    = iv;
4788//   Lord[2]   = tmp;
4789//   tmp[1]    = "C";
4790//   iv        = 0;
4791//   tmp[2]    = iv;
4792//   Lord[3]   = tmp;
4793//   tmp       = 0;
4794//   L[3]      = Lord;
4795//   // we are done with the list
4796//   def @R = ring(L);
4797//   setring @R;
4798//   matrix @D[Nnew][Nnew];
4799//   @D[3,4] = 1; // t,Dt
4800//   for(i=1; i<=N; i++)
4801//   {
4802//     @D[4+i,4+N+i]=1;
4803//   }
4804//   //  L[5] = matrix(UpOneMatrix(Nnew));
4805//   //  L[6] = @D;
4806//   nc_algebra(1,@D);
4807//   dbprint(ppl,"// -1-1- the ring @R is ready");
4808//   dbprint(ppl-1,@R);
4809//   // create the ideal
4810//   poly F  = imap(save,F);
4811//   ideal I = u*F-t,u*v-1;
4812//   poly p;
4813//   for(i=1; i<=N; i++)
4814//   {
4815//     p = u*Dt; // u*Dt
4816//     p = diff(F,var(4+i))*p;
4817//     I = I, var(N+4+i) + p; // Dx, Dy
4818//   }
4819//   // add the relations between t,Dt and s
4820//   //  I = I, t*Dt+1+S;
4821//   // -------- the ideal I is ready ----------
4822//   dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
4823//   ideal J = engine(I,eng);
4824//   ideal K = nselect(J,1..2);
4825//   dbprint(ppl,"// -1-3- u,v are eliminated in @R");
4826//   dbprint(ppl-1,K); // without u,v: not yet our answer
4827//   //----- create a ring with elim.ord for t,Dt -------
4828//   setring save;
4829//   // ------------ new ring @R2 ------------------
4830//   // without u,v and with the elim.ord for t,Dt
4831//   // keep: N, i,j,s, tmp, RL
4832//   Nnew = 2*N+2;
4833//   //  list RL = ringlist(save); // is defined earlier
4834//   kill Lord,tmp,iv, RName;
4835//   L = 0;
4836//   list Lord, tmp;
4837//   intvec iv;
4838//   L[1] = RL[1]; // char
4839//   L[4] = RL[4]; // char, minpoly
4840//   // check whether vars have admissible names -> done earlier
4841//   //  list Name  = RL[2];
4842//   list RName;
4843//   RName[1] = "t";
4844//   RName[2] = "Dt";
4845//   // DName is defined earlier
4846//   list NName = RName + Name + DName;
4847//   L[2]   = NName;
4848//   tmp    = 0;
4849//   // block ord (a(1,1),dp);
4850//   tmp[1]  = "a"; // string
4851//   iv      = 1,1;
4852//   tmp[2]  = iv; //intvec
4853//   Lord[1] = tmp;
4854//   // continue with dp 1,1,1,1...
4855//   tmp[1]  = "dp"; // string
4856//   s       = "iv=";
4857//   for(i=1;i<=Nnew;i++)
4858//   {
4859//     s = s+"1,";
4860//   }
4861//   s[size(s)]= ";";
4862//   execute(s);
4863//   kill s;
4864//   kill NName;
4865//   tmp[2]    = iv;
4866//   Lord[2]   = tmp;
4867//   tmp[1]    = "C";
4868//   iv        = 0;
4869//   tmp[2]    = iv;
4870//   Lord[3]   = tmp;
4871//   tmp       = 0;
4872//   L[3]      = Lord;
4873//   // we are done with the list
4874//   // Add: Plural part
4875//   def @R2 = ring(L);
4876//   setring @R2;
4877//   matrix @D[Nnew][Nnew];
4878//   @D[1,2]=1;
4879//   for(i=1; i<=N; i++)
4880//   {
4881//     @D[2+i,2+N+i]=1;
4882//   }
4883//   nc_algebra(1,@D);
4884//   dbprint(ppl,"// -2-1- the ring @R2 is ready");
4885//   dbprint(ppl-1,@R2);
4886//   ideal MM = maxideal(1);
4887//   MM = 0,0,MM;
4888//   map R01 = @R, MM;
4889//   ideal K2 = R01(K);
4890//   // add the relations between t,Dt and s
4891//   //  K2       = K2, t*Dt+1+S;
4892//   poly G = t*Dt+S+1;
4893//   K2 = NF(K2,std(G)),G;
4894//   dbprint(ppl,"// -2-2- starting elimination for t,Dt in @R2");
4895//   ideal J  = engine(K2,eng);
4896//   ideal K  = nselect(J,1..2);
4897//   dbprint(ppl,"// -2-3- t,Dt are eliminated");
4898//   dbprint(ppl-1,K);
4899//   //  "------- produce a final result --------";
4900//   // ----- create the ordinary Weyl algebra and put
4901//   // ----- the result into it
4902//   // ------ create the ring @R5
4903//   // keep: N, i,j,s, tmp, RL
4904//   setring save;
4905//   Nnew = 2*N;
4906//   //  list RL = ringlist(save); // is defined earlier
4907//   kill Lord, tmp, iv;
4908//   //  kill L;
4909//   L = 0;
4910//   list Lord, tmp;
4911//   intvec iv;
4912//   L[1] = RL[1]; // char
4913//   L[4] = RL[4]; // char, minpoly
4914//   // check whether vars have admissible names -> done earlier
4915//   //  list Name  = RL[2];
4916//   // DName is defined earlier
4917//   list NName = Name + DName;
4918//   L[2]   = NName;
4919//   // dp ordering;
4920//   string   s       = "iv=";
4921//   for(i=1;i<=2*N;i++)
4922//   {
4923//     s = s+"1,";
4924//   }
4925//   s[size(s)]= ";";
4926//   execute(s);
4927//   tmp     = 0;
4928//   tmp[1]  = "dp"; // string
4929//   tmp[2]  = iv; //intvec
4930//   Lord[1] = tmp;
4931//   kill s;
4932//   tmp[1]    = "C";
4933//   iv        = 0;
4934//   tmp[2]    = iv;
4935//   Lord[2]   = tmp;
4936//   tmp       = 0;
4937//   L[3]      = Lord;
4938//   // we are done with the list
4939//   // Add: Plural part
4940//   def @R5 = ring(L);
4941//   setring @R5;
4942//   matrix @D[Nnew][Nnew];
4943//   for(i=1; i<=N; i++)
4944//   {
4945//     @D[i,N+i]=1;
4946//   }
4947//   nc_algebra(1,@D);
4948//   dbprint(ppl,"// -3-1- the ring @R5 is ready");
4949//   dbprint(ppl-1,@R5);
4950//   ideal K5 = imap(@R2,K);
4951//   option(redSB);
4952//   dbprint(ppl,"// -3-2- the final cosmetic std");
4953//   K5 = engine(K5,eng); // std does the job too
4954//   // total cleanup
4955//   kill @R;
4956//   kill @R2;
4957//   ideal LD = K5;
4958//   ideal BS = imap(@LR,B);
4959//   kill @LR;
4960//   export BS;
4961//   export LD;
4962//   return(@R5);
4963// }
4964// example
4965// {
4966//   "EXAMPLE:"; echo = 2;
4967//   ring r = 0,(x,y,z),Dp;
4968//   poly F = x^2+y^3+z^5;
4969//   def A = annfsgms(F);
4970//   setring A;
4971//   LD;
4972//   print(matrix(BS));
4973// }
4974
4975
4976proc convloc(list @NL)
4977"USAGE:  convloc(L); L a list
4978RETURN:  list
4979PURPOSE: convert a ringlist L into another ringlist,
4980@* where all the 'p' orderings are replaced with the 's' orderings, e.g. @code{dp} by @code{ds}.
4981ASSUME: L is a result of a ringlist command
4982EXAMPLE: example convloc; shows examples
4983"
4984{
4985  list NL = @NL;
4986  // given a ringlist, returns a new ringlist,
4987  // where all the p-orderings are replaced with s-ord's
4988  int i,j,k,found;
4989  int nblocks = size(NL[3]);
4990  for(i=1; i<=nblocks; i++)
4991  {
4992    for(j=1; j<=size(NL[3][i]); j++)
4993    {
4994      if (typeof(NL[3][i][j]) == "string" )
4995      {
4996        found = 0;
4997        for (k=1; k<=size(NL[3][i][j]); k++)
4998        {
4999          if (NL[3][i][j][k]=="p")
5000          {
5001            NL[3][i][j][k]="s";
5002            found = 1;
5003            //    printf("replaced at %s,%s,%s",i,j,k);
5004          }
5005        }
5006      }
5007    }
5008  }
5009  return(NL);
5010}
5011example
5012{
5013  "EXAMPLE:"; echo = 2;
5014  ring r = 0,(x,y,z),(Dp(2),dp(1));
5015  list L = ringlist(r);
5016  list N = convloc(L);
5017  def rs = ring(N);
5018  setring rs;
5019  rs;
5020}
5021
5022proc annfspecial(ideal I, poly F, int mir, number n)
5023"USAGE:  annfspecial(I,F,mir,n);  I an ideal, F a poly, int mir, number n
5024RETURN:  ideal
5025PURPOSE: compute the annihilator ideal of F^n in the Weyl Algebra
5026@*           for the given rational number n
5027ASSUME:  The basering is D[s] and contains 's' explicitly as a variable,
5028@*   the ideal I is the Ann F^s in D[s] (obtained with e.g. SannfsBM),
5029@*   the integer 'mir' is the minimal integer root of the BS polynomial of F,
5030@*   and the number n is rational.
5031NOTE: We compute the real annihilator for any rational value of n (both
5032@*       generic and exceptional). The implementation goes along the lines of
5033@*       the Algorithm 5.3.15 from Saito-Sturmfels-Takayama.
5034DISPLAY: If printlevel=1, progress debug messages will be printed,
5035@*       if printlevel>=2, all the debug messages will be printed.
5036EXAMPLE: example annfspecial; shows examples
5037"
5038{
5039
5040  if (!isRational(n))
5041  {
5042    "ERROR: n must be a rational number!";
5043  }
5044  int ppl = printlevel-voice+2;
5045  //  int mir =  minIntRoot(L[1],0);
5046  int ns   = varNum("s");
5047  if (!ns)
5048  {
5049    ERROR("Variable s expected in the ideal AnnFs");
5050  }
5051  int d;
5052  ideal P = subst(I,var(ns),n);
5053  if (denominator(n) == 1)
5054  {
5055    // n is fraction-free
5056    d = int(numerator(n));
5057    if ( (!d) && (n!=0))
5058    {
5059      ERROR("no parametric special values are allowed");
5060    }
5061    d = d - mir;
5062    if (d>0)
5063    {
5064      dbprint(ppl,"// -1-1- starting syzygy computations");
5065      matrix J[1][1] = F^d;
5066      dbprint(ppl-1,"// -1-1-1- of the polynomial ideal");
5067      dbprint(ppl-1,J);
5068      matrix K[1][size(I)] = subst(I,var(ns),mir);
5069      dbprint(ppl-1,"// -1-1-2- modulo ideal:");
5070      dbprint(ppl-1, K);
5071      module M = modulo(J,K);
5072      dbprint(ppl-1,"// -1-1-3- getting the result:");
5073      dbprint(ppl-1, M);
5074      P  = P, ideal(M);
5075      dbprint(ppl,"// -1-2- finished syzygy computations");
5076    }
5077    else
5078    {
5079      dbprint(ppl,"// -1-1- d<=0, no syzygy computations needed");
5080      dbprint(ppl-1,"// -1-2- for d =");
5081      dbprint(ppl-1, d);
5082    }
5083  }
5084  // also the else case: d<=0 or n is not an integer
5085  dbprint(ppl,"// -2-1- starting final Groebner basis");
5086  P = groebner(P);
5087  dbprint(ppl,"// -2-2- finished final Groebner basis");
5088  return(P);
5089}
5090example
5091{
5092  "EXAMPLE:"; echo = 2;
5093  ring r = 0,(x,y),dp;
5094  poly F = x3-y2;
5095  def  B = annfs(F);  setring B;
5096  minIntRoot(BS[1],0);
5097  // So, the minimal integer root is -1
5098  setring r;
5099  def  A = SannfsBM(F);
5100  setring A;
5101  poly F = x3-y2;
5102  annfspecial(LD,F,-1,3/4); // generic root
5103  annfspecial(LD,F,-1,-2);  // integer but still generic root
5104  annfspecial(LD,F,-1,1);   // exceptional root
5105}
5106
5107/*
5108//static proc new_ex_annfspecial()
5109{
5110  //another example for annfspecial: x3+y3+z3
5111  ring r = 0,(x,y,z),dp;
5112  poly F =  x3+y3+z3;
5113  def  B = annfs(F);  setring B;
5114  minIntRoot(BS[1],0);
5115  // So, the minimal integer root is -1
5116  setring r;
5117  def  A = SannfsBM(F);
5118  setring A;
5119  poly F =  x3+y3+z3;
5120  annfspecial(LD,F,-1,3/4); // generic root
5121  annfspecial(LD,F,-1,-2);  // integer but still generic root
5122  annfspecial(LD,F,-1,1);   // exceptional root
5123}
5124*/
5125
5126proc minIntRoot(ideal P, int fact)
5127"USAGE:  minIntRoot(P, fact); P an ideal, fact an int
5128RETURN:  int
5129PURPOSE: minimal integer root of a maximal ideal P
5130NOTE:    if fact==1, P is the result of some 'factorize' call,
5131@*       else P is treated as the result of bernstein::gmssing.lib
5132@*       in both cases without constants and multiplicities
5133EXAMPLE: example minIntRoot; shows examples
5134"
5135{
5136  //    ideal P = factorize(p,1);
5137  // or ideal P = bernstein(F)[1];
5138  intvec vP;
5139  number nP;
5140  int i;
5141  if ( fact )
5142  {
5143    // the result comes from "factorize"
5144    P = normalize(P); // now leadcoef = 1
5145    // TODO: hunt for units and kill then !!!
5146    P = lead(P)-P;
5147    // nP = leadcoef(P[i]-lead(P[i])); // for 1 var only, extract the coeff
5148  }
5149  else
5150  {
5151    // bernstein deletes -1 usually
5152    P = P, -1;
5153  }
5154  // for both situations:
5155  // now we have an ideal of fractions of type "number"
5156  int sP = size(P);
5157  for(i=1; i<=sP; i++)
5158  {
5159    nP = leadcoef(P[i]);
5160    if ( (nP - int(nP)) == 0 )
5161    {
5162      vP = vP,int(nP);
5163    }
5164  }
5165  if ( size(vP)>=2 )
5166  {
5167    vP = vP[2..size(vP)];
5168  }
5169  sP = -Max(-vP);
5170  if (sP == 0)
5171  {
5172    "Warning: zero root present!";
5173  }
5174  return(sP);
5175}
5176example
5177{
5178  "EXAMPLE:"; echo = 2;
5179  ring r   = 0,(x,y),ds;
5180  poly f1  = x*y*(x+y);
5181  ideal I1 = bernstein(f1)[1]; // a local Bernstein poly
5182  I1;
5183  minIntRoot(I1,0);
5184  poly  f2  = x2-y3;
5185  ideal I2  = bernstein(f2)[1];
5186  I2;
5187  minIntRoot(I2,0);
5188  // now we illustrate the behaviour of factorize
5189  // together with a global ordering
5190  ring r2  = 0,x,dp;
5191  poly f3   = 9*(x+2/3)*(x+1)*(x+4/3); //global b-polynomial of f1=x*y*(x+y)
5192  ideal I3 = factorize(f3,1);
5193  I3;
5194  minIntRoot(I3,1);
5195  // and a more interesting situation
5196  ring  s  = 0,(x,y,z),ds;
5197  poly  f  = x3 + y3 + z3;
5198  ideal I  = bernstein(f)[1];
5199  I;
5200  minIntRoot(I,0);
5201}
5202
5203proc isHolonomic(def M)
5204"USAGE:  isHolonomic(M); M an ideal/module/matrix
5205RETURN:  int, 1 if M is holonomic over the base ring, and 0 otherwise
5206ASSUME: basering is a Weyl algebra in characteristic 0
5207PURPOSE: check whether M is holonomic over the base ring
5208NOTE:    M is holonomic if 2*dim(M) = dim(R), where R is the
5209base ring; dim stays for Gelfand-Kirillov dimension
5210EXAMPLE: example isHolonomic; shows examples
5211"
5212{
5213  if (dmodappassumeViolation())
5214  {
5215    ERROR("Basering is inappropriate: characteristic>0 or qring present");
5216  }
5217  if (!isWeyl(basering))
5218  {
5219    ERROR("Basering is not a Weyl algebra");
5220  }
5221
5222  if ( (typeof(M) != "ideal") && (typeof(M) != "module") && (typeof(M) != "matrix") )
5223  {
5224  //  print(typeof(M));
5225    ERROR("an argument of type ideal/module/matrix expected");
5226  }
5227  if (attrib(M,"isSB")!=1)
5228  {
5229    M = std(M);
5230  }
5231  int dimR = gkdim(std(0));
5232  int dimM = gkdim(M);
5233  return( (dimR==2*dimM) );
5234}
5235example
5236{
5237  "EXAMPLE:"; echo = 2;
5238  ring R = 0,(x,y),dp;
5239  poly F = x*y*(x+y);
5240  def A = annfsBM(F,0);
5241  setring A;
5242  LD;
5243  isHolonomic(LD);
5244  ideal I = std(LD[1]);
5245  I;
5246  isHolonomic(I);
5247}
5248
5249proc reiffen(int p, int q)
5250"USAGE:  reiffen(p, q);  int p, int q
5251RETURN:  ring
5252PURPOSE: set up the polynomial, describing a Reiffen curve
5253NOTE:  activate the output ring with the @code{setring} command and
5254@*       find the curve as a polynomial RC.
5255@*  A Reiffen curve is defined as RC = x^p + y^q + xy^{q-1}, q >= p+1 >= 5
5256
5257EXAMPLE: example reiffen; shows examples
5258"
5259{
5260  // we allow also other numbers, p \geq 1, q\geq 1
5261// a Reiffen curve is defined as
5262// F = x^p + y^q +x*y^{q-1}, q \geq p+1 \geq 5
5263
5264// ASSUME: q >= p+1 >= 5. Otherwise an error message is returned
5265
5266//   if ( (p<4) || (q<5) || (q-p<1) )
5267//   {
5268//     ERROR("Some of conditions p>=4, q>=5 or q>=p+1 is not satisfied!");
5269//   }
5270  if ( (p<1) || (q<1) )
5271  {
5272    ERROR("Some of conditions p>=1, q>=1 is not satisfied!");
5273  }
5274  ring @r = 0,(x,y),dp;
5275  poly RC = y^q +x^p + x*y^(q-1);
5276  export RC;
5277  return(@r);
5278}
5279example
5280{
5281  "EXAMPLE:"; echo = 2;
5282  def r = reiffen(4,5);
5283  setring r;
5284  RC;
5285}
5286
5287proc arrange(int p)
5288"USAGE:  arrange(p);  int p
5289RETURN:  ring
5290PURPOSE: set up the polynomial, describing a hyperplane arrangement
5291NOTE:  must be executed in a commutative ring
5292ASSUME: basering is present and it is commutative
5293EXAMPLE: example arrange; shows examples
5294"
5295{
5296  int UseBasering = 0 ;
5297  if (p<2)
5298  {
5299    ERROR("p>=2 is required!");
5300  }
5301  if ( nameof(basering)!="basering" )
5302  {
5303    if (p > nvars(basering))
5304    {
5305      ERROR("too big p");
5306    }
5307    else
5308    {
5309      def @r = basering;
5310      UseBasering = 1;
5311    }
5312  }
5313  else
5314  {
5315    // no basering found
5316    ERROR("no basering found!");
5317    //    ring @r = 0,(x(1..p)),dp;
5318  }
5319  int i,j,sI;
5320  poly  q = 1;
5321  list ar;
5322  ideal tmp;
5323  tmp = ideal(var(1));
5324  ar[1] = tmp;
5325  for (i = 2; i<=p; i++)
5326  {
5327    // add i-nary sums to the product
5328    ar = indAR(ar,i);
5329  }
5330  for (i = 1; i<=p; i++)
5331  {
5332    tmp = ar[i]; sI = size(tmp);
5333    for (j = 1; j<=sI; j++)
5334    {
5335      q = q*tmp[j];
5336    }
5337  }
5338  if (UseBasering)
5339  {
5340    return(q);
5341  }
5342  //  poly AR = q; export AR;
5343  //  return(@r);
5344}
5345example
5346{
5347  "EXAMPLE:"; echo = 2;
5348  ring X = 0,(x,y,z,t),dp;
5349  poly q = arrange(3);
5350  factorize(q,1);
5351}
5352
5353proc checkRoot(poly F, number a, list #)
5354"USAGE:  checkRoot(f,alpha [,S,eng]);  poly f, number alpha, string S, int eng
5355RETURN:  int
5356ASSUME: Basering is a commutative ring, alpha is a rational number.
5357PURPOSE: check whether a rational number alpha is a root of the global
5358@* Bernstein-Sato polynomial of f and compute its multiplicity,
5359@* with the algorithm given by S and with the Groebner basis engine given by eng.
5360NOTE:  The annihilator of f^s in D[s] is needed and hence it is computed with the
5361@*       algorithm by Briancon and Maisonobe. The value of a string S can be
5362@*       'alg1' (default) - for the algorithm 1 of [LM08]
5363@*       'alg2' - for the algorithm 2 of [LM08]
5364@*       Depending on the value of S, the output of type int is:
5365@*       'alg1': 1 only if -alpha is a root of the global Bernstein-Sato polynomial
5366@*       'alg2':  the multiplicity of -alpha as a root of the global Bernstein-Sato
5367@*                  polynomial of f. If -alpha is not a root, the output is 0.
5368@*       If eng <>0, @code{std} is used for Groebner basis computations,
5369@*       otherwise (and by default) @code{slimgb} is used.
5370DISPLAY: If printlevel=1, progress debug messages will be printed,
5371@*          if printlevel>=2, all the debug messages will be printed.
5372EXAMPLE: example checkRoot; shows examples
5373"
5374{
5375  int eng = 0;
5376  int chs = 0; // choice
5377  string algo = "alg1";
5378  string st;
5379  if ( size(#)>0 )
5380  {
5381   if ( typeof(#[1]) == "string" )
5382   {
5383     st = string(#[1]);
5384     if ( (st == "alg1") || (st == "ALG1") || (st == "Alg1") ||(st == "aLG1"))
5385     {
5386       algo = "alg1";
5387       chs  = 1;
5388     }
5389     if ( (st == "alg2") || (st == "ALG2") || (st == "Alg2") || (st == "aLG2"))
5390     {
5391       algo = "alg2";
5392       chs  = 1;
5393     }
5394     if (chs != 1)
5395     {
5396       // incorrect value of S
5397       print("Incorrect algorithm given, proceed with the default alg1");
5398       algo = "alg1";
5399     }
5400     // second arg
5401     if (size(#)>1)
5402     {
5403       // exists 2nd arg
5404       if ( typeof(#[2]) == "int" )
5405       {
5406         // the case: given alg, given engine
5407         eng = int(#[2]);
5408       }
5409       else
5410       {
5411         eng = 0;
5412       }
5413     }
5414     else
5415     {
5416       // no second arg
5417       eng = 0;
5418     }
5419   }
5420   else
5421   {
5422     if ( typeof(#[1]) == "int" )
5423     {
5424       // the case: default alg, engine
5425       eng = int(#[1]);
5426       // algo = "alg1";  //is already set
5427     }
5428     else
5429     {
5430       // incorr. 1st arg
5431       algo = "alg1";
5432     }
5433   }
5434  }
5435  // size(#)=0, i.e. there is no algorithm and no engine given
5436  //  eng = 0; algo = "alg1";  //are already set
5437  // int ppl = printlevel-voice+2;
5438  printlevel=printlevel+1;
5439  def save = basering;
5440  def @A = SannfsBM(F);
5441  setring @A;
5442  poly F = imap(save,F);
5443  number a = imap(save,a);
5444  if ( algo=="alg1")
5445  {
5446    int output = checkRoot1(LD,F,a,eng);
5447  }
5448  else
5449  {
5450    if ( algo=="alg2")
5451    {
5452      int output = checkRoot2(LD,F,a,eng);
5453    }
5454  }
5455  printlevel=printlevel-1;
5456  return(output);
5457}
5458example
5459{
5460  "EXAMPLE:"; echo = 2;
5461  printlevel=0;
5462  ring r = 0,(x,y),Dp;
5463  poly F = x^4+y^5+x*y^4;
5464  checkRoot(F,11/20);    // -11/20 is a root of bf
5465  poly G = x*y;
5466  checkRoot(G,1,"alg2"); // -1 is a root of bg with multiplicity 2
5467}
5468
5469proc checkRoot1(ideal I, poly F, number a, list #)
5470"USAGE:  checkRoot1(I,f,alpha [,eng]);  ideal I, poly f, number alpha, int eng
5471ASSUME:  Basering is D[s], I is the annihilator of f^s in D[s],
5472@* that is basering and I are the output of Sannfs-like procedure,
5473@* f is a polynomial in K[x] and alpha is a rational number.
5474RETURN:  int, 1 if -alpha is a root of the Bernstein-Sato polynomial of f
5475PURPOSE: check, whether alpha is a root of the global Bernstein-Sato polynomial of f
5476NOTE:  If eng <>0, @code{std} is used for Groebner basis computations,
5477@*       otherwise (and by default) @code{slimgb} is used.
5478DISPLAY: If printlevel=1, progress debug messages will be printed,
5479@*          if printlevel>=2, all the debug messages will be printed.
5480EXAMPLE: example checkRoot1; shows examples
5481"
5482{
5483  // to check: alpha is rational (has char 0 check inside)
5484  if (!isRational(a))
5485  {
5486    "ERROR: alpha must be a rational number!";
5487  }
5488  //  no qring
5489  if ( size(ideal(basering)) >0 )
5490  {
5491    "ERROR: no qring is allowed";
5492  }
5493  int eng = 0;
5494  if ( size(#)>0 )
5495  {
5496    if ( typeof(#[1]) == "int" )
5497    {
5498      eng = int(#[1]);
5499    }
5500  }
5501  int ppl = printlevel-voice+2;
5502  dbprint(ppl,"// -0-1- starting the procedure checkRoot1");
5503  def save = basering;
5504  int N = nvars(basering);
5505  int Nnew = N-1;
5506  int n = Nnew / 2;
5507  int i;
5508  string s;
5509  list RL = ringlist(basering);
5510  list L, Lord;
5511  list tmp;
5512  intvec iv;
5513  L[1] = RL[1];  // char
5514  L[4] = RL[4];  // char, minpoly
5515  // check whether basering is D[s]=K(_x,_Dx,s)
5516  list Name = RL[2];
5517//   for (i=1; i<=n; i++)
5518//   {
5519//     if ( bracket(var(i+n),var(i))!=1 )
5520//     {
5521//       ERROR("basering should be D[s]=K(_x,_Dx,s)");
5522//     }
5523//   }
5524  if ( Name[N]!="s" )
5525  {
5526    ERROR("the last variable of basering should be s");
5527  }
5528  // now, create the new vars
5529  list NName;
5530  for (i=1; i<=Nnew; i++)
5531  {
5532    NName[i] = Name[i];
5533  }
5534  L[2] = NName;
5535  kill Name,NName;
5536  // block ord (dp);
5537  tmp[1] = "dp"; // string
5538  s = "iv=";
5539  for (i=1; i<=Nnew; i++)
5540  {
5541    s = s+"1,";
5542  }
5543  s[size(s)]=";";
5544  execute(s);
5545  kill s;
5546  tmp[2]  = iv;
5547  Lord[1] = tmp;
5548  tmp[1]  = "C";
5549  iv      = 0;
5550  tmp[2]  = iv;
5551  Lord[2] = tmp;
5552  tmp     = 0;
5553  L[3]    = Lord;
5554  // we are done with the list
5555  def @R@ = ring(L);
5556  setring @R@;
5557  matrix @D[Nnew][Nnew];
5558  for (i=1; i<=n; i++)
5559  {
5560    @D[i,i+n]=1;
5561  }
5562  def @R = nc_algebra(1,@D);
5563  setring @R;
5564  kill @R@;
5565  dbprint(ppl,"// -1-1- the ring @R(_x,_Dx) is ready");
5566  dbprint(ppl-1, S);
5567  // create the ideal K = ann_D[s](f^s)_{s=-alpha} + < f >
5568  setring save;
5569  ideal K = subst(I,s,-a);
5570  dbprint(ppl,"// -1-2- the variable s has been substituted by "+string(-a));
5571  dbprint(ppl-1, K);
5572  K = NF(K,std(F));
5573  // make leadcoeffs positive
5574  for (i=1; i<=ncols(K); i++)
5575  {
5576    if ( leadcoef(K[i])<0 )
5577    {
5578      K[i] = -K[i];
5579    }
5580  }
5581  K = K,F;
5582  // ------------ the ideal K is ready ------------
5583  setring @R;
5584  ideal K = imap(save,K);
5585  dbprint(ppl,"// -1-3- starting the computation of a Groebner basis of K in @R");
5586  dbprint(ppl-1, K);
5587  ideal G = engine(K,eng);
5588  dbprint(ppl,"// -1-4- the Groebner basis has been computed");
5589  dbprint(ppl-1, G);
5590  return(G[1]!=1);
5591}
5592example
5593{
5594  "EXAMPLE:"; echo = 2;
5595  ring r = 0,(x,y),Dp;
5596  poly F = x^4+y^5+x*y^4;
5597  printlevel = 0;
5598  def A = Sannfs(F);
5599  setring A;
5600  poly F = imap(r,F);
5601  checkRoot1(LD,F,31/20);   // -31/20 is not a root of bs
5602  checkRoot1(LD,F,11/20);   // -11/20 is a root of bs
5603}
5604
5605proc checkRoot2 (ideal I, poly F, number a, list #)
5606"USAGE:  checkRoot2(I,f,a [,eng]);  I an ideal, f a poly, alpha a number, eng an optional int
5607ASSUME:  I is the annihilator of f^s in D[s], basering is D[s],
5608@* that is basering and I are the output os Sannfs-like procedure,
5609@* f is a polynomial in K[_x] and alpha is a rational number.
5610RETURN:  int, the multiplicity of -alpha as a root of the BS polynomial of f.
5611PURPOSE: check whether a rational number alpha is a root of the global Bernstein-
5612@* Sato polynomial of f and compute its multiplicity from the known Ann F^s in D[s]
5613NOTE:   If -alpha is not a root, the output is 0.
5614@*       If eng <>0, @code{std} is used for Groebner basis computations,
5615@*       otherwise (and by default) @code{slimgb} is used.
5616DISPLAY: If printlevel=1, progress debug messages will be printed,
5617@*          if printlevel>=2, all the debug messages will be printed.
5618EXAMPLE: example checkRoot2; shows examples
5619"
5620{
5621
5622
5623  // to check: alpha is rational (has char 0 check inside)
5624  if (!isRational(a))
5625  {
5626    "ERROR: alpha must be a rational number!";
5627  }
5628  //  no qring
5629  if ( size(ideal(basering)) >0 )
5630  {
5631    "ERROR: no qring is allowed";
5632  }
5633
5634  int eng = 0;
5635  if ( size(#)>0 )
5636  {
5637    if ( typeof(#[1]) == "int" )
5638    {
5639      eng = int(#[1]);
5640    }
5641  }
5642  int ppl = printlevel-voice+2;
5643  dbprint(ppl,"// -0-1- starting the procedure checkRoot2");
5644  def save = basering;
5645  int N = nvars(basering);
5646  int n = (N-1) / 2;
5647  int i;
5648  string s;
5649  list RL = ringlist(basering);
5650  list L, Lord;
5651  list tmp;
5652  intvec iv;
5653  L[1] = RL[1];  // char
5654  L[4] = RL[4];  // char, minpoly
5655  // check whether basering is D[s]=K(_x,_Dx,s)
5656  list Name = RL[2];
5657  for (i=1; i<=n; i++)
5658  {
5659    if ( bracket(var(i+n),var(i))!=1 )
5660    {
5661      ERROR("basering should be D[s]=K(_x,_Dx,s)");
5662    }
5663  }
5664  if ( Name[N]!="s" )
5665  {
5666    ERROR("the last variable of basering should be s");
5667  }
5668  // now, create the new vars
5669  L[2] = Name;
5670  kill Name;
5671  // block ord (dp);
5672  tmp[1] = "dp"; // string
5673  s = "iv=";
5674  for (i=1; i<=N; i++)
5675  {
5676    s = s+"1,";
5677  }
5678  s[size(s)]=";";
5679  execute(s);
5680  kill s;
5681  tmp[2]  = iv;
5682  Lord[1] = tmp;
5683  tmp[1]  = "C";
5684  iv      = 0;
5685  tmp[2]  = iv;
5686  Lord[2] = tmp;
5687  tmp     = 0;
5688  L[3]    = Lord;
5689  // we are done with the list
5690  def @R@ = ring(L);
5691  setring @R@;
5692  matrix @D[N][N];
5693  for (i=1; i<=n; i++)
5694  {
5695    @D[i,i+n]=1;
5696  }
5697  def @R = nc_algebra(1,@D);
5698  setring @R;
5699  kill @R@;
5700  dbprint(ppl,"// -1-1- the ring @R(_x,_Dx,s) is ready");
5701  dbprint(ppl-1, @R);
5702  // now, continue with the algorithm
5703  ideal I = imap(save,I);
5704  poly F = imap(save,F);
5705  number a = imap(save,a);
5706  ideal II = NF(I,std(F));
5707  // make leadcoeffs positive
5708  for (i=1; i<=ncols(II); i++)
5709  {
5710    if ( leadcoef(II[i])<0 )
5711    {
5712      II[i] = -II[i];
5713    }
5714  }
5715  ideal J,G;
5716  int m;  // the output (multiplicity)
5717  dbprint(ppl,"// -2- starting the bucle");
5718  for (i=0; i<=n; i++)  // the multiplicity has to be <= n
5719  {
5720    // create the ideal Ji = ann_D[s](f^s) + < f, (s+alpha)^{i+1} >
5721    // (s+alpha)^i in Ji <==> -alpha is a root with multiplicity >= i
5722    J = II,F,(s+a)^(i+1);
5723    // ------------ the ideal Ji is ready -----------
5724    dbprint(ppl,"// -2-"+string(i+1)+"-1- starting the computation of a Groebner basis of J"+string(i)+" in @R");
5725    dbprint(ppl-1, J);
5726    G = engine(J,eng);
5727    dbprint(ppl,"// -2-"+string(i+1)+"-2- the Groebner basis has been computed");
5728    dbprint(ppl-1, G);
5729    if ( NF((s+a)^i,G)==0 )
5730    {
5731      dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has not multiplicity "+string(i+1));
5732      m = i;
5733      break;
5734    }
5735    dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has multiplicity at least "+string(i+1));
5736  }
5737  dbprint(ppl,"// -3- the bucle has finished");
5738  return(m);
5739}
5740example
5741{
5742  "EXAMPLE:"; echo = 2;
5743  ring r = 0,(x,y,z),Dp;
5744  poly F = x*y*z;
5745  printlevel = 0;
5746  def A = Sannfs(F);
5747  setring A;
5748  poly F = imap(r,F);
5749  checkRoot2(LD,F,1);    // -1 is a root of bs with multiplicity 3
5750  checkRoot2(LD,F,1/3);  // -1/3 is not a root
5751}
5752
5753proc checkFactor(ideal I, poly F, poly q, list #)
5754"USAGE:  checkFactor(I,f,qs [,eng]);  I an ideal, f a poly, qs a poly, eng an optional int
5755ASSUME:  checkFactor is called from the basering, created by Sannfs-like proc,
5756@* that is, from the Weyl algebra in x1,..,xN,d1,..,dN tensored with K[s].
5757@* The ideal I is the annihilator of f^s in D[s], that is the ideal, computed
5758@* by Sannfs-like procedure (usually called LD there).
5759@* Moreover, f is a polynomial in K[x1,..,xN] and qs is a polynomial in K[s].
5760RETURN:  int, 1 if qs is a factor of the global Bernstein polynomial of f and 0 otherwise
5761PURPOSE: check whether a univariate polynomial qs is a factor of the
5762@*  Bernstein-Sato polynomial of f without explicit knowledge of the latter.
5763NOTE:    If eng <>0, @code{std} is used for Groebner basis computations,
5764@*       otherwise (and by default) @code{slimgb} is used.
5765DISPLAY: If printlevel=1, progress debug messages will be printed,
5766@*          if printlevel>=2, all the debug messages will be printed.
5767EXAMPLE: example checkFactor; shows examples
5768"
5769{
5770
5771  // ASSUME too complicated, cannot check it.
5772
5773  int eng = 0;
5774  if ( size(#)>0 )
5775  {
5776    if ( typeof(#[1]) == "int" )
5777    {
5778      eng = int(#[1]);
5779    }
5780  }
5781  int ppl = printlevel-voice+2;
5782  def @R2 = basering;
5783  int N = nvars(@R2);
5784  int i;
5785  // we're in D_n[s], where the elim ord for s is set
5786  dbprint(ppl,"// -0-1- starting the procedure checkFactor");
5787  dbprint(ppl,"// -1-1- the ring @R2(_x,_Dx,s) is ready");
5788  dbprint(ppl-1, @R2);
5789  // create the ideal J = ann_D[s](f^s) + < f,q >
5790  ideal J = NF(I,std(F));
5791  // make leadcoeffs positive
5792  for (i=1; i<=ncols(J); i++)
5793  {
5794    if ( leadcoef(J[i])<0 )
5795    {
5796      J[i] = -J[i];
5797    }
5798  }
5799  J = J,F,q;
5800  // ------------ the ideal J is ready -----------
5801  dbprint(ppl,"// -1-2- starting the elimination of _x,_Dx in @R2");
5802  dbprint(ppl-1, J);
5803  ideal G = engine(J,eng);
5804  ideal K = nselect(G,1..N-1);
5805  kill J,G;
5806  dbprint(ppl,"// -1-3- _x,_Dx are eliminated");
5807  dbprint(ppl-1, K);
5808  //q is a factor of bs if and only if K = < q >
5809  //K = normalize(K);
5810  //q = normalize(q);
5811  //return( (K[1]==q) );
5812  return( NF(K[1],std(q))==0 );
5813}
5814example
5815{
5816  "EXAMPLE:"; echo = 2;
5817  ring r = 0,(x,y),Dp;
5818  poly F = x^4+y^5+x*y^4;
5819  printlevel = 0;
5820  def A = Sannfs(F);
5821  setring A;
5822  poly F = imap(r,F);
5823  checkFactor(LD,F,20*s+31);     // -31/20 is not a root of bs
5824  checkFactor(LD,F,20*s+11);     // -11/20 is a root of bs
5825  checkFactor(LD,F,(20*s+11)^2); // the multiplicity of -11/20 is 1
5826}
5827
5828proc varNum(string s)
5829"USAGE:  varNum(s);  string s
5830RETURN:  int
5831PURPOSE: returns the number of the variable with the name s
5832@*  among the variables of basering or 0 if there is no such variable
5833EXAMPLE: example varNum; shows examples
5834"
5835{
5836  int i;
5837  for (i=1; i<= nvars(basering); i++)
5838  {
5839    if ( string(var(i)) == s )
5840    {
5841      return(i);
5842    }
5843  }
5844  return(0);
5845}
5846example
5847{
5848  "EXAMPLE:"; echo = 2;
5849  ring X = 0,(x,y1,t,z(0),z,tTa),dp;
5850  varNum("z");
5851  varNum("t");
5852  varNum("xyz");
5853}
5854
5855static proc indAR(list L, int n)
5856"USAGE:  indAR(L,n);  list L, int n
5857RETURN:  list
5858PURPOSE: computes arrangement inductively, using L and
5859@* var(n) as the next variable
5860ASSUME: L has a structure of an arrangement
5861EXAMPLE: example indAR; shows examples
5862"
5863{
5864  if ( (n<2) || (n>nvars(basering)) )
5865  {
5866    ERROR("incorrect n");
5867  }
5868  int sl = size(L);
5869  list K;
5870  ideal tmp;
5871  poly @t = L[sl][1] + var(n); //1 elt
5872  K[sl+1] = ideal(@t);
5873  tmp = L[1]+var(n);
5874  K[1] = tmp; tmp = 0;
5875  int i,j,sI;
5876  ideal I;
5877  for(i=sl; i>=2; i--)
5878  {
5879    I = L[i-1]; sI = size(I);
5880    for(j=1; j<=sI; j++)
5881    {
5882      I[j] = I[j] + var(n);
5883    }
5884    tmp  = L[i],I;
5885    K[i] = tmp;
5886    I = 0; tmp = 0;
5887  }
5888  kill I; kill tmp;
5889  return(K);
5890}
5891example
5892{
5893  "EXAMPLE:"; echo = 2;
5894  ring r = 0,(x,y,z,t,v),dp;
5895  list L;
5896  L[1] = ideal(x);
5897  list K = indAR(L,2);
5898  K;
5899  list M = indAR(K,3);
5900  M;
5901  M = indAR(M,4);
5902  M;
5903}
5904
5905proc isRational(number n)
5906"USAGE:  isRational(n); n number
5907RETURN:  int
5908PURPOSE: determine whether n is a rational number,
5909@* that is it does not contain parameters.
5910ASSUME: ground field is of characteristic 0
5911EXAMPLE: example indAR; shows examples
5912"
5913{
5914  if (char(basering) != 0)
5915  {
5916    ERROR("The ground field must be of characteristic 0!");
5917  }
5918  number dn = denominator(n);
5919  number nn = numerator(n);
5920  return( ((int(dn)==dn) && (int(nn)==nn)) );
5921}
5922example
5923{
5924  "EXAMPLE:"; echo = 2;
5925  ring r = (0,a),(x,y),dp;
5926  number n1 = 11/73;
5927  isRational(n1);
5928  number n2 = (11*a+3)/72;
5929  isRational(n2);
5930}
5931
5932/// ****** EXAMPLES ************
5933
5934/*
5935
5936//static proc exCheckGenericity()
5937{
5938  LIB "control.lib";
5939  ring r = (0,a,b,c),x,dp;
5940  poly p = (x-a)*(x-b)*(x-c);
5941  def A = annfsBM(p);
5942  setring A;
5943  ideal J = slimgb(LD);
5944  matrix T = lift(LD,J);
5945  T = normalize(T);
5946  genericity(T);
5947  // Ann =x^3*Dx+3*x^2*t*Dt+(-a-b-c)*x^2*Dx+(-2*a-2*b-2*c)*x*t*Dt+3*x^2+(a*b+a*c+b*c)*x*Dx+(a*b+a*c+b*c)*t*Dt+(-2*a-2*b-2*c)*x+(-a*b*c)*Dx+(a*b+a*c+b*c)
5948  // genericity: g = a2-ab-ac+b2-bc+c2 =0
5949  // g = (a -(b+c)/2)^2 + (3/4)*(b-c)^2;
5950  // g ==0 <=> a=b=c
5951  // indeed, Ann = (x-a)^2*(x*Dx+3*t*Dt+(-a)*Dx+3)
5952  // --------------------------------------------
5953  // BUT a direct computation shows
5954  // when a=b=c,
5955  // Ann = x*Dx+3*t*Dt+(-a)*Dx+3
5956}
5957
5958//static proc exOT_17()
5959{
5960  // Oaku-Takayama, p.208
5961  ring R = 0,(x,y),dp;
5962  poly F = x^3-y^2; // x^2+x*y+y^2;
5963  option(prot);
5964  option(mem);
5965  //  option(redSB);
5966  def A = annfsOT(F,0);
5967  setring A;
5968  LD;
5969  gkdim(LD); // a holonomic check
5970  //  poly F = x^3-y^2; // = x^7 - y^5; // x^3-y^4; // x^5 - y^4;
5971}
5972
5973//static proc exOT_16()
5974{
5975  // Oaku-Takayama, p.208
5976  ring R = 0,(x),dp;
5977  poly F = x*(1-x);
5978  option(prot);
5979  option(mem);
5980  //  option(redSB);
5981  def A = annfsOT(F,0);
5982  setring A;
5983  LD;
5984  gkdim(LD); // a holonomic check
5985}
5986
5987//static proc ex_bcheck()
5988{
5989  ring R = 0,(x,y),dp;
5990  poly F = x*y*(x+y);
5991  option(prot);
5992  option(mem);
5993  int eng = 0;
5994  //  option(redSB);
5995  def A = annfsOT(F,eng);
5996  setring A;
5997  LD;
5998}
5999
6000//static proc ex_bcheck2()
6001{
6002  ring R = 0,(x,y),dp;
6003  poly F = x*y*(x+y);
6004  int eng = 0;
6005  def A = annfsBM(F,eng);
6006  setring A;
6007  LD;
6008}
6009
6010//static proc ex_BMI()
6011{
6012  // a hard example
6013  ring r = 0,(x,y),Dp;
6014  poly F1 = (x2-y3)*(x3-y2);
6015  poly F2 = (x2-y3)*(xy4+y5+x4);
6016  ideal F = F1,F2;
6017  def A = annfsBMI(F);
6018  setring A;
6019  LD;
6020  BS;
6021}
6022
6023//static proc ex2_BMI()
6024{
6025  // this example was believed to be intractable in 2005 by Gago-Vargas, Castro and Ucha
6026  ring r = 0,(x,y),Dp;
6027  option(prot);
6028  option(mem);
6029  ideal F = x2+y3,x3+y2;
6030  printlevel = 2;
6031  def A = annfsBMI(F);
6032  setring A;
6033  LD;
6034  BS;
6035}
6036
6037//static proc ex_operatorBM()
6038{
6039  ring r = 0,(x,y,z,w),Dp;
6040  poly F = x^3+y^3+z^2*w;
6041  printlevel = 0;
6042  def A = operatorBM(F);
6043  setring A;
6044  F; // the original polynomial itself
6045  LD; // generic annihilator
6046  LD0; // annihilator
6047  bs; // normalized Bernstein poly
6048  BS; // root and multiplicities of the Bernstein poly
6049  PS; // the operator, s.t. PS*F^{s+1} = bs*F^s mod LD
6050  reduce(PS*F-bs,LD); // check the property of PS
6051}
6052
6053*/
Note: See TracBrowser for help on using the repository browser.