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

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