source: git/Singular/LIB/dmod.lib @ 291c20

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