source: git/Singular/LIB/dmod.lib @ 3360fb

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