source: git/Singular/LIB/hnoether.lib @ 0132b0

spielwiese
Last change on this file since 0132b0 was 0132b0, checked in by Olaf Bachmann <obachman@…>, 26 years ago
* incoporated new versions from Martin git-svn-id: file:///usr/local/Singular/svn/trunk@1437 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 99.1 KB
Line 
1// $Id: hnoether.lib,v 1.5 1998-04-23 13:23:23 obachman Exp $
2// author:  Martin Lamm,  email: lamm@mathematik.uni-kl.de
3// last change:           26.03.98
4///////////////////////////////////////////////////////////////////////////////
5
6version="$Id: hnoether.lib,v 1.5 1998-04-23 13:23:23 obachman Exp $";
7info="
8LIBRARY:  hnoether.lib   PROCEDURES FOR THE HAMBURGER-NOETHER-DEVELOPMENT
9
10           Important procedures:
11 develop(f [,n]);    Hamburger-Noether development from the irred. polynomial f
12 reddevelop(f);      Hamburger-Noether development from the (red.) polynomial f
13 extdevelop(hne,n);  extension of Hamburger-Noether development hne from f
14 param(hne);         returns a parametrization of f (input=output(develop))
15 displayHNE(hne);    display Hamburger-Noether development as an ideal
16 invariants(hne);    invariants of f, e.g. the characteristic exponents
17 displayInvariants(hne);  display invariants of f
18 generators(hne);    computes the generators of the semigroup of values
19 intersection(hne1,hne2); intersection multiplicity of two curves
20 stripHNE(hne);      reduce amount of memory consumed by hne
21
22           perhaps useful procedures:
23 puiseux2generators(m,n); convert puiseux pairs to generators of semigroup
24 multiplicities(hne);     multiplicities of blowed up curves
25 newtonpoly(f);      newtonpolygon of polynom f
26 newtonhoehne(f);    same as newtonpoly, but uses internal procedure
27 getnm(f);           intersection points of the Newton-polygon with the axes
28 T_Transform(f,Q,N); returns f(y,xy^Q)/y^NQ (type f(x,y): poly, Q,N: int)
29 T1_Transform(f,d,M); returns f(x,y+d*x^M)  (type f(x,y): poly,d:number,M:int)
30 T2_Transform(f,d,M,N);   a composition of T1 & T
31 koeff(f,I,J);       gets coefficient of indicated monomial of poly f (I,J:int)
32 redleit(f,S,E);     restriction of monomials of f to line (S-E)
33 squarefree(f);      returns a squarefree divisor of the poly f
34 allsquarefree(f,l); returns the maximal squarefree divisor of the poly f
35 set_list(L,v,l);    managing interconnected lists
36
37           procedures (more or less) for internal use:
38 leit(f,n,m);        special case of redleit (for irred. polynomials)
39 testreducible(f,n,m); tests whether f is reducible
40 polytest(f);        tests coefficients and exponents of poly f
41 charPoly(f,M,N);    characteristic polynomial of f
42 find_in_list(L,p);  find int p in list L
43 get_last_divisor(M,N); last divisor in Euclid's algorithm
44 factorfirst(f,M,N); try to factor f in a trivial way before using 'factorize'
45 extrafactor(f,M,N); try to factor charPoly(f,M,N) where 'factorize' cannot
46 extractHNEs(H,t);   extracts output H of HN to output of reddevelop
47 HN(f,grenze);       recursive subroutine for reddevelop
48 constructHNEs(...); subroutine for HN
49";
50
51///////////////////////////////////////////////////////////////////////////////
52LIB "primitiv.lib";
53///////////////////////////////////////////////////////////////////////////////
54
55proc getnm (poly f)
56USAGE:   getnm(f); f polynomial in x,y
57ASSUME:  basering = ...,(x,y),ls;  or ds
58RETURN:  intvec(n,m) : (0,n) is the intersection point of the Newton
59         polygon of f with the y-axis, n=-1 if it doesn't exist
60         (m,0) is its intersection point with the x-axis,
61         m=-1 if this point doesn't exist
62EXAMPLE: example getnm; shows an example
63{
64 // wir gehen davon aus, dass die Prozedur von develop aufgerufen wurde, also
65 // die Ringordnung ist ls (ds ginge auch)
66 return(ord(subst(f,x,0)),ord(subst(f,y,0)));
67}
68example
69{ "EXAMPLE:"; echo = 2;
70   ring r = 0,(x,y),ds;
71   poly f = x5+x4y3-y2+y4;
72   getnm(f);
73}
74///////////////////////////////////////////////////////////////////////////////
75
76proc leit (poly f, int n, int m)
77// leit(poly f, int n, int m) returns all monomials on the line
78// from (0,n) to (m,0) in the Newton diagram
79{
80 return(jet(f,m*n,intvec(n,m))-jet(f,m*n-1,intvec(n,m)))
81}
82///////////////////////////////////////////////////////////////////////////////
83proc testreducible (poly f, int n, int m)
84// testreducible(poly f,int n,int m) returns true if there are points in the
85// Newton diagram below the line (0,n)-(m,0)
86{
87 return(size(jet(f,m*n-1,intvec(n,m))) != 0)
88}
89///////////////////////////////////////////////////////////////////////////////
90proc T_Transform (poly f, int Q, int N)
91// returns f(y,xy^Q)/y^NQ
92{
93 map T = basering,y,x*y^Q;
94 return(T(f)/y^(N*Q));
95}
96///////////////////////////////////////////////////////////////////////////////
97proc T1_Transform (poly f, number d, int M)
98// returns f(x,y+d*x^M)
99{
100 map T1 = basering,x,y+d*x^M;
101 return(T1(f));
102}
103///////////////////////////////////////////////////////////////////////////////
104
105proc T2_Transform (poly f, number d, int M, int N)
106USAGE: T2_Transform(f,d,M,N); f poly, d number; M,N int
107RETURN: list: poly T2(f,d',M,N), number d' in \{ d, 1/d \}
108{
109 //---------------------- compute gcd and extgcd of N,M -----------------------
110  int ggt=gcd(M,N);
111  M=M/ggt; N=N/ggt;
112  list ts=extgcd(M,N);
113  int tau,sigma=ts[2],-ts[3];
114  if (sigma<0) { tau=-tau; sigma=-sigma;}
115 // es gilt: 0<=tau<=N, 0<=sigma<=M, |N*sigma-M*tau| = 1 = ggT(M,N)
116  if (N*sigma < M*tau) { d = 1/d; }
117 //--------------------------- euklid. Algorithmus ----------------------------
118  int R;
119  int M1,N1=M,N;
120  for ( R=M1%N1; R!=0; ) { M1=N1; N1=R; R=M1%N1;}
121  int Q=M1 / N1;
122  map T1 = basering,x,y+d*x^Q;
123  map Tstar=basering,x^(N-Q*tau)*y^tau,x^(M-sigma*Q)*y^sigma;
124  if (defined(Protokoll)) {
125   "Trafo. T2: x->x^"+string(N-Q*tau)+"*y^"+string(tau)+", y->x^"
126    +string(M-sigma*Q)+"*y^"+string(sigma);
127   "delta =",d,"Q =",Q,"tau,sigma =",tau,sigma;
128  }
129 //------------------- Durchfuehrung der Transformation T2 --------------------
130 // man koennte an T2_Transform noch eine Liste mit allen Eckpunkten des
131 // Newtonpolys uebergeben und nur die Transformierten der Eckpunkte betrachten
132 // um max. Exponenten e,f von x,y zu finden--noch einfacher: ein Referenzpo-
133 // lynom, das das gleiche Newtonpolygon hat (z.B. Einschraenkung auf die Mono-
134 // me in den Eckpunkten, oder alle Monome haben Koeff. 1, das ist einfacher)
135 //----------------------------------------------------------------------------
136
137  f=Tstar(f); // hier dann refpoly=Tstar(refpoly)
138  poly hilf;
139 // dividiere f so lange durch x, wie die Div. aufgeht:
140  for (hilf=f/x; hilf*x==f; hilf=f/x) {f=hilf;}
141  for (hilf=f/y; hilf*y==f; hilf=f/y) {f=hilf;} // gleiches fuer y
142  return(list(T1(f),d));
143}
144///////////////////////////////////////////////////////////////////////////////
145
146proc koeff (poly f, int I, int J)
147USAGE:  koeff(f,I,J); f polynomial in x and y, I,J integers
148RETURN: if f = sum(a(i,j)*x^i*y^j), then koeff(f,I,J)= a(I,J) (of type number)
149EXAMPLE: example koeff;  shows an example
150{
151  matrix mat = coeffs(coeffs(f,y)[J+1,1],x);
152  if (size(mat) <= I) { return(0);}
153  else { return(leadcoef(mat[I+1,1]));}
154}
155example
156{ "EXAMPLE:"; echo = 2;
157  ring r=0,(x,y),dp;
158  koeff(x2+2xy+3xy2-x2y-2y3,1,2);
159}
160///////////////////////////////////////////////////////////////////////////////
161
162proc squarefree (poly f)
163USAGE:  squarefree(f); f poly in x and y
164RETURN: a squarefree divisor of f
165        Normally the return value is a greatest squarefree divisor, but there
166        is an exception: factors with a p-th root, p the ring characteristic,
167        are lost.
168EXAMPLE: example squarefree; shows some examples.
169{
170 // es gibt noch ein Problem: syz gibt manchmal in Koerpererweiterung (p,a)
171 // nicht f/g zurueck, obwohl die Division aufgeht ... In dem Fall ist die
172 // Rueckgabe evtl. nicht quadratfrei! Bsp.: squarefree((1/a*x3+y7)^3);
173 // in char 7
174 // In Singular 1.1.3 funktioniert syz, dafuer geht das gleiche Bsp. schief,
175 // weil gcd auf einmal falsch wird! (ring (7,a),(x,y),dp; minpoly=a2+1; )
176
177 //----------------- Wechsel in geeigneten Ring & Variablendefinition ---------
178  def altring = basering;
179  int e;
180  int gcd_ok=1;
181  string mipl="0";
182  if (size(parstr(altring))==1) {mipl=string(minpoly);}
183 //---- test: char = (p^k,a) (-> gcd not implemented) or (p,a) (gcd works) ----
184  if ((char(basering)!=0) and (charstr(basering)!=string(char(basering)))) {
185    string tststr=charstr(basering);
186    tststr=tststr[1..find(tststr,",")-1];           //-> "p^k" bzw. "p"
187    gcd_ok=(tststr==string(char(basering)));
188  }
189  execute("ring rsqrf = ("+charstr(altring)+"),(x,y),dp;");
190  if ((gcd_ok!=0) && (mipl!="0")) { execute "minpoly="+mipl+";"; }
191  poly f=fetch(altring,f);
192  poly dif,g,l;
193  if (gcd_ok!=0) {
194 //-------------------- Berechne f/ggT(f,df/dx,df/dy) ------------------------
195    dif=diff(f,x);
196    if (dif==0) { g=f; }        // zur Beschleunigung
197    else { g=gcd(f,dif); }
198    if (g!=1) {                 // sonst schon sicher, dass f quadratfrei
199     dif=diff(f,y);
200     if (dif!=0) { g=gcd(g,dif); }
201    }
202    if (g!=1) {
203     e=0;
204     if (g==f) { l=1; }         // zur Beschleunigung
205     else {
206       module m=syz(ideal(g,f));
207       if (deg(m[2,1])>0) {
208         "!! The Singular command 'syz' has returned a wrong result !!";
209         l=1;                   // Division f/g muss aufgehen
210       }
211       else { l=m[1,1]; }
212     }
213 //----------------------------------------------------------------------------
214 // Polynomdivision geht, wenn factory eingebunden ist
215 // dann also l=f/g; aber: ist ebenfalls fehlerhaft! (s.o. als Bsp.)
216 // wenn / zur Polynomdivision einsetzbar ist, kann der Ringwechsel gespart
217 // werden, sollte dann also zum Einsatz gebracht werden (Zeitersparnis)
218 //----------------------------------------------------------------------------
219    }
220    else { e=1; }
221  }
222  else {
223 //------------------- Berechne syz(f,df/dx) oder syz(f,df/dy) ----------------
224 //-- Achtung: Ist f reduzibel, koennen Faktoren mit Ableitung Null verloren --
225 //-- gehen! Ist aber nicht weiter schlimm, weil char (p^k,a) nur im irred.  --
226 //-- Fall vorkommen kann. Wenn f nicht g^p ist, wird auf jeden Fall         --
227 //------------------------ ein Faktor gefunden. ------------------------------
228    dif=diff(f,x);
229    if (dif == 0) {
230     dif=diff(f,y);
231     if (dif==0) { e=2; l=1; } // f is of power divisible by char of basefield
232     else { l=syz(ideal(dif,f))[1,1];  // x^p+y^(p-1) abgedeckt
233            if (deg(l)==deg(f)) { e=1;}
234            else {e=0;}
235     }
236    }
237    else { l=syz(ideal(dif,f))[1,1];
238           if (deg(l)==deg(f)) { e=1;}
239           else {e=0;}
240    }
241  }
242 //--------------- Wechsel in alten Ring und Rueckgabe des Ergebnisses --------
243  setring altring;
244  if (e==1) { return(f); }    // zur Beschleunigung
245  else {
246   poly l=fetch(rsqrf,l);
247   return(l);
248  }
249}
250example
251{ "EXAMPLE:"; echo = 2;
252 ring exring=3,(x,y),dp;
253 squarefree(x3+y);
254 squarefree(x3);
255 squarefree(x2);
256 squarefree(xy+x);
257 squarefree((x+y)^3*(x-y)^2); // (x+y)^3 is lost
258 squarefree((x+y)^4*(x-y)^2); // result is (x+y)*(x-y)
259}
260///////////////////////////////////////////////////////////////////////////////
261
262proc allsquarefree (poly f, poly l)
263USAGE : allsquarefree(f,l);  poly f,l
264        l is the squarefree divisor of f you get by l=squarefree(f);
265RETURN: the squarefree divisor of f consisting of all irreducible factors of f
266NOTE  : * this proc uses factorize to get the missing factors of f not in l and
267          therefore may be slow. Furthermore factorize can still return
268          a factor more than once (what should not occur)
269        * this proc uses polynomial division of factory (which still has a bug
270         at the moment: it can return nonsense, if the basering has parameters)
271EXAMPLE: example allsquarefree;  shows an example
272{
273 //---------- eliminiere bereits mit squarefree gefundene Faktoren ------------
274 poly g=l;                            // g = gcd(f,l);
275 while (deg(g)!=0) {
276  f=f/g;
277  g=gcd(f,l);
278 }                                    // jetzt f=h^p
279 //--------------- Berechne uebrige Faktoren mit factorize --------------------
280 if (deg(f)>0) {
281  g=1;
282  ideal factf=factorize(f,1);
283  for (int i=1; i<=size(factf); i++) { g=g*factf[i]; }
284  poly testp=squarefree(g);
285  if (deg(testp)<deg(g)) {
286    "!! factorize has not worked correctly !!";
287    if (testp==1) {" We cannot proceed ..."; g=1;}
288    else {" But we could recover the correct result..."; g=testp;}
289  }
290  l=l*g;
291 }
292 return(l);
293}
294example
295{ "EXAMPLE:"; echo = 2;
296  ring exring=7,(x,y),dp;
297  poly f=(x+y)^7*(x-y)^8;
298  poly l=squarefree(f);
299  l; // x-y found because 7 does not divide 8
300  allsquarefree(f,l); // all factors (x+y)*(x-y) found
301}
302///////////////////////////////////////////////////////////////////////////////
303
304proc polytest(poly f)
305USAGE : polytest(f); f poly in x and y
306RETURN: a monomial of f with |coefficient| > 16001
307          or exponent divisible by 32003, if there is one
308        0 else (in this case computing a squarefree divisor
309                in characteristic 32003 could make sense)
310NOTE:   this procedure is only useful in characteristic zero, because otherwise
311        there is no appropriate ordering of the leading coefficients
312{
313 poly verbrecher=0;
314 intvec leitexp;
315 for (; (f<>0) and (verbrecher==0); f=f-lead(f)) {
316  if ((leadcoef(f)<-16001) or (leadcoef(f)>16001)) {verbrecher=lead(f);}
317  leitexp=leadexp(f);
318  if (( ((leitexp[1] % 32003) == 0)   and (leitexp[1]<>0))
319     or ( ((leitexp[2] % 32003) == 0) and (leitexp[2]<>0)) )
320       {verbrecher=lead(f);}
321 }
322 return(verbrecher);
323}
324
325//////////////////////////////////////////////////////////////////////////////
326
327
328proc develop
329USAGE:   develop(f [,n]); f polynomial in two variables, n integer
330ASSUME:  f irreducible as a power series (for reducible f use reddevelop)
331RETURN:  Hamburger-Noether development of f, in form of a list:
332         [1]: Hamburger-Noether matrix
333            each row contains the coefficients of the corresponding line of the
334            Hamburger-Noether extension (HNE). The end of the line is marked in
335            the matrix as the first ring variable (usually x)
336         [2]: intvec indicating the length of lines of the HNE
337         [3]: int:
338           0  if the 1st ring variable was transverse (with respect to f),
339           1  if the variables were changed at the beginning of the computation
340           -1 if an error has occurred
341         [4]: the transformed polynomial of f to make it possible to extend the
342              Hamburger-Noether development a posteriori without having to do
343              all the previous calculation once again (0 if not needed)
344DISPLAY: The (non zero) elements of the HNE
345
346NOTE:    If the optional parameter n is given, the HN-matrix will have at least
347         n columns. Otherwise the number of columns will be chosen minimal s.t.
348         the matrix contains all necessary information (i.e. all lines of the
349         HNE but the last (which is in general infinite) appear).
350         If n is negative, the algorithm is stopped as soon as possible, i.e.
351         the information computed is enough for 'invariants', but the HN-matrix
352         may contain undetermined elements, which are marked with the
353         2nd variable (of the basering).
354         In any case, the optional parameter only affects the calculation of
355         the LAST line of the HNE; develop(f) gives already all necessary
356         information for the procedure 'invariants'. A negative value of n will
357         result in a very poor parametrization, but it can make 'develop'
358         faster; a positive value will improve the exactness of the
359         parametrization.
360
361         For time critical computations it is recommended to use
362         "ring ...,(x,y),ls" as basering - it increases the algorithm's speed.
363
364EXAMPLES: example develop; shows an example
365          example param;   shows an example for using the 2nd parameter
366{
367 //--------- Abfangen unzulaessiger Ringe: 1) nur eine Unbestimmte ------------
368 poly f=#[1];
369 if (size(#) > 1) {int maxspalte=#[2];}
370 else             {int maxspalte= 1 ; }
371 if (nvars(basering) < 2) {
372   " Sorry. I need two variables in the ring.";
373   return(list(matrix(maxideal(1)[1]),intvec(0),-1,poly(0)));}
374 if (nvars(basering) > 2) {
375   " Warning! You have defined too many variables!";
376   " All variables except the first two will be ignored!";}
377
378 string namex=varstr(1); string namey=varstr(2);
379 list return_error=matrix(maxideal(1)[2]),intvec(0),int(-1),poly(0);
380
381 //------------- 2) mehrere Unbestimmte, weitere unzulaessige Ringe -----------
382 // Wir koennen einheitlichen Rueckgabewert benutzen, aus dem ersichtlich ist,
383 // dass ein Fehler aufgetreten ist: return_error.
384 //----------------------------------------------------------------------------
385
386 if (charstr(basering)=="real") {
387  "The algorithm doesn't work with 'real' as coefficient field.";
388                     // denn : map from characteristic -1 to -1 not implemented
389  return(return_error);
390 }
391 if ((char(basering)!=0) and (charstr(basering)!=string(char(basering)))) {
392 //-- teste, ob char = (p^k,a) (-> a primitiv; erlaubt) oder (p,a[,b,...]) ----
393    string tststr=charstr(basering);
394    tststr=tststr[1..find(tststr,",")-1];           //-> "p^k" bzw. "p"
395    int primit=(tststr==string(char(basering)));
396    if (primit!=0) {
397      "such extensions of Z/p are not implemented.",
398      "Please try (p^k,a) as ground field.";
399      return(return_error);
400    }
401 }
402 //---- Ende der unzulaessigen Ringe; Ringwechsel in einen guenstigen Ring: ---
403
404 int ringwechsel=(varstr(basering)!="x,y") or (ordstr(basering)!="ls(2),C");
405
406 def altring = basering;
407 if (ringwechsel) {
408   string mipl=string(minpoly);
409   execute("ring guenstig = ("+charstr(altring)+"),(x,y),ls;");
410   if ((char(basering)==0) && (mipl!="0")) {
411     execute "minpoly="+mipl+";";
412   }}
413 else { def guenstig=basering; }
414 export guenstig;
415
416 //-------------------------- Initialisierungen -------------------------------
417 map m=altring,x,y;
418 if (ringwechsel) { poly f=m(f); }
419 if (defined(Protokoll))
420 {"received polynomial: ",f,", where x =",namex,", y =",namey;}
421
422 int M,N,Q,R,l,e,hilf,eps,getauscht,Abbruch,zeile,exponent,Ausgabe;
423
424 // Werte von Ausgabe: 0 : normale HNE-Matrix,
425 // 1 : Fehler aufgetreten - Matrix (namey) zurueck
426 // 2 : Die HNE ist eine Nullzeile - Matrix (0) zurueck
427 // int maxspalte=1; geaendert: wird jetzt am Anfang gesetzt
428
429 int minimalHNE=0;          // Flag fuer minimale HNE-Berechnung
430 intvec hqs;                // erhaelt die Werte von h(zeile)=Q;
431
432 if (maxspalte<0) {
433   minimalHNE=1;
434   maxspalte=1;
435 }
436
437 number c,delta;
438 int p = char(basering);
439 string ringchar=charstr(basering);
440 map xytausch = basering,y,x;
441 if ((p!=0) and (ringchar != string(p))) {
442                            // coefficient field is extension of Z/pZ
443   execute "int n_elements="+ringchar[1,size(ringchar)-2]+";";
444                            // number of elements of actual ring
445   number generat=par(1);   // generator of the coefficient field of the ring
446 }
447
448
449 //========= Abfangen von unzulaessigen oder trivialen Eingaben ===============
450 //------------ Nullpolynom oder Einheit im Potenzreihenring: -----------------
451 if (f == 0) {"You have given me the zero-polynomial !"; Abbruch=1; Ausgabe=1;}
452 else {
453   intvec nm = getnm(f);
454   N = nm[1]; M = nm[2]; //Berechne Schnittpunkte Newtonpolygon mit Achsen
455   if (N == 0)
456   {" The given polynomial is a unit as power series!!"; Abbruch=1; Ausgabe=1;}
457   else {
458    if (N == -1) {"The HNE is x = 0"; Abbruch=1; Ausgabe=2; getauscht=1;}
459    else {
460     if (M == -1) {"The HNE is y = 0"; Abbruch=1; Ausgabe=2;}
461   }}
462   if (N+M==-2) {"Remark: The polynomial is divisible both by x and y,",
463                 "so it is not irreducible.";
464                 "The result of develop is only one of the existing HNE's.";
465   }
466 }
467 //--------------------- Test auf Quadratfreiheit -----------------------------
468 if (Abbruch==0) {
469
470 //-------- Fall basering==0,... : Wechsel in Ring mit char >0 ----------------
471 // weil squarefree eine Standardbasis berechnen muss (verwendet Syzygien)
472 // -- wenn f in diesem Ring quadratfrei ist, dann erst recht im Ring guenstig
473 //----------------------------------------------------------------------------
474
475  if ((p==0) and (size(charstr(basering))==1)) {
476   int testerg=(polytest(f)==0);
477   ring zweitring = 32003,(x,y),dp;
478   map polyhinueber=guenstig,x,y;     // fetch geht nicht
479   poly f=polyhinueber(f);
480   poly test_sqr=squarefree(f);
481   if (test_sqr != f) {
482    "Most probably the given polynomial is not squarefree. But the test was";
483    "made in characteristic 32003 and not 0 to improve speed. You can";
484    "(r) redo the test in char 0 (but this may take some time)";
485    "(c) continue the development, if you're sure that the polynomial",
486    "IS squarefree";
487    if (testerg==1) {
488      "(s) continue the development with a squarefree factor (*)";}
489    "(q) or just quit the algorithm (default action)";
490    "";"Please enter the letter of your choice:";
491    string str=read("")[1];
492    setring guenstig;
493    map polyhinueber=zweitring,x,y;
494    if (str=="r") {
495      poly test_sqr=squarefree(f);
496      if (test_sqr != f) {
497       "The given polynomial is in fact not squarefree.";
498       "I'll continue with the radical.";
499       pause;
500       f=test_sqr;
501      }
502      else {"everything is ok -- the polynomial is squarefree in char(k)=0";}
503    }
504    else {
505      if ((str=="s") and (testerg==1)) {
506       "(*) attention: it could be that the factor is only one in char 32003!";
507        f=polyhinueber(test_sqr);
508      }
509      else {
510        if (str<>"c") {
511          setring altring;kill guenstig;kill zweitring;
512          return(return_error);}
513        else { "if the algorithm doesn't terminate, you were wrong...";}
514    }}
515    kill zweitring;
516    nm = getnm(f);             // N,M haben sich evtl. veraendert
517    N = nm[1]; M = nm[2];      // Berechne Schnittpunkte Newtonpoly mit Achsen
518    if (defined(Protokoll)) {"I continue with the polynomial",f; }
519   }
520   else {
521     setring guenstig;
522     kill zweitring;
523   }
524  }
525 // ------------------- Fall Charakteristik > 0 -------------------------------
526  else {
527   poly test_sqr=squarefree(f);
528   if (test_sqr == 1) {
529    "The given polynomial is of the form g^"+string(p)+", therefore",
530    "reducible.";"Please try again.";
531    setring altring;
532    kill guenstig;
533    return(return_error);}
534   if (test_sqr != f) {
535    "The given polynomial is not squarefree. I'll continue with the radical.";
536    if (p != 0)
537     {"But if the polynomial contains a factor of the form g^"+string(p)+",";
538      "this factor will be lost.";}
539    pause;
540    f=test_sqr;
541    nm = getnm(f);              // N,M haben sich veraendert
542    N = nm[1]; M = nm[2];       // Berechne Schnittpunkte Newtonpoly mit Achsen
543    if (defined(Protokoll)) {"I continue with the polynomial",f; }
544   }
545
546  }                             // endelse(p==0)
547
548  if (N==0) {
549    " Sorry. The remaining polynomial is a unit in the power series ring...";
550    setring altring;kill guenstig;return(return_error);
551  }
552 //---------------------- gewaehrleiste, dass x transvers ist -----------------
553  if (M < N)
554  { f = xytausch(f);            // Variablentausch : x jetzt transvers
555    getauscht = 1;              // den Tausch merken
556    M = M+N; N = M-N; M = M-N;  // M, N auch vertauschen
557  }
558  if (defined(Protokoll)) {
559   if (getauscht) {"x<->y were exchanged; poly is now ",f;}
560   else           {"x , y were not exchanged";}
561   "M resp. N are now",M,N;
562  }
563 }                              // end(if Abbruch==0)
564
565 ideal a(0);
566 while (Abbruch==0) {
567
568 //================= Beginn der Schleife (eigentliche Entwicklung) ============
569
570 //------------------- ist das Newtonpolygon eine gerade Linie? ---------------
571  if (testreducible(f,N,M)) {
572    " The given polynomial is not irreducible";
573    kill guenstig;
574    setring altring;
575    return(return_error);       // Abbruch der Prozedur!
576  }
577  R = M%N;
578  Q = M / N;
579
580 //-------------------- Fall Rest der Division R = 0 : ------------------------
581  if (R == 0) {
582    c = koeff(f,0,N);
583    if (c == 0) {"Something has gone wrong! I didn't get N correctly!"; exit;}
584    e = gcd(M,N);
585 //----------------- Test, ob leitf = c*(y^N - delta*x^(m/e))^e ist -----------
586    if (p==0) {
587      delta = koeff(f,M/ e,N - N/ e) / (-1*e*c);
588      if (defined(Protokoll)) {"quasihomogeneous leading form:",
589         leit(f,N,M)," = ",c,"* (y -",delta,"* x^"+string(M/ e)+")^",e," ?";}
590      if (leit(f,N,M) != c*(y^(N/ e) - delta*x^(M/ e))^e)
591        { " The given Polynomial is reducible !"; Abbruch=1; Ausgabe=1;}
592    }
593    else {                     // p!=0
594      if (e%p != 0) {
595        delta = koeff(f,M/ e,N - N/ e) / (-1*e*c);
596        if (defined(Protokoll)) {"quasihomogeneous leading form:",
597           leit(f,N,M)," = ",c,"* (y -",delta,"* x^"+string(M/ e)+")^",e," ?";}
598        if (leit(f,N,M) != c*(y^(N/ e) - delta*x^(M/ e))^e)
599         { " The given Polynomial is reducible !"; Abbruch=1; Ausgabe=1;}
600      }
601
602      else {                   // e%p == 0
603        eps = e;
604        for (l = 0; eps%p == 0; l=l+1) { eps=eps/ p;}
605        if (defined(Protokoll)) {e," -> ",eps,"*",p,"^",l;}
606        delta = koeff(f,(M/ e)*p^l,(N/ e)*p^l*(eps-1)) / (-1*eps*c);
607
608        if ((ringchar != string(p)) and (delta != 0)) {
609 //- coeff. field is not Z/pZ => we`ve to correct delta by taking (p^l)th root-
610          if (delta == generat) {exponent=1;}
611          else {
612           if (delta == 1) {exponent=0;}
613           else {
614            exponent=pardeg(delta);
615
616 //-- an dieser Stelle kann ein Fehler auftreten, wenn wir eine transzendente -
617 //-- Erweiterung von Z/pZ haben: dann ist das hinzuadjungierte Element kein  -
618 //-- Erzeuger der mult. Gruppe, d.h. in Z/pZ (a) gibt es i.allg. keinen      -
619 //-- Exponenten mit z.B. a2+a = a^exp                                        -
620 //----------------------------------------------------------------------------
621          }}
622          delta = generat^(extgcd(n_elements-1,p^l)[3]*exponent);
623        }
624
625        if (defined(Protokoll)) {"quasihomogeneous leading form:",
626          leit(f,N,M)," = ",c,"* (y^"+string(N/ e),"-",delta,"* x^"
627          +string(M/ e)+")^",e,"  ?";}
628        if (leit(f,N,M) != c*(y^(N/ e) - delta*x^(M/ e))^e)
629          { " The given Polynomial is reducible !"; Abbruch=1; Ausgabe=1;}
630      }
631    }
632    if (Abbruch == 0) {
633      f = T1_Transform(f,delta,M/ e);
634      "a("+string(zeile)+","+string(Q)+") =",delta;
635      a(zeile)[Q]=delta;
636      if (defined(Protokoll)) {"transformed polynomial: ",f;}}
637
638      nm=getnm(f); N=nm[1]; M=nm[2];        // Neuberechnung des Newtonpolygons
639  }
640 //--------------------------- Fall R > 0 : -----------------------------------
641  else {
642    "h("+string(zeile)+") =",Q;
643    hqs[zeile+1]=Q;                  // denn zeile beginnt mit dem Wert 0
644    a(zeile)[Q+1]=x;                 // Markierung des Zeilenendes der HNE
645    maxspalte=maxspalte*((Q+1) < maxspalte) + (Q+1)*((Q+1) >= maxspalte);
646                                     // Anpassung der Sp.zahl der HNE-Matrix
647    f = T_Transform(f,Q,N);
648    if (defined(Protokoll)) {"transformed polynomial: ",f;}
649    zeile=zeile+1;
650 //------------ Bereitstellung von Speicherplatz fuer eine neue Zeile: --------
651    ideal a(zeile);
652    M=N;N=R;
653  }
654
655 //--------------- schneidet das Newtonpolygon beide Achsen? ------------------
656  if (M==-1) {
657     "The HNE is finite!";
658     a(zeile)[Q+1]=x;   // Markiere das Ende der Zeile
659     hqs[zeile+1]=Q;
660     maxspalte=maxspalte*((Q+1) < maxspalte) + (Q+1)*((Q+1) >= maxspalte);
661     f=0;               // transformiertes Polynom wird nicht mehr gebraucht
662     Abbruch=1;
663  }
664  else {if (M<N) {"Something has gone wrong: M<N";}}
665  if(defined(Protokoll)) {"new M,N:",M,N;}
666
667 //----------------- Abbruchbedingungen fuer die Schleife: --------------------
668  if ((N==1) and (Abbruch!=1) and ((M > maxspalte) or (minimalHNE==1))
669      and (size(a(zeile))>0))
670 //----------------------------------------------------------------------------
671 // Abbruch, wenn die Matrix so voll ist, dass eine neue Spalte angefangen
672 // werden muesste und die letzte Zeile nicht nur Nullen enthaelt
673 // oder wenn die Matrix nicht voll gemacht werden soll (minimale Information)
674 //----------------------------------------------------------------------------
675   { Abbruch=1; hqs[zeile+1]=-1;
676     if (maxspalte < ncols(a(zeile))) { maxspalte=ncols(a(zeile));}
677     if ((minimalHNE==1) and (M <= maxspalte)) {
678 // teile param mit, dass Eintraege der letzten Zeile nur teilw. richtig sind:-
679       hqs[zeile+1]=-M;
680 //------------- markiere den Rest der Zeile als unbekannt: -------------------
681       for (R=M; R <= maxspalte; R++) { a(zeile)[R]=y;}
682     }                  // R wird nicht mehr gebraucht
683   }
684 //========================= Ende der Schleife ================================
685
686 }
687 setring altring;
688 if (Ausgabe == 0) {
689 //-------------------- Ergebnis in den alten Ring transferieren: -------------
690   map zurueck=guenstig,maxideal(1)[1],maxideal(1)[2];
691   matrix amat[zeile+1][maxspalte];
692   ideal uebergabe;
693   for (e=0; e<=zeile; e=e+1) {
694     uebergabe=zurueck(a(e));
695     if (ncols(uebergabe) > 1) {
696      amat[e+1,1..ncols(uebergabe)]=uebergabe;}
697     else {amat[e+1,1]=uebergabe[1];}
698   }
699   if (ringwechsel) { f=zurueck(f); }
700 }
701
702 kill guenstig;
703 if (Ausgabe == 0) { return(list(amat,hqs,getauscht,f));}
704 if (Ausgabe == 1) { return(return_error);}             // error has occurred
705 if (Ausgabe == 2) { return(list(matrix(ideal(0,x)),intvec(1),getauscht,
706                                 poly(0)));}            // HNE is x=0 or y=0
707}
708example
709{ "EXAMPLE:"; echo = 2;
710  ring exring = 7,(x,y),ds;
711  list hne=develop(4x98+2x49y7+x11y14+2y14);
712  print(hne[1]);
713  // therefore the HNE is:
714  // z(-1)= 3*z(0)^7 + z(0)^7*z(1),
715  // z(0) = z(1)*z(2),   (note that there is  1 zero   in the 2nd row before x)
716  // z(1) = z(2)^3*z(3), (note that there are 3 zeroes in the 3rd row before x)
717  // z(2) = z(3)*z(4),
718  // z(3) = -z(4)^2 + 0*z(4)^3 +...+ 0*z(4)^8 + ?*z(4)^9 + ...
719  //   (the missing x in the matrix indicates that this line is not complete.
720  //    It can only occur in the last line of the HNE, and normally does.)
721  hne[2]; pause;
722  param(hne);
723  // returns the parametrisation x(t)= -t14+O(t21), y(t)= -3t98+O(t105)
724  // (the term -t109 in y may have a wrong coefficient)
725  displayHNE(hne);
726}
727
728///////////////////////////////////////////////////////////////////////////////
729
730proc param
731USAGE:  param(l) takes the output of develop(f)
732        (list l (matrix m, intvec v, int s[,poly g]))
733        and gives a parametrisation for f; the first variable of the active
734        ring is chosen as indefinite. If the ring contains more than
735        two variables, the 3rd variable is chosen (remember that develop takes
736        the first two variables and therefore the other vars should be unused)
737RETURN: ideal of two polynomials: if the HNE was finite, f(param[1],param[2])
738        will be  zero. If not, the real parametrisation will be
739        two power series; then param will return a truncation of these series.
740EXAMPLE: example param;      shows an example
741         example develop;   shows another example
742
743{
744 //-------------------------- Initialisierungen -------------------------------
745 matrix m=#[1];
746 intvec v=#[2];
747 int switch=#[3];
748 if (switch==-1) {
749   "An error has occurred in develop, so there is no HNE.";
750   return(ideal(0,0));
751 }
752 int fehler,fehlervor,untergrad,untervor,beginn,i,zeile,hilf;
753
754 if (nvars(basering) > 2) { poly z(size(v)+1)=var(3); }
755 else                     { poly z(size(v)+1)=var(1); }
756 poly z(size(v));
757 zeile=size(v);
758 //------------- Parametrisierung der untersten Zeile der HNE -----------------
759 if (v[zeile] > 0) {
760   fehler=0;           // die Parametrisierung wird exakt werden
761   for (i=1; i<=v[zeile]; i++) {
762     z(zeile)=z(zeile)+m[zeile,i]*z(zeile+1)^i;
763 }}
764 else {
765   untervor=1;         // = Untergrad der vorhergehenden Zeile
766   if (v[zeile]==-1) {
767     fehler=ncols(m)+1;
768     for (i=1; i<=ncols(m); i++) {
769       z(zeile)=z(zeile)+m[zeile,i]*z(zeile+1)^i;
770       if ((untergrad==0) and (m[zeile,i]!=0)) {untergrad=i;}
771                       // = Untergrad der aktuellen Zeile
772   }}
773   else {
774     fehler= -v[zeile];
775     for (i=1; i<-v[zeile]; i++) {
776       z(zeile)=z(zeile)+m[zeile,i]*z(zeile+1)^i;
777       if ((untergrad==0) and (m[zeile,i]!=0)) {untergrad=i;}
778   }}
779 }
780 //------------- Parametrisierung der restlichen Zeilen der HNE ---------------
781 for (zeile=size(v)-1; zeile>0; zeile--) {
782   poly z(zeile);
783   beginn=0;             // Beginn der aktuellen Zeile
784   for (i=1; i<=v[zeile]; i++) {
785     z(zeile)=z(zeile)+m[zeile,i]*z(zeile+1)^i;
786     if ((beginn==0) and (m[zeile,i]!=0)) { beginn=i;}
787   }
788   z(zeile)=z(zeile) + z(zeile+1)^v[zeile] * z(zeile+2);
789   if (beginn==0) {
790     if (fehler>0) {     // damit fehler=0 bleibt bei exakter Param.
791     fehlervor=fehler;   // Fehler der letzten Zeile
792     fehler=fehler+untergrad*(v[zeile]-1)+untervor;   // Fehler dieser Zeile
793     hilf=untergrad;
794     untergrad=untergrad*v[zeile]+untervor;
795     untervor=hilf;}}    // untervor = altes untergrad
796   else {
797     fehlervor=fehler;
798     fehler=fehler+untergrad*(beginn-1);
799     untervor=untergrad;
800     untergrad=untergrad*beginn;
801 }}
802 //--------------------- Ausgabe der Fehlerabschaetzung -----------------------
803 if (switch==0) {
804   if (fehler>0) {
805     if (fehlervor>0)
806      { "// ** Warning: result is exact up to order",fehlervor-1,"in",
807        maxideal(1)[1],"and",fehler-1,"in",maxideal(1)[2],"!";}
808     else { "// ** Warning: result is exact up to order",fehler-1,"in",
809        maxideal(1)[2],"!";}}
810   return(ideal(z(2),z(1)));}
811 else {
812   if (fehler>0) {
813     if (fehlervor>0)
814      { "// ** Warning: result is exact up to order",fehler-1,"in",
815        maxideal(1)[1],"and",fehlervor-1,"in",maxideal(1)[2],"!";}
816     else { "// ** Warning: result is exact up to order",fehler-1,"in",
817        maxideal(1)[1],"!";}}
818   return(ideal(z(1),z(2)));}
819}
820example
821{ "EXAMPLE:"; echo = 2;
822 ring exring=0,(x,y,t),ds;
823 poly f=x3+2xy2+y2;
824 list hne=develop(f);
825 list hne_extended1=develop(f,6);
826 list hne_extended2=develop(f,10);
827 pause;
828                                   //   compare the different matrices ...
829 print(hne[1]);
830 print(hne_extended1[1]);
831 print(hne_extended2[1]);
832                                   // ... and the resulting parametrizations:
833 param(hne);
834 param(hne_extended1);
835 param(hne_extended2);
836}
837///////////////////////////////////////////////////////////////////////////////
838
839proc invariants
840USAGE:  invariants(l) takes the output of develop(f)
841        (list l (matrix m, intvec v, int s[,poly g]))
842        and computes some invariants:
843RETURN:  a list, if l contains a valid HNE:
844    - invariants(l)[1]: intvec         (characteristic exponents)
845    - invariants(1)[2],[3]: 2 x intvec (puiseux pairs, 1st and 2nd components)
846    - invariants(l)[4]: int            (degree of the conductor)
847    - invariants(l)[5]: intvec         (sequence of multiplicities)
848         an empty list, if an error occurred in the procedure develop
849EXAMPLE: example invariants; shows an example
850{
851 //-------------------------- Initialisierungen -------------------------------
852 matrix m=#[1];
853 intvec v=#[2];
854 int switch=#[3];
855 list ergebnis;
856 if (switch==-1) {
857   "An error has occurred in develop, so there is no HNE.";
858   return(ergebnis);
859 }
860 intvec beta,s,svorl,ordnung,multips,multseq,mpuiseux,npuiseux;
861 int genus,zeile,i,j,k,summe,conductor,ggT;
862 string Ausgabe;
863 int nc=ncols(m); int nr=nrows(m);
864 ordnung[nr]=1;
865         // alle Indizes muessen (gegenueber [Ca]) um 1 erhoeht werden,
866         // weil 0..r nicht als Wertebereich erlaubt ist (aber nrows(m)==r+1)
867
868 //---------------- Bestimme den Untergrad der einzelnen Zeilen ---------------
869 for (zeile=nr; zeile>1; zeile--) {
870   if ((size(ideal(m[zeile,1..nc])) > 1) or (zeile==nr)) { // keine Nullzeile
871      k=1;
872      while (m[zeile,k]==0) {k++;}
873      ordnung[zeile-1]=k*ordnung[zeile]; // vgl. auch Def. von untergrad in
874      genus++;                           // proc param
875      svorl[genus]=zeile;} // werden gerade in umgekehrter Reihenfolge abgelegt
876   else {
877      ordnung[zeile-1]=v[zeile]*ordnung[zeile]+ordnung[zeile+1];
878 }}
879 //----------------- charakteristische Exponenten (beta) ----------------------
880 s[1]=1;
881 for (k=1; k <= genus; k++) { s[k+1]=svorl[genus-k+1];} // s[2]==s(1), u.s.w.
882 beta[1]=ordnung[1]; //charakt. Exponenten: Index wieder verschoben
883 for (k=1; k <= genus; k++) {
884   summe=0;
885   for (i=1; i <= s[k]; i++) {summe=summe+v[i]*ordnung[i];}
886   beta[k+1]=summe+ordnung[s[k]]+ordnung[s[k]+1]-ordnung[1];
887 }
888 //--------------------------- Puiseuxpaare -----------------------------------
889 int produkt=1;
890 for (i=1; i<=genus; i++) {
891   ggT=gcd(beta[1],beta[i+1]*produkt);
892   mpuiseux[i]=beta[i+1]*produkt / ggT;
893   npuiseux[i]=beta[1] / ggT;
894   produkt=produkt*npuiseux[i];
895 }
896 //---------------------- Grad des Konduktors ---------------------------------
897 summe=1-ordnung[1];
898 if (genus > 0) {
899   for (i=2; i <= genus+1; i++) {
900     summe=summe + beta[i] * (ordnung[s[i-1]] - ordnung[s[i]]);
901   }                              // n.b.: Indizierung wieder um 1 verschoben
902 }
903 conductor=summe;
904 //------------------- Multiplizitaetensequenz: -------------------------------
905 k=1;
906 multips=multiplicities(#);
907 for (i=1; i<size(v); i++) {
908   for (j=1; j<=v[i]; j++) {
909     multseq[k]=multips[i];
910     k++;
911 }}
912 multseq[k]=1;
913 //------------------------- Rueckgabe ----------------------------------------
914 ergebnis=beta,mpuiseux,npuiseux,conductor,multseq;
915 return(ergebnis);
916}
917example
918{ "EXAMPLE:"; echo = 2;
919 ring exring=0,(x,y),dp;
920 list hne=develop(y4+2x3y2+x6+x5y);
921 list erg=invariants(hne);
922 erg[1];                   // the characteristic exponents
923 erg[2],erg[3];            // the puiseux pairs in packed form
924 erg[4] / 2;               // the delta-invariant
925 erg[5];                   // the sequence of multiplicities
926                           // To display the invariants more 'nicely':
927 displayInvariants(hne);
928}
929///////////////////////////////////////////////////////////////////////////////
930
931proc displayInvariants
932USAGE:   displayInvariants(l); takes the output both of
933         develop(f) and reddevelop(f)
934          ( list l (matrix m, intvec v, int s[,poly g])
935            or list of lists in the form l            )
936DISPLAY: invariants of the corresponding branch, resp. of all branches,
937         in a better readable form
938RETURN:  nothing
939EXAMPLE: example displayInvariants;  shows an example
940{
941 int i,j,k,mul;
942 string Ausgabe;
943 list ergebnis;
944 //-- entferne ueberfluessige Daten zur Erhoehung der Rechengeschwindigkeit: --
945 #=stripHNE(#);
946 //-------------------- Ausgabe eines Zweiges ---------------------------------
947 if (typeof(#[1])=="matrix") {
948   ergebnis=invariants(#);
949   if (size(ergebnis)!=0) {
950    " characteristic exponents  :",ergebnis[1];
951    if (size(ergebnis[1])>1) {
952     for (i=1; i<=size(ergebnis[2]); i++) {
953       Ausgabe=Ausgabe+"("+string(ergebnis[2][i])+","
954       +string(ergebnis[3][i])+")";
955    }}
956    " puiseux pairs             :",Ausgabe;
957    " degree of the conductor   :",ergebnis[4];
958    " delta invariant           :",ergebnis[4]/2;
959    " generators of semigroup   :",puiseux2generators(ergebnis[2],ergebnis[3]);
960    " sequence of multiplicities:",ergebnis[5];
961 }}
962 //-------------------- Ausgabe aller Zweige ----------------------------------
963 else {
964  for (j=1; j<=size(#); j++) {
965    ergebnis=invariants(#[j]);
966    " --- invariants of branch number",j,": ---";
967    " characteristic exponents  :",ergebnis[1];
968    Ausgabe="";
969    if (size(ergebnis[1])>1) {
970     for (i=1; i<=size(ergebnis[2]); i++) {
971       Ausgabe=Ausgabe+"("+string(ergebnis[2][i])+","
972       +string(ergebnis[3][i])+")";
973    }}
974    " puiseux pairs             :",Ausgabe;
975    " degree of the conductor   :",ergebnis[4];
976    " delta invariant           :",ergebnis[4]/2;
977    " generators of semigroup   :",puiseux2generators(ergebnis[2],ergebnis[3]);
978    " sequence of multiplicities:",ergebnis[5];
979    "";
980  }
981  if (size(#)>1) {
982    " -------------- intersection multiplicities : -------------- ";"";
983    Ausgabe="branch |   ";
984    for (j=size(#); j>1; j--) {
985      if (size(string(j))==1) { Ausgabe=Ausgabe+" "+string(j)+"    "; }
986      else                    { Ausgabe=Ausgabe+string(j)+"    "; }
987    }
988    Ausgabe;
989    Ausgabe="-------+";
990    for (j=2; j<size(#); j++) { Ausgabe=Ausgabe+"------"; }
991    Ausgabe=Ausgabe+"-----";
992    Ausgabe;
993  }
994  for (j=1; j<size(#); j++) {
995    if (size(string(j))==1) { Ausgabe="    "+string(j)+"  |"; }
996    else                    { Ausgabe="   " +string(j)+"  |"; }
997    for (k=size(#); k>j; k--) {
998      mul=intersection(#[j],#[k]);
999      for (i=1; i<=5-size(string(mul)); i++) { Ausgabe=Ausgabe+" "; }
1000      Ausgabe=Ausgabe+string(mul);
1001      if (k>j+1) { Ausgabe=Ausgabe+","; }
1002    }
1003    Ausgabe;
1004  }
1005 }
1006 return();
1007}
1008example
1009{ "EXAMPLE:"; echo = 2;
1010 ring exring=0,(x,y),dp;
1011 list hne=develop(y4+2x3y2+x6+x5y);
1012 displayInvariants(hne);
1013}
1014///////////////////////////////////////////////////////////////////////////////
1015
1016proc multiplicities
1017USAGE:   multiplicities(l) takes the output of develop(f)
1018         (list l (matrix m, intvec v, int s[,poly g]))
1019RETURN:  intvec of the different multiplicities that occur during the succes-
1020         sive blowing up of the curve corresponding to f
1021EXAMPLE: example multiplicities;  shows an example
1022{
1023 matrix m=#[1];
1024 intvec v=#[2];
1025 int switch=#[3];
1026 list ergebnis;
1027 if (switch==-1) {
1028   "An error has occurred in develop, so there is no HNE.";
1029   return(intvec(0));
1030 }
1031 intvec ordnung;
1032 int zeile,k;
1033 int nc=ncols(m); int nr=nrows(m);
1034 ordnung[nr]=1;
1035 //---------------- Bestimme den Untergrad der einzelnen Zeilen ---------------
1036 for (zeile=nr; zeile>1; zeile--) {
1037   if ((size(ideal(m[zeile,1..nc])) > 1) or (zeile==nr)) { // keine Nullzeile
1038      k=1;
1039      while (m[zeile,k]==0) {k++;}
1040      ordnung[zeile-1]=k*ordnung[zeile];
1041   }
1042   else {
1043      ordnung[zeile-1]=v[zeile]*ordnung[zeile]+ordnung[zeile+1];
1044 }}
1045 return(ordnung);
1046}
1047example
1048{ "EXAMPLE:"; echo = 2;
1049  ring r=0,(x,y),dp;
1050  multiplicities(develop(x5+y7));
1051  // The first value is the multiplicity of the curve itself, here it's 5
1052}
1053///////////////////////////////////////////////////////////////////////////////
1054
1055proc puiseux2generators (intvec m, intvec n)
1056USAGE:   puiseux2generators (m,n);
1057         m,n intvecs with 1st resp. 2nd components of puiseux pairs
1058RETURN:  intvec of the generators of the semigroup of values
1059EXAMPLE: example puiseux2generators;  shows an example
1060{
1061 intvec beta;
1062 int q=1;
1063 //------------ glatte Kurve (eigentl. waeren m,n leer): ----------------------
1064 if (m==0) { return(intvec(1)); }
1065 //------------------- singulaere Kurve: --------------------------------------
1066 for (int i=1; i<=size(n); i++) { q=q*n[i]; }
1067 beta[1]=q; // == q_0
1068 m=1,m; n=1,n; // m[1] ist damit m_0 usw., genau wie beta[1]==beta_0
1069 for (i=2; i<=size(n); i++) {
1070  beta[i]=m[i]*q/n[i] - m[i-1]*q + n[i-1]*beta[i-1];
1071  q=q/n[i]; // == q_i
1072 }
1073 return(beta);
1074}
1075example
1076{ "EXAMPLE:"; echo = 2;
1077  // take (3,2),(7,2),(15,2),(31,2),(63,2),(127,2) as puiseux pairs:
1078  puiseux2generators(intvec(3,7,15,31,63,127),intvec(2,2,2,2,2,2));
1079}
1080///////////////////////////////////////////////////////////////////////////////
1081
1082proc generators
1083USAGE:   generators(l); takes the output of develop(f)
1084         (list l (matrix m, intvec v, int s[,poly g]))
1085RETURN:  intvec of the generators of the semigroup of values
1086EXAMPLE: example generators;  shows an example
1087{
1088 list inv=invariants(#);
1089 return(puiseux2generators(inv[2..3]));
1090}
1091example
1092{ "EXAMPLE:"; echo = 2;
1093  ring r=0,(x,y),dp;
1094  poly f=x15-21x14+8x13y-6x13-16x12y+20x11y2-1x12+8x11y-36x10y2+24x9y3+4x9y2
1095         -16x8y3+26x7y4-6x6y4+8x5y5+4x3y6-1y8;
1096  list hne=develop(f);
1097  generators(hne);
1098}
1099///////////////////////////////////////////////////////////////////////////////
1100
1101proc intersection (list hn1, list hn2)
1102USAGE:   intersection(hne1,hne2);
1103         hne1,hne2 two lists representing a HNE (normally two entries out of
1104         the output of reddevelop), i.e. list(matrix,intvec,int[,poly])
1105RETURN:  intersection multiplicity of the branches corresponding to hne1 & hne2
1106         (of type int)
1107EXAMPLE: example intersection;  shows an example
1108{
1109 //------------------ `intersect' ist schon reserviert ... --------------------
1110 int i,j,s,sum,schnitt,unterschied;
1111 matrix a1=hn1[1];
1112 matrix a2=hn2[1];
1113 intvec h1=hn1[2];
1114 intvec h2=hn2[2];
1115 intvec n1=multiplicities(hn1);
1116 intvec n2=multiplicities(hn2);
1117 if (hn1[3]!=hn2[3]) {
1118 //-- die jeweils erste Zeile von hn1,hn2 gehoert zu verschiedenen Parametern -
1119 //---------------- d.h. beide Kurven schneiden sich transversal --------------
1120   schnitt=n1[1]*n2[1];        // = mult(hn1)*mult(hn2)
1121 }
1122 else {
1123 //--------- die jeweils erste Zeile gehoert zum gleichen Parameter -----------
1124   unterschied=0;
1125 //h1[1],h2[1];size(h1),size(h2);
1126   for (s=1; (h1[s]==h2[s]) && (s<size(h1)) && (s<size(h2))
1127              && (unterschied==0); s++) {
1128     for (i=1; (a1[s,i]==a2[s,i]) && (i<=h1[s]); i++) {;}
1129     if (i<=h1[s]) {
1130       unterschied=1;
1131       s--;                    // um s++ am Schleifenende wieder auszugleichen
1132     }
1133   }
1134   if (unterschied==0) {
1135     if ((s<size(h1)) && (s<size(h2))) {
1136       for (i=1; (a1[s,i]==a2[s,i]) && (i<=h1[s]) && (i<=h2[s]); i++) {;}
1137     }
1138     else {
1139 //-------------- Sonderfall: Unterschied in letzter Zeile suchen -------------
1140 // Beachte: Es koennen undefinierte Stellen auftreten, bei abbrechender HNE
1141 // muss die Ende-Markierung weg, h_[r] ist unendlich, die Matrix muss mit
1142 // Nullen fortgesetzt gedacht werden
1143 //----------------------------------------------------------------------------
1144       if (ncols(a1)>ncols(a2)) { j=ncols(a1); }
1145       else                     { j=ncols(a2); }
1146       unterschied=0;
1147       if ((h1[s]>0) && (s==size(h1))) {
1148         a1[s,h1[s]+1]=0;
1149         if (ncols(a1)<=ncols(a2)) { unterschied=1; }
1150       }
1151       if ((h2[s]>0) && (s==size(h2))) {
1152         a2[s,h2[s]+1]=0;
1153         if (ncols(a2)<=ncols(a1)) { unterschied=1; }
1154       }
1155       if (unterschied==1) {                   // mind. eine HNE war endlich
1156         matrix ma1[1][j]=a1[s,1..ncols(a1)];  // und bedarf der Fortsetzung
1157         matrix ma2[1][j]=a2[s,1..ncols(a2)];  // mit Nullen
1158       }
1159       else {
1160         if (ncols(a1)>ncols(a2)) { j=ncols(a2); }
1161         else                     { j=ncols(a1); }
1162         matrix ma1[1][j]=a1[s,1..j];          // Beschr. auf vergleichbaren
1163         matrix ma2[1][j]=a2[s,1..j];          // Teil (der evtl. y's enth.)
1164       }
1165 // print(ma1);print(ma2);
1166       for (i=1; (ma1[1,i]==ma2[1,i]) && (i<j) && (ma1[1,i]!=var(2)); i++) {;}
1167       if (ma1[1,i]==ma2[1,i]) {
1168         "//** The two HNE's are identical!";
1169         "//** You have either tried to intersect a branch with itself,";
1170         "//** or the two branches have been developed separately.";
1171         "//   In the latter case use `extdevelop' to extend the HNE's until",
1172         "they differ.";
1173         return(-1);
1174       }
1175       if ((ma1[1,i]==var(2)) || (ma2[1,i]==var(2))) {
1176         "//** The two HNE's are (so far) identical. This is because they",
1177         "have been";
1178         "//** computed separately. I need more data; use `extdevelop' to",
1179         "extend them,";
1180         if (ma1[1,i]==var(2)) {"//** at least the first one.";}
1181         else                  {"//** at least the second one.";}
1182         return(-1);
1183       }
1184     }
1185   }
1186   sum=0;
1187   h1[size(h1)]=ncols(a1)+42;        // Ersatz fuer h1[r]=infinity
1188   h2[size(h2)]=ncols(a2)+42;
1189   for (j=1; j<s; j++) {sum=sum+h1[j]*n1[j]*n2[j];}
1190   if ((i<=h1[s]) && (i<=h2[s]))    { schnitt=sum+i*n1[s]*n2[s]; }
1191   if (i==h2[s]+1) { schnitt=sum+h2[s]*n1[s]*n2[s]+n2[s+1]*n1[s]; }
1192   if (i==h1[s]+1) { schnitt=sum+h1[s]*n2[s]*n1[s]+n1[s+1]*n2[s]; }
1193 // "s:",s-1,"i:",i,"S:",sum;
1194 }
1195 return(schnitt);
1196}
1197example
1198{
1199  if (nameof(basering)=="HNEring") {
1200   def rettering=HNEring;
1201   kill HNEring;
1202  }
1203  "EXAMPLE:"; echo = 2;
1204  ring r=0,(x,y),dp;
1205  list hne=reddevelop((x2-y3)*(x2+y3));
1206  intersection(hne[1],hne[2]);
1207  kill HNEring,r;
1208  echo = 0;
1209  if (defined(rettering)) { // wenn aktueller Ring vor Aufruf von example
1210   setring rettering;       // HNEring war, muss dieser erst wieder restauriert
1211   def HNEring=rettering;   // werden
1212   export HNEring;
1213  }
1214}
1215///////////////////////////////////////////////////////////////////////////////
1216
1217proc displayHNE(list ldev,list #)
1218USAGE:   displayHNE(ldev,[,n]); ldev=list
1219         (output list of develop(f) or reddevelop(f)), n=int
1220RETURN:  - if only one argument is given, no return value, but
1221         display an ideal HNE of the following form:
1222            HNE[1]=-y+[]*z(0)^1+[]*z(0)^2+...+z(0)^<>*z(1)
1223            HNE[2]=-x+          []*z(1)^2+...+z(1)^<>*z(2)
1224            HNE[3]=             []*z(2)^2+...+z(2)^<>*z(3)
1225            .......             ..........................
1226            HNE[r+1]=           []*z(r)^2+[]*z(r)^3+......
1227     where x,y are the indeterminates of the basering. The values of [] are
1228     the coefficients of the Hamburger-Noether matrix, the values of <> are
1229     represented in the HN-matrix as 'x'
1230         the 1st line (HNE[1]) means that y==[]*z(0)^1+... ,
1231         the 2nd line (HNE[2]) means that x==[]*z(1)^1+...
1232     so you can see which indeterminate corresponds to which line
1233     (it's also possible that x corresponds to the 1st line and y to the 2nd)
1234         - if a second argument is given, create and export a new ring with
1235         name 'displayring' containing an ideal 'HNE' as described above
1236
1237     If ldev contains the output of reddevelop(f), displayHNE shows the HNE's
1238     of all branches of f in the form described above.
1239     The optional parameter is then ignored.
1240EXAMPLE: example displayHNE; shows an example
1241{
1242 if ((typeof(ldev[1])=="list") || (typeof(ldev[1])=="none")) {
1243   for (int i=1; i<=size(ldev); i++) {
1244     "// Hamburger-Noether development of branch nr."+string(i)+":";
1245     displayHNE(ldev[i]);"";
1246   }
1247   return();
1248 }
1249 //--------------------- Initialisierungen und Ringwechsel --------------------
1250 matrix m=ldev[1];
1251 intvec v=ldev[2];
1252 int switch=ldev[3];
1253 if (switch==-1) {
1254   "An error has occurred in develop, so there is no HNE.";
1255   return(ideal(0));
1256 }
1257 if (parstr(basering)!="") {
1258   if (charstr(basering)!=string(char(basering))+","+parstr(basering)) {
1259     "Sorry -- not implemented for rings of type (p^k,a),...";
1260     return(ideal(0));
1261   }
1262 }
1263 def altring=basering;
1264 ring dazu=char(altring),z(0..size(v)-1),ls;
1265 def displayring=dazu+altring;
1266 setring displayring;
1267 if (size(#) != 0) {
1268    export displayring;
1269  }
1270 map holematrix=altring,0;        // mappt nur die Monome vom Grad Null
1271 matrix m=holematrix(m);
1272 //--------------------- Erzeuge Matrix n mit n[i,j]=z(j-1)^i -----------------
1273 int i;
1274 matrix n[ncols(m)][nrows(m)];
1275 for (int j=1; j<=nrows(m); j++) {
1276    for (i=1; i<=ncols(m); i++) { n[i,j]=z(j-1)^i; }
1277 }
1278 matrix displaymat=m*n;
1279 ideal HNE;
1280 for (i=1; i<nrows(m); i++) { HNE[i]=displaymat[i,i]+z(i)*z(i-1)^v[i]; }
1281 HNE[nrows(m)]=displaymat[nrows(m),nrows(m)];
1282 if (nrows(m)<2) { HNE[2]=z(0); }
1283 if (switch==0) {
1284    HNE[1] = HNE[1]-var(size(v)+2);
1285    HNE[2] = HNE[2]-var(size(v)+1);
1286 }
1287 else {
1288    HNE[1] = HNE[1]-var(size(v)+1);
1289    HNE[2] = HNE[2]-var(size(v)+2);
1290 }
1291if (size(#) == 0) {
1292   HNE;
1293   return();
1294 }
1295if (size(#) != 0) {
1296   "// basering is now 'displayring' containing ideal 'HNE'";
1297   keepring(displayring);
1298   export(HNE);
1299   return(HNE);
1300 }
1301}
1302example
1303{ "EXAMPLE:"; echo = 2;
1304  ring r=0,(x,y),dp;
1305  poly f=x3+2xy2+y2;
1306  list hn=develop(f);
1307  displayHNE(hn);
1308}
1309///////////////////////////////////////////////////////////////////////////////
1310//                      procedures for reducible curves                      //
1311///////////////////////////////////////////////////////////////////////////////
1312
1313
1314proc newtonhoehne (poly f)
1315USAGE:   newtonhoehne(f);   f poly
1316ASSUME:  basering = ...,(x,y),ds  or ls
1317RETURN:  list of intvec(x,y) of coordinates of the newtonpolygon of f
1318NOTE:    This proc is only available in versions of Singular that know the
1319         command  system("newton",f);  f poly
1320{
1321 intvec nm = getnm(f);
1322 if ((nm[1]>0) && (nm[2]>0)) { f=jet(f,nm[1]*nm[2],nm); }
1323 list erg=system("newton",f);
1324 int i; list Ausgabe;
1325 for (i=1; i<=size(erg); i++) { Ausgabe[i]=leadexp(erg[i]); }
1326 return(Ausgabe);
1327}
1328///////////////////////////////////////////////////////////////////////////////
1329
1330proc newtonpoly (poly f)
1331USAGE:   newtonpoly(f);   f poly
1332RETURN:  list of intvec(x,y) of coordinates of the newtonpolygon of f
1333NOTE: There are many assumptions: (to improve speed)
1334      - The basering must be ...,(x,y),ls
1335      - f(x,0) != 0 != f(0,y), f(0,0) = 0
1336EXAMPLE: example newtonpoly;  shows an example
1337{
1338 intvec A=(0,ord(subst(f,x,0)));
1339 intvec B=(ord(subst(f,y,0)),0);
1340 intvec C,D,H; list L;
1341 int abbruch,i;
1342 poly hilf;
1343
1344 L[1]=A;
1345 //-------- wirf alle Monome auf oder oberhalb der Geraden AB raus: -----------
1346 f=jet(f,A[2]*B[1]-1,intvec(A[2],B[1]));
1347 map xytausch=basering,y,x;
1348 for (i=2; f!=0; i++) {
1349   abbruch=0;
1350   while (abbruch==0) {
1351 // finde den Punkt aus {verbliebene Pkte (a,b) mit a minimal} mit b minimal: -
1352
1353     C=leadexp(f);           // Ordnung ls ist wesentlich!
1354
1355     if (jet(f,A[2]*C[1]-A[1]*C[2]-1,intvec(A[2]-C[2],C[1]-A[1]))==0)
1356       { abbruch=1; }        // keine Monome unterhalb der Geraden AC
1357
1358 // ----- alle Monome auf der Parallelen zur y-Achse durch C wegwerfen: -------
1359 // ------------------ (links von C gibt es sowieso keine mehr) ---------------
1360     else { f=jet(f,-C[1]-1,intvec(-1,0)); }
1361   }
1362 //- finde alle Monome auf der Geraden durch A und C (unterhalb gibt's keine) -
1363   hilf=jet(f,A[2]*C[1]-A[1]*C[2],intvec(A[2]-C[2],C[1]-A[1]));
1364       
1365   H=leadexp(xytausch(hilf));
1366   D=H[2],H[1];
1367
1368 // die Alternative waere ein Ringwechsel nach ..,(y,x),ds gewesen
1369 // D ist der naechste Eckpunkt (unterster Punkt auf Geraden durch A,C)
1370
1371   L[i]=D;
1372   A=D;
1373 //----------------- alle Monome auf oder unterhalb DB raus -------------------
1374   f=jet(f,D[2]*B[1]-1,intvec(D[2],B[1]-D[1]));
1375 }
1376 L[i]=B;
1377 return(L);
1378}
1379example
1380{ "EXAMPLE:";
1381  ring @exring_Newt=0,(x,y),ls;
1382  export @exring_Newt;
1383  "  ring exring=0,(x,y),ls;";
1384  echo = 2;
1385  poly f=x5+2x3y-x2y2+3xy5+y6-y7;
1386  newtonpoly(f);
1387  echo = 0;
1388  kill @exring_Newt;
1389}
1390///////////////////////////////////////////////////////////////////////////////
1391
1392proc charPoly(poly f, int M, int N)
1393USAGE:  charPoly(f,M,N);  f poly in x,y,  M,N int: length and height
1394                          of newtonpolygon of f, which has to be only one line
1395RETURN:  the characteristic polynomial of f
1396EXAMPLE: example charPoly;  shows an example
1397{
1398 poly charp;
1399 int Np=N/ gcd(M,N);
1400 f=subst(f,x,1);
1401 for(charp=0; f<>0; f=f-lead(f))
1402  { charp=charp+leadcoef(f)*y^(leadexp(f)[2]/ Np);}
1403 return(charp);
1404}
1405example
1406{ "EXAMPLE:"; echo = 2;
1407  ring exring=0,(x,y),dp;
1408  charPoly(y4+2y3x2-yx6+x8,8,4);
1409  charPoly(y6+3y3x2-x4,4,6);
1410}
1411///////////////////////////////////////////////////////////////////////////////
1412
1413proc find_in_list(list L,int p)
1414USAGE:  find_in_list(L,p); L: list of intvec(x,y)
1415        (sorted in y: L[1][2]>=L[2][2]), int p >= 0
1416RETURN: int i: L[i][2]=p if existent; otherwise i with L[i][2]<p if existent;
1417        otherwise i = size(L)+1;
1418{
1419 int i;
1420 L[size(L)+1]=intvec(0,-1);          // falls p nicht in L[.][2] vorkommt
1421 for (i=1; L[i][2]>p; i++) {;}
1422 return(i);
1423}
1424///////////////////////////////////////////////////////////////////////////////
1425proc set_list
1426USAGE: set_list(L,v,l); L list, v intvec, l element of L (arbitrary type)
1427RETURN: L with L[v[1]][v[2]][...][v[n]] set to l
1428WARNING: Make sure there is no conflict of types!
1429         size(v) must be bigger than 1! (i.e. v must NOT be simply an integer)
1430EXAMPLE:                 L=set_list(L,intvec(a,b,c),q);
1431         does exactly what you would expect when typing
1432                         L[a][b][c]=q;
1433         (but the last command will only produce an error message)
1434{
1435 list L=#[1];
1436 intvec v=#[2];
1437 def ersetze=#[3];
1438 //---------------- Bilde den Verzweigungsbaum nach ---------------------------
1439 def hilf(1)=L[v[1]];
1440 for (int tiefe=2; tiefe<size(v); tiefe++) {
1441   def hilf(tiefe)=hilf(tiefe-1)[v[tiefe]];
1442 }
1443 //---------------- Fuege Aenderung in die Liste ein --------------------------
1444 hilf(size(v)-1)[v[size(v)]]=ersetze;
1445 for (tiefe=size(v)-1; tiefe>1; tiefe--) {
1446   hilf(tiefe-1)[v[tiefe]]=hilf(tiefe);
1447 }
1448 L[v[1]]=hilf(1);
1449 return(L);
1450}
1451///////////////////////////////////////////////////////////////////////////////
1452proc get_last_divisor(int M, int N)
1453USAGE:   get_last_divisor(M,N); int M,N
1454RETURN:  int Q: M=q1*N+r1, N=q2*r1+r2, ..., ri=Q*r(i+1) (Euclidean alg.)
1455EXAMPLE: example get_last_divisor; shows an example
1456{
1457 int R=M%N; int Q=M / N;
1458 while (R!=0) {M=N; N=R; R=M%N; Q=M / N;}
1459 return(Q)
1460}
1461example
1462{ "EXAMPLE"; echo = 2;
1463  ring r=0,(x,y),dp;
1464  get_last_divisor(12,10);
1465}
1466///////////////////////////////////////////////////////////////////////////////
1467proc redleit (poly f,intvec S, intvec E)
1468USAGE:   redleit(f,S,E); f poly,
1469         S,E intvec(x,y): two different points on a line in the newtonpolygon
1470         of f (e.g. the starting and the ending point)
1471RETURN:  poly g: all monomials of f which lay on that line
1472NOTE:    It is not checked whether S and E really belong to the newtonpolygon!
1473EXAMPLE: example redleit;  shows an example
1474{
1475 if (E[1]<S[1]) { intvec H=E; E=S; S=H; } // S,E verkehrt herum eingegeben
1476 return(jet(f,E[1]*S[2]-E[2]*S[1],intvec(S[2]-E[2],E[1]-S[1])));
1477}
1478example
1479{ "EXAMPLE"; echo = 2;
1480  ring exring=0,(x,y),dp;
1481  redleit(y6+xy4-2x3y2+x4y+x6,intvec(3,2),intvec(4,1));
1482}
1483///////////////////////////////////////////////////////////////////////////////
1484
1485
1486proc extdevelop (list l, int Exaktheit)
1487USAGE:   extdevelop(l,n);  list l (matrix m, intvec v, int s, poly g), int n
1488         takes the output l of develop(f) ( or extdevelop(L,n),
1489         or one entry of the output of reddevelop(f))  and
1490RETURN:  an extension of the Hamburger-Noether development of f in the form
1491         of develop, i.e. a list L (matrix m,intvec v,...)
1492         The new HN-matrix will have at least n columns
1493         (if the HNE isn't finite).
1494         Thus if f is irreducible, extdevelop(develop(f),n);
1495         (in most cases) will produce the same result as develop(f,n).
1496         Type  help develop;  for more details
1497EXAMPLE: example extdevelop;  shows an example
1498{
1499 //------------ Initialisierungen und Abfangen unzulaessiger Aufrufe ----------
1500 matrix m=l[1];
1501 intvec v=l[2];
1502 int switch=l[3];
1503 if (nvars(basering) < 2) {
1504   " Sorry. I need two variables in the ring.";
1505   return(list(matrix(maxideal(1)[1]),intvec(0),-1,poly(0)));}
1506 if (switch==-1) {
1507   "An error has occurred in develop, so there is no HNE and no extension.";
1508   return(l);
1509 }
1510 poly f=l[4];
1511 if (f==0) {
1512   " No extension is possible";
1513   return(l);
1514 }
1515 int Q=v[size(v)];
1516 if (Q>0) {
1517   " The HNE was already exact";
1518   return(l);
1519 }
1520 else {
1521   if (Q==-1) { Q=ncols(m); }
1522   else { Q=-Q-1; }
1523 }
1524 int zeile=nrows(m);
1525 int spalten,i,lastside;
1526 ideal lastrow=m[zeile,1..Q];
1527 int ringwechsel=(varstr(basering)!="x,y") or (ordstr(basering)!="ls(2),C");
1528
1529 //------------------------- Ringwechsel, falls noetig ------------------------
1530 if (ringwechsel) {
1531  def altring = basering;
1532  int p = char(basering); // Ringcharakteristik
1533  if (charstr(basering)!=string(p)) {
1534     string tststr=charstr(basering);
1535     tststr=tststr[1..find(tststr,",")-1];     //-> "p^k" bzw. "p"
1536     if (tststr==string(p)) {
1537       if (size(parstr(basering))>1) {         // ring (p,a,..),...
1538        execute "ring extdguenstig=("+charstr(basering)+"),(x,y),ls;";
1539       }
1540       else {                                  // ring (p,a),...
1541        string mipl=string(minpoly);
1542        ring extdguenstig=(p,`parstr(basering)`),(x,y),ls;
1543        if (mipl!="0") { execute "minpoly="+mipl+";"; }
1544       }
1545     }
1546     else {
1547       execute "ring extdguenstig=("+charstr(basering)+"),(x,y),ls;";     
1548     }
1549  }
1550  else {                               // charstr(basering)== p : no parameter
1551     ring extdguenstig=p,(x,y),ls;
1552  }
1553  export extdguenstig;
1554  map hole=altring,x,y;
1555  poly f=hole(f);
1556  ideal a=hole(lastrow);
1557  //----- map hat sich als sehr zeitaufwendig bei f gross herausgestellt ------
1558  //-------- (fetch,imap nur 5% schneller), daher nach Moeglichkeit -----------
1559  //-----------------Beibehaltung des alten Ringes: ---------------------------
1560 }
1561 else { ideal a=lastrow; }
1562 list Newton;
1563 number delta;
1564 //--------------------- Fortsetzung der HNE ----------------------------------
1565 while (Q<Exaktheit) {
1566  Newton=newtonpoly(f);
1567  lastside=size(Newton)-1;
1568  if (Newton[lastside][2]!=1) {
1569    " *** The transformed polynomial was not valid!!";}
1570  Q=Newton[lastside+1][1]-Newton[lastside][1];      // Laenge der letzten Seite
1571
1572 //--- quasihomogenes Leitpolynom ist c*x^a*y+d*x^(a+Q) => delta=-d/c: --------
1573  delta=-koeff(f,Newton[lastside+1][1],0)/koeff(f,Newton[lastside][1],1);
1574  a[Q]=delta;
1575  "a("+string(zeile-1)+","+string(Q)+") =",delta;
1576  if (Q<Exaktheit) {
1577   f=T1_Transform(f,delta,Q);
1578   if (defined(Protokoll)) { "transformed polynomial:",f; }
1579   if (subst(f,y,0)==0) {
1580     "The HNE is finite!";
1581     a[Q+1]=x; Exaktheit=Q;
1582     f=0;                          // Speicherersparnis: f nicht mehr gebraucht
1583   }
1584  }
1585 }
1586 //------- Wechsel in alten Ring, Zusammensetzung alte HNE + Erweiterung ------
1587 if (ringwechsel) {
1588  setring altring;
1589  map zurueck=extdguenstig,var(1),var(2);
1590  f=zurueck(f);
1591  lastrow=zurueck(a);
1592 }
1593 else { lastrow=a; }
1594 if (ncols(lastrow)>ncols(m)) { spalten=ncols(lastrow); }
1595 else { spalten=ncols(m); }
1596 matrix mneu[zeile][spalten];
1597 for (i=1; i<nrows(m); i++) {
1598  mneu[i,1..ncols(m)]=m[i,1..ncols(m)];
1599 }
1600 mneu[zeile,1..ncols(lastrow)]=lastrow;
1601 if (lastrow[ncols(lastrow)]!=var(1)) {
1602  if (ncols(lastrow)==spalten) { v[zeile]=-1; }  // keine undefinierten Stellen
1603  else {
1604   v[zeile]=-Q-1;
1605   for (i=ncols(lastrow)+1; i<=spalten; i++) {
1606    mneu[zeile,i]=var(2);           // fuelle nicht def. Stellen der Matrix auf
1607 }}}
1608 else { v[zeile]=Q; }               // HNE war exakt
1609 if (ringwechsel) { kill extdguenstig; }
1610
1611 return(list(mneu,v,switch,f));
1612}
1613example
1614{
1615  if (nameof(basering)=="HNEring") {
1616   def rettering=HNEring;
1617   kill HNEring;
1618  }
1619  "EXAMPLE:"; echo = 2;
1620  ring exring=0,(x,y),dp;
1621  list hne=reddevelop(x14-3y2x11-y3x10-y2x9+3y4x8+y5x7+3y4x6+x5*(-y6+y5)-3y6x3-y7x2+y8);
1622  print(hne[1][1]); // finite HNE
1623  print(extdevelop(hne[1],5)[1]); pause;
1624  print(hne[2][1]); // HNE that can be extended
1625  list ehne=extdevelop(hne[2],5);
1626  print(ehne[1]); // new HN-matrix has 5 columns
1627  param(hne[2]);
1628  param(ehne);
1629  param(extdevelop(ehne,7)); pause;
1630  //////////////////////////
1631  print(develop(x-y2-2y3-3y4)[1]);
1632  print(extdevelop(develop(x-y2-2y3-3y4),4)[1]);
1633  print(extdevelop(develop(x-y2-2y3-3y4),10)[1]);
1634  kill HNEring,exring;
1635  echo = 0;
1636  if (defined(rettering)) { // wenn aktueller Ring vor Aufruf von example
1637   setring rettering;       // HNEring war, muss dieser erst wieder restauriert
1638   def HNEring=rettering;   // werden
1639   export HNEring;
1640  }
1641}
1642///////////////////////////////////////////////////////////////////////////////
1643
1644proc stripHNE (list l)
1645USAGE:   stripHNE(l);    takes the output both of develop(f) and reddevelop(f)
1646           ( list l (matrix m, intvec v, int s[,poly g])
1647             or list of lists in the form l            )
1648RETURN:  a list in the same format as l, but all polynomials g are set to zero
1649NOTE:    The purpose of this procedure is to remove huge amounts of data
1650         no longer needed. It is useful, if one or more of the polynomials
1651         in l consumes much memory. It is still possible to compute invariants,
1652         parametrizations etc. with the stripped HNE(s), but it is not possible
1653         to use extdevelop with them.
1654EXAMPLE: example stripHNE;  shows an example
1655{
1656 list h;
1657 if (typeof(l[1])=="matrix") { l[4]=poly(0); }
1658 else {
1659  for (int i=1; i<=size(l); i++) {
1660    h=l[i];
1661    h[4]=poly(0);
1662    l[i]=h;
1663  }
1664 }
1665 return(l);
1666}
1667example
1668{ "EXAMPLE:"; echo = 2;
1669  ring r=0,(x,y),dp;
1670  list hne=develop(x2+y3+y4);
1671  hne;
1672  stripHNE(hne);
1673}
1674///////////////////////////////////////////////////////////////////////////////
1675
1676proc extractHNEs(list HNEs, int transvers)
1677USAGE:  extractHNEs(HNEs,transvers);  list HNEs (output from HN),
1678        int transvers: 1 if x,y were exchanged, 0 else
1679RETURN: list of Hamburger-Noether-Extensions in the form of reddevelop
1680NOTE:   This procedure is only for internal purpose; examples don't make sense
1681{
1682 int i,maxspalte,hspalte,hnezaehler;
1683 list HNEaktu,Ergebnis;
1684 for (hnezaehler=1; hnezaehler<=size(HNEs); hnezaehler++) {
1685  maxspalte=0;
1686  HNEaktu=HNEs[hnezaehler];
1687  if (defined(Protokoll)) {"To process:";HNEaktu;}
1688  if (size(HNEs[hnezaehler])!=size(HNEs[hnezaehler][1])+2) {
1689     "The ideals and the hqs in HNEs[",hnezaehler,"] don't match!!";
1690     HNEs[hnezaehler];
1691  }
1692 //------------ ermittle  maximale Anzahl benoetigter Spalten: ----------------
1693  for (i=2; i<size(HNEaktu); i++) {
1694    hspalte=ncols(HNEaktu[i]);
1695    maxspalte=maxspalte*(hspalte < maxspalte)+hspalte*(hspalte >= maxspalte);
1696  }
1697 //------------- schreibe Ausgabe fuer hnezaehler-ten Zweig: ------------------
1698  matrix ma[size(HNEaktu)-2][maxspalte];
1699  for (i=1; i<=(size(HNEaktu)-2); i++) {
1700    if (ncols(HNEaktu[i+1]) > 1) {
1701      ma[i,1..ncols(HNEaktu[i+1])]=HNEaktu[i+1]; }
1702    else { ma[i,1]=HNEaktu[i+1][1];}
1703  }
1704  Ergebnis[hnezaehler]=list(ma,HNEaktu[1],transvers,HNEaktu[size(HNEaktu)]);
1705  kill ma;
1706 }
1707 return(Ergebnis);
1708}
1709///////////////////////////////////////////////////////////////////////////////
1710
1711proc factorfirst(poly f, int M, int N)
1712USAGE : factorfirst(f,M,N); f poly, M,N int
1713RETURN: number d: f=c*(y^(N/e) - d*x^(M/e))^e with e=gcd(M,N), number c fitting
1714        0 if d does not exist
1715EXAMPLE: example factorfirst;  shows an example
1716{
1717 number c = koeff(f,0,N);
1718 number delta;
1719 int eps,l;
1720 int p=char(basering);
1721 string ringchar=charstr(basering);
1722
1723 if (c == 0) {"Something has gone wrong! I didn't get N correctly!"; exit;}
1724 int e = gcd(M,N);
1725
1726 if (p==0) { delta = koeff(f,M/ e,N - N/ e) / (-1*e*c); }
1727 else {
1728   if (e%p != 0) { delta = koeff(f,M/ e,N - N/ e) / (-1*e*c); }
1729   else {
1730     eps = e;
1731     for (l = 0; eps%p == 0; l=l+1) { eps=eps/ p;}
1732     if (defined(Protokoll)) {e," -> ",eps,"*",p,"^",l;}
1733     delta = koeff(f,(M/ e)*p^l,(N/ e)*p^l*(eps-1)) / (-1*eps*c);
1734
1735     if ((charstr(basering) != string(p)) and (delta != 0)) {
1736 //------ coefficient field is not Z/pZ => (p^l)th root is not identity -------
1737       delta=0;
1738       if (defined(Protokoll)) {
1739         "trivial factorization not implemented for",
1740         "parameters---I've to use 'factorize'";
1741       }
1742     }
1743   }
1744 }
1745 if (defined(Protokoll)) {"quasihomogeneous leading form:",f," = ",c,
1746        "* (y^"+string(N/ e),"-",delta,"* x^"+string(M/ e)+")^",e," ?";}
1747 if (f != c*(y^(N/ e) - delta*x^(M/ e))^e) {return(0);}
1748 else {return(delta);}
1749}
1750example
1751{ "EXAMPLE:"; echo = 2;
1752  ring exring=7,(x,y),dp;
1753  factorfirst(2*(y3-3x4)^5,20,15);
1754  factorfirst(x14+y7,14,7);
1755  factorfirst(x14+x8y3+y7,14,7);
1756}
1757///////////////////////////////////////////////////////////////////////////////
1758
1759
1760proc reddevelop (poly f)
1761USAGE:   reddevelop(f); f poly
1762RETURN:  Hamburger-Noether development of f :
1763         A list of lists in the form of develop(f); each entry contains the
1764         data for one of the branches of f.
1765         For more details type 'help develop;'
1766NOTE:    as the Hamburger-Noether development of a reducible curve normally
1767         exists only in a ring extension, reddevelop automatically changes
1768         the basering to  ring HNEring=...,(x,y),ls; !
1769EXAMPLE: example reddevelop;  shows an example
1770{
1771 def altring = basering;
1772 int p = char(basering);                 // Ringcharakteristik
1773
1774 //-------------------- Tests auf Zulaessigkeit von basering ------------------
1775 if (charstr(basering)=="real") {
1776   " Singular cannot factorize over 'real' as ground field";
1777   return(list());
1778 }
1779 if (size(maxideal(1))<2) {
1780   " A univariate polynomial ring makes no sense !";
1781   return(list());
1782 }
1783 if (size(maxideal(1))>2) {
1784   " Warning: all but the first two variables are ignored!";
1785 }
1786 if (find(charstr(basering),string(char(basering)))!=1) {
1787   " ring of type (p^k,a) not implemented";
1788 //----------------------------------------------------------------------------
1789 // weder primitives Element noch factorize noch map "char p^k" -> "char -p"
1790 // [(p^k,a)->(p,a) ground field] noch fetch
1791 //----------------------------------------------------------------------------
1792   return(list());
1793 }
1794 //----------------- Definition eines neuen Ringes: HNEring -------------------
1795 string namex=varstr(1); string namey=varstr(2);
1796 if (string(char(altring))==charstr(altring)) {       // kein Parameter
1797   ring HNEring = char(altring),(x,y),ls;
1798   map m=altring,x,y;
1799   poly f=m(f);
1800   kill m;
1801 }
1802 else {
1803   string mipl=string(minpoly);
1804   if (mipl=="0") {
1805     " ** WARNING: No algebraic extension of this ground field is possible!";
1806     " ** We try to develop this polynomial, but if the need for an extension";
1807     " ** occurs during the calculation, we cannot proceed with the";
1808     " ** corresponding branches ...";
1809     execute "ring HNEring=("+charstr(basering)+"),(x,y),ls;";
1810 //--- ring ...=(char(.),`parstr()`),... geht nicht, wenn mehr als 1 Param. ---
1811   }
1812   else {
1813    string pa=parstr(altring);
1814    ring HNhelpring=p,`pa`,dp;
1815    execute "poly mipo="+mipl+";";   // Minimalpolynom in Polynom umgewandelt
1816    ring HNEring=(p,a),(x,y),ls;
1817    map getminpol=HNhelpring,a;
1818    mipl=string(getminpol(mipo));    // String umgewandelt mit 'a' als Param.
1819    execute "minpoly="+mipl+";";     // "minpoly=poly is not supported"
1820    kill HNhelpring, getminpol;
1821   }
1822   if (nvars(altring)==2) { poly f=fetch(altring,f); }
1823   else {
1824     map m=altring,x,y;
1825     poly f=m(f);
1826     kill m;
1827   }
1828 }
1829 export HNEring;
1830
1831 if (defined(Protokoll))
1832 {"received polynomial: ",f,", with x =",namex,", y =",namey;}
1833
1834 //----------------------- Variablendefinitionen ------------------------------
1835 int Abbruch,i,NullHNEx,NullHNEy;
1836 string str;
1837 list Newton,Ergebnis,hilflist;
1838
1839 //====================== Tests auf Zulaessigkeit des Polynoms ================
1840
1841 //-------------------------- Test, ob Einheit oder Null ----------------------
1842 if (subst(subst(f,x,0),y,0)!=0) {
1843   "The given polynomial is a unit in the power series ring!";
1844   keepring HNEring;
1845   return(list());                   // there are no HNEs
1846 }
1847 if (f==0) {
1848   "The given polynomial is zero!";
1849   keepring HNEring;
1850   return(list());                   // there are no HNEs
1851 }
1852
1853 //-----------------------  Test auf Quadratfreiheit --------------------------
1854
1855 if ((p==0) and (size(charstr(basering))==1)) {
1856
1857 //-------- Fall basering==0,... : Wechsel in Ring mit char >0 ----------------
1858 // weil squarefree eine Standardbasis berechnen muss (verwendet Syzygien)
1859 // -- wenn f in diesem Ring quadratfrei ist, dann erst recht im Ring HNEring
1860 //----------------------------------------------------------------------------
1861  int testerg=(polytest(f)==0);
1862  ring zweitring = 32003,(x,y),dp;
1863
1864  map polyhinueber=HNEring,x,y;         // fetch geht nicht
1865  poly f=polyhinueber(f);
1866  poly test_sqr=squarefree(f);
1867  if (test_sqr != f) {
1868   "Most probably the given polynomial is not squarefree. But the test was";
1869   "made in characteristic 32003 and not 0 to improve speed. You can";
1870   "(r) redo the test in char 0 (but this may take some time)";
1871   "(c) continue the development, if you're sure that the polynomial IS",
1872   "squarefree";
1873   if (testerg==1) {
1874     "(s) continue the development with a squarefree factor (*)";}
1875   "(q) or just quit the algorithm (default action)";
1876   "";"Please enter the letter of your choice:";
1877   str=read("")[1];                     // : liest 1 Zeichen von der Tastatur
1878   setring HNEring;
1879   map polyhinueber=zweitring,x,y;
1880   if (str=="r") {
1881     poly test_sqr=squarefree(f);
1882     if (test_sqr != f) {
1883      "The given polynomial is in fact not squarefree.";
1884      "I'll continue with the radical.";
1885      f=test_sqr;
1886     }
1887     else {"everything is ok -- the polynomial is squarefree in",
1888           "characteristic 0";}
1889   }
1890   else {
1891     if ((str=="s") and (testerg==1)) {
1892       "(*)attention: it could be that the factor is only one in char 32003!";
1893       f=polyhinueber(test_sqr);
1894     }
1895     else {
1896       if (str<>"c") {
1897         setring altring;kill HNEring;kill zweitring;
1898         return(list());}
1899       else { "if the algorithm doesn't terminate, you were wrong...";}
1900   }}
1901   kill zweitring;
1902   if (defined(Protokoll)) {"I continue with the polynomial",f; }
1903  }
1904  else {
1905    setring HNEring;
1906    kill zweitring;
1907  }
1908 }
1909 //------------------ Fall Char > 0 oder Ring hat Parameter -------------------
1910 else {
1911  poly test_sqr=squarefree(f);
1912  if (test_sqr != f) {
1913   if (test_sqr == 1) {
1914    "The given polynomial is of the form g^"+string(p)+",";
1915    "therefore not squarefree.  You can:";
1916    " (q) quit the algorithm (recommended) or";
1917    " (f) continue with the full radical (using a factorization of the";
1918    "     pure power part; this could take much time)";
1919    "";"Please enter the letter of your choice:";
1920    str=read("")[1];
1921    if (str<>"f") { str="q"; }
1922   }
1923   else {
1924    "The given polynomial is not squarefree.";
1925    if (p != 0)
1926     {
1927      " You can:";
1928      " (c) continue with a squarefree divisor (but factors of the form g^"
1929      +string(p);
1930      "     are lost; this is recommended, takes no more time)";
1931      " (f) continue with the full radical (using a factorization of the";
1932      "     pure power part; this could take much time)";
1933      " (q) quit the algorithm";
1934      "";"Please enter the letter of your choice:";
1935      str=read("")[1];
1936      if ((str<>"f") && (str<>"q")) { str="c"; }
1937     }
1938    else { "I'll continue with the radical."; str="c"; }
1939   }                                // endelse (test_sqr!=1)
1940   if (str=="q") {
1941    setring altring;kill HNEring;
1942    return(list());
1943   }
1944   if (str=="c") { f=test_sqr; }
1945   if (str=="f") { f=allsquarefree(f,test_sqr); }
1946  }
1947  if (defined(Protokoll)) {"I continue with the polynomial",f; }
1948
1949 }
1950 //====================== Ende Test auf Quadratfreiheit =======================
1951 if (subst(subst(f,x,0),y,0)!=0) {
1952   "Sorry. The remaining polynomial is a unit in the power series ring...";
1953   keepring HNEring;
1954   return(list());
1955 }
1956 //---------------------- Test, ob f teilbar durch x oder y -------------------
1957 if (subst(f,y,0)==0) {
1958   f=f/y; NullHNEy=1; }             // y=0 is a solution
1959 if (subst(f,x,0)==0) {
1960   f=f/x; NullHNEx=1; }             // x=0 is a solution
1961
1962 Newton=newtonpoly(f);
1963 i=1; Abbruch=0;
1964 //----------------------------------------------------------------------------
1965 // finde Eckpkt. des Newtonpolys, der den Teil abgrenzt, fuer den x transvers:
1966 // Annahme: Newton ist sortiert, s.d. Newton[1]=Punkt auf der y-Achse,
1967 // Newton[letzt]=Punkt auf der x-Achse
1968 //----------------------------------------------------------------------------
1969 while ((i<size(Newton)) and (Abbruch==0)) {
1970  if ((Newton[i+1][1]-Newton[i][1])>=(Newton[i][2]-Newton[i+1][2]))
1971   {Abbruch=1;}
1972  else {i=i+1;}
1973 }
1974 int grenze1=Newton[i][2];
1975 int grenze2=Newton[i][1];
1976 //----------------------------------------------------------------------------
1977 // Stelle Ring bereit zur Uebertragung der Daten im Fall einer Koerperer-
1978 // weiterung. Definiere Objekte, die spaeter uebertragen werden.
1979 // Binde die Listen (azeilen,...) an den Ring (um sie nicht zu ueberschreiben
1980 // bei Def. in einem anderen Ring).
1981 // Exportiere Objekte, damit sie auch in der proc HN noch da sind
1982 //----------------------------------------------------------------------------
1983 ring HNE_noparam = char(altring),(a,x,y),ls;
1984 export HNE_noparam;
1985 poly f;
1986 list azeilen=ideal(0);
1987 list HNEs=ideal(0);
1988 list aneu=ideal(0);
1989 ideal deltais;
1990 poly delta;                   // nicht number, weil delta von a abhaengen kann
1991 export f,azeilen,HNEs,aneu,deltais,delta;
1992 //----- hier steht die Anzahl bisher benoetigter Ringerweiterungen drin: -----
1993 int EXTHNEnumber=0; export EXTHNEnumber;
1994 setring HNEring;
1995
1996 // -------- Berechne HNE von allen Zweigen, fuer die x transvers ist: --------
1997 if (defined(Protokoll))
1998   {"1st step: Treat newton polygon until height",grenze1;}
1999 if (grenze1>0) {
2000  hilflist=HN(f,grenze1,1);
2001  if (typeof(hilflist[1][1])=="ideal") { hilflist[1]=list(); }
2002 //- fuer den Fall, dass keine Zweige in transz. Erw. berechnet werden konnten-
2003  Ergebnis=extractHNEs(hilflist[1],0);
2004  if (hilflist[2]!=-1) {
2005    if (defined(Protokoll)) {" ring change in HN(",1,") detected";}
2006    poly transfproc=hilflist[2];
2007    map hole=HNE_noparam,transfproc,x,y;
2008    setring HNE_noparam;
2009    f=imap(HNEring,f);
2010    setring EXTHNEring(EXTHNEnumber);
2011    poly f=hole(f);
2012  }
2013 }
2014 if (NullHNEy==1) {
2015  Ergebnis=Ergebnis+list(list(matrix(ideal(0,x)),intvec(1),int(0),poly(0)));
2016 }
2017 // --------------- Berechne HNE von allen verbliebenen Zweigen: --------------
2018 if (defined(Protokoll))
2019    {"2nd step: Treat newton polygon until height",grenze2;}
2020 if (grenze2>0) {
2021  map xytausch=basering,y,x;
2022  kill hilflist;
2023  def letztring=basering;
2024  if (EXTHNEnumber==0) { setring HNEring; }
2025  else                 { setring EXTHNEring(EXTHNEnumber); }
2026  list hilflist=HN(xytausch(f),grenze2,1);
2027  if (typeof(hilflist[1][1])=="ideal") { hilflist[1]=list(); }
2028  if (not(defined(Ergebnis))) {
2029 //-- HN wurde schon mal ausgefuehrt; Ringwechsel beim zweiten Aufruf von HN --
2030    if (defined(Protokoll)) {" ring change in HN(",1,") detected";}
2031    poly transfproc=hilflist[2];
2032    map hole=HNE_noparam,transfproc,x,y;
2033    setring HNE_noparam;
2034    list Ergebnis=imap(letztring,Ergebnis);
2035    setring EXTHNEring(EXTHNEnumber);
2036    list Ergebnis=hole(Ergebnis);
2037  }
2038  Ergebnis=Ergebnis+extractHNEs(hilflist[1],1);
2039 }
2040 if (NullHNEx==1) {
2041  Ergebnis=Ergebnis+list(list(matrix(ideal(0,x)),intvec(1),int(1),poly(0)));
2042 }
2043 //------------------- Loesche globale, nicht mehr benoetigte Objekte: --------
2044 if (EXTHNEnumber>0) {
2045  kill HNEring;
2046  def HNEring=EXTHNEring(EXTHNEnumber);
2047  setring HNEring;
2048  export HNEring;
2049  kill EXTHNEring(1..EXTHNEnumber);
2050 }
2051 kill HNE_noparam;
2052 kill EXTHNEnumber;
2053 keepring basering;
2054 "  ~~~ result:",size(Ergebnis)," branch(es) successfully computed ~~~";
2055 return(Ergebnis);
2056}
2057example
2058{
2059  if (nameof(basering)=="HNEring") {
2060   def rettering=HNEring;
2061   kill HNEring;
2062  }
2063  "EXAMPLE:"; echo = 2;
2064  ring r=0,(x,y),dp;
2065  list hne=reddevelop(x4-y6);
2066  size(hne);           // i.e. x4-y6 has two branches
2067  print(hne[1][1]);    // HN-matrix of 1st branch
2068  param(hne[1]);
2069  param(hne[2]);
2070  displayInvariants(hne);
2071  kill HNEring,r;
2072  pause;
2073  // a more interesting example:
2074  ring r = 32003,(x,y),dp;
2075  poly f = x25+x24-4x23-1x22y+4x22+8x21y-2x21-12x20y-4x19y2+4x20+10x19y+12x18y2
2076          -24x18y-20x17y2-4x16y3+x18+60x16y2+20x15y3-9x16y-80x14y3-10x13y4
2077          +36x14y2+60x12y4+2x11y5-84x12y3-24x10y5+126x10y4+4x8y6-126x8y5+84x6y6
2078          -36x4y7+9x2y8-1y9;
2079  list hne=reddevelop(f);
2080  size(hne);
2081  print(hne[1][1]);
2082  print(hne[4][1]);
2083  // a ring change was necessary, a is a parameter
2084  HNEring;
2085  kill HNEring,r;
2086  echo = 0;
2087  if (defined(rettering)) { // wenn aktueller Ring vor Aufruf von example
2088   setring rettering;       // HNEring war, muss dieser erst wieder restauriert
2089   def HNEring=rettering;   // werden
2090   export HNEring;
2091  }
2092}
2093///////////////////////////////////////////////////////////////////////////////
2094
2095proc HN (poly f,int grenze, int Aufruf_Ebene)
2096NOTE: This procedure is only for internal use, it is called via reddevelop
2097{
2098 //---------- Variablendefinitionen fuer den unverzweigten Teil: --------------
2099 if (defined(Protokoll)) {"procedure HN",Aufruf_Ebene;}
2100 int Abbruch,ende,i,j,e,M,N,Q,R,zeiger,zeile,zeilevorher;
2101 intvec hqs;
2102 poly fvorher;
2103 list erg=ideal(0); list HNEs=ideal(0); // um die Listen an den Ring zu binden
2104
2105 //-------------------- Bedeutung von Abbruch: --------------------------------
2106 //------- 0:keine Verzweigung | 1:Verzweigung,nicht fertig | 2:fertig --------
2107 //
2108 // Struktur von HNEs : Liste von Listen L (fuer jeden Zweig) der Form
2109 // L[1]=intvec (hqs), L[2],L[3],... ideal (die Zeilen (0,1,...) der HNE)
2110 // L[letztes]=poly (transformiertes f)
2111 //----------------------------------------------------------------------------
2112 list Newton;
2113 number delta;
2114 int p = char(basering);                // Ringcharakteristik
2115 list azeilen=ideal(0);
2116 ideal hilfid; list hilflist=ideal(0); intvec hilfvec;
2117
2118 // ======================= der unverzweigte Teil: ============================
2119 while (Abbruch==0) {
2120  Newton=newtonpoly(f);
2121  zeiger=find_in_list(Newton,grenze);
2122  if (Newton[zeiger][2] != grenze)
2123    {"Didn't find an edge in the newton polygon!";}
2124  if (zeiger==size(Newton)-1) {
2125    if (defined(Protokoll)) {"only one relevant side in newton polygon";}
2126    M=Newton[zeiger+1][1]-Newton[zeiger][1];
2127    N=Newton[zeiger][2]-Newton[zeiger+1][2];
2128    R = M%N;
2129    Q = M / N;
2130
2131 //-------- 1. Versuch: ist der quasihomogene Leitterm reine Potenz ? ---------
2132 //              (dann geht alles wie im irreduziblen Fall)
2133 //----------------------------------------------------------------------------
2134    e = gcd(M,N);
2135    delta=factorfirst(redleit(f,Newton[zeiger],Newton[zeiger+1])
2136                      /x^Newton[zeiger][1],M,N);
2137    if (delta==0) {
2138      if (defined(Protokoll)) {" The given polynomial is reducible !";}
2139      Abbruch=1;
2140    }
2141    if (Abbruch==0) {
2142 //-------------- f,zeile retten fuer den Spezialfall (###): ------------------
2143      fvorher=f;zeilevorher=zeile;
2144      if (R==0) {
2145 //------------- transformiere f mit T1, wenn kein Abbruch nachher: -----------
2146        if (N>1) { f = T1_Transform(f,delta,M/ e); }
2147        else     { ende=1; }
2148        if (defined(Protokoll)) {"a("+string(zeile)+","+string(Q)+") =",delta;}
2149        azeilen=set_list(azeilen,intvec(zeile+1,Q),delta);
2150      }
2151      else {
2152 //------------- R > 0 : transformiere f mit T2 -------------------------------
2153        erg=T2_Transform(f,delta,M,N);
2154        f=erg[1];delta=erg[2];
2155 //------- vollziehe Euklid.Alg. nach, um die HN-Matrix zu berechnen: ---------
2156        while (R!=0) {
2157         if (defined(Protokoll)) { "h("+string(zeile)+") =",Q; }
2158         hqs[zeile+1]=Q;  //denn zeile beginnt mit dem Wert 0
2159 //------------------ markiere das Zeilenende der HNE: ------------------------
2160         azeilen=set_list(azeilen,intvec(zeile+1,Q+1),x);
2161         zeile=zeile+1;
2162 //----------- Bereitstellung von Speicherplatz fuer eine neue Zeile: ---------
2163         azeilen[zeile+1]=ideal(0);
2164         M=N; N=R; R=M%N; Q=M / N;
2165        }
2166        if (defined(Protokoll)) {"a("+string(zeile)+","+string(Q)+") =",delta;}
2167        azeilen=set_list(azeilen,intvec(zeile+1,Q),delta);
2168      }
2169      if (defined(Protokoll)) {"transformed polynomial: ",f;}
2170      grenze=e;
2171 //----------------------- teste Abbruchbedingungen: --------------------------
2172      if (subst(f,y,0)==0) {              // <==> y|f
2173        "finite HNE of one branch found";
2174        azeilen=set_list(azeilen,intvec(zeile+1,Q+1),x);
2175 //- Q wird nur in hqs eingetragen, wenn der Spezialfall nicht eintritt (s.u.)-
2176        Abbruch=2;
2177        if (grenze>1) {
2178         if (jet(f,1,intvec(0,1))==0) {
2179 //------ jet(...)=alle Monome von f, die nicht durch y2 teilbar sind ---------
2180 "THE TEST FOR SQUAREFREENESS WAS BAD!! The polynomial was NOT squarefree!!!";}
2181         else {
2182 //-------------------------- Spezialfall (###): ------------------------------
2183 // Wir haben das Problem, dass die HNE eines Zweiges hier abbricht, aber ein
2184 // anderer Zweig bis hierher genau die gleiche HNE hat, die noch weiter geht
2185 // Loesung: mache Transform. rueckgaengig und behandle f im Verzweigungsteil
2186 //----------------------------------------------------------------------------
2187          Abbruch=1;
2188          f=fvorher;zeile=zeilevorher;grenze=Newton[zeiger][2];
2189        }}
2190        else {f=0;}     // f nicht mehr gebraucht - spare Speicher
2191        if (Abbruch==2) { hqs[zeile+1]=Q; }
2192      }                 // Spezialfall nicht eingetreten
2193      else {
2194        if (ende==1) {
2195          "HNE of one branch found"; Abbruch=2; hqs[zeile+1]=-Q-1;}
2196      }
2197    }                   // end(if Abbruch==0)
2198  }                     // end(if zeiger...)
2199  else { Abbruch=1;}
2200 }                      // end(while Abbruch==0)
2201
2202 // ===================== der Teil bei Verzweigung: ===========================
2203
2204 if (Abbruch==1) {
2205 //---------- Variablendefinitionen fuer den verzweigten Teil: ----------------
2206  poly leitf,teiler,transformiert;
2207  list faktoren=ideal(0); list aneu=ideal(0);
2208  ideal deltais;
2209  intvec eis;
2210  int zaehler,hnezaehler,zl,zl1,M1,N1,R1,Q1,needext;
2211  int numberofRingchanges,lastRingnumber,ringischanged,flag;
2212  string letztringname;
2213
2214  zeiger=find_in_list(Newton,grenze);
2215  if (defined(Protokoll)) {
2216    "Branching part reached---newton polygon :",Newton;
2217    "relevant part until height",grenze,", from",Newton[zeiger],"on";
2218  }
2219  azeilen=list(hqs)+azeilen; // hat jetzt Struktur von HNEs: hqs in der 1.Zeile
2220
2221 //======= Schleife fuer jede zu betrachtende Seite des Newtonpolygons: =======
2222  for(i=zeiger; i<size(Newton); i++) {
2223   if (defined(Protokoll)) { "we consider side",Newton[i],Newton[i+1]; }
2224   M=Newton[i+1][1]-Newton[i][1];
2225   N=Newton[i][2]-Newton[i+1][2];
2226   R = M%N;
2227   Q = M / N;
2228   e=gcd(M,N);
2229   needext=1;
2230   letztringname=nameof(basering);
2231   lastRingnumber=EXTHNEnumber;
2232
2233 //-- wechsle so lange in Ringerw., bis Leitform vollst. in Linearfakt. zerf.:-
2234   for (numberofRingchanges=1; needext==1; numberofRingchanges++) {
2235    leitf=redleit(f,Newton[i],Newton[i+1])/(x^Newton[i][1]*y^Newton[i+1][2]);
2236    delta=factorfirst(leitf,M,N);
2237    needext=0;
2238    if (delta==0) {
2239
2240 //---------- Sonderbehandlung: faktorisere einige Polynome ueber Q(a): -------
2241     if (charstr(basering)=="0,a") {
2242       faktoren,flag=extrafactor(leitf,M,N);  // damit funktion. Bsp. Baladi 5
2243       if (flag==0)
2244         { " ** I cannot proceed, will produce some error messages...";}
2245     }
2246     else
2247      {
2248 //------------------ faktorisiere das charakt. Polynom: ----------------------
2249      faktoren=factorize(charPoly(leitf,M,N));
2250     }
2251
2252     zaehler=1; eis=0;
2253     for (j=1; j<=size(faktoren[2]); j++) {
2254      teiler=faktoren[1][j];
2255      if (teiler/y != 0) {         // sonst war's eine Einheit --> wegwerfen!
2256        if (defined(Protokoll)) {"factor of leading form found:",teiler;}
2257        if (teiler/y2 == 0) {      // --> Faktor hat die Form cy+d
2258          deltais[zaehler]=-subst(teiler,y,0)/koeff(teiler,0,1); //=-d/c
2259          eis[zaehler]=faktoren[2][j];
2260          zaehler++;
2261        }
2262        else {
2263          " Change of basering necessary!!";
2264          if (defined(Protokoll)) { teiler,"is not properly factored!"; }
2265          if (needext==0) { poly zerlege=teiler; }
2266          needext=1;
2267        }
2268      }
2269     }                             // end(for j)
2270    }
2271    else { deltais=ideal(delta); eis=e;}
2272    if (defined(Protokoll)) {"roots of char. poly:";deltais;
2273                             "with multiplicities:",eis;}
2274    if (needext==1) {
2275 //--------------------- fuehre den Ringwechsel aus: --------------------------
2276      ringischanged=1;
2277      if ((size(parstr(basering))>0) && string(minpoly)=="0") {
2278        " ** We've had bad luck! The HNE cannot completely be calculated!";
2279                                   // HNE in transzendenter Erw. fehlgeschlagen
2280        kill zerlege;
2281        ringischanged=0; break;    // weiter mit gefundenen Faktoren
2282      }
2283      if (parstr(basering)=="") {
2284        EXTHNEnumber++;
2285        splitring(zerlege,"EXTHNEring("+string(EXTHNEnumber)+")");
2286        poly transf=0;
2287        poly transfproc=0;
2288      }
2289      else {
2290        if (defined(translist)) { kill translist; } // Vermeidung einer Warnung
2291        if (numberofRingchanges>1) {  // ein Ringwechsel hat nicht gereicht
2292         list translist=splitring(zerlege,"",list(transf,transfproc));
2293         poly transf=translist[1]; poly transfproc=translist[2];
2294        }
2295        else {
2296         if (defined(transfproc)) { // in dieser proc geschah schon Ringwechsel
2297          EXTHNEnumber++;
2298          list translist=splitring(zerlege,"EXTHNEring("
2299               +string(EXTHNEnumber)+")",list(a,transfproc));
2300          poly transf=translist[1];
2301          poly transfproc=translist[2];
2302         }
2303         else {
2304          EXTHNEnumber++;
2305          list translist=splitring(zerlege,"EXTHNEring("
2306               +string(EXTHNEnumber)+")",a);
2307          poly transf=translist[1];
2308          poly transfproc=transf;
2309        }}
2310      }
2311 //----------------------------------------------------------------------------
2312 // transf enthaelt jetzt den alten Parameter des Ringes, der aktiv war vor
2313 // Beginn der Schleife (evtl. also ueber mehrere Ringwechsel weitergereicht),
2314 // transfproc enthaelt den alten Parm. des R., der aktiv war zu Beginn der
2315 // Prozedur, und der an die aufrufende Prozedur zurueckgegeben werden muss
2316 // transf ist Null, falls der alte Ring keinen Parameter hatte,
2317 // das gleiche gilt fuer transfproc
2318 //----------------------------------------------------------------------------
2319
2320 //------ Neudef. von Variablen, Uebertragung bisher errechneter Daten: -------
2321      poly leitf,teiler,transformiert;
2322      list faktoren; list aneu=ideal(0);
2323      ideal deltais;
2324      number delta;
2325      setring HNE_noparam;
2326      if (defined(letztring)) { kill letztring; }
2327      if (lastRingnumber>0) { def letztring=EXTHNEring(lastRingnumber); }
2328      else                  { def letztring=HNEring; }
2329      f=imap(letztring,f);
2330      setring EXTHNEring(EXTHNEnumber);
2331      map hole=HNE_noparam,transf,x,y;
2332      poly f=hole(f);
2333    }
2334   }    // end (while needext==1) bzw. for (numberofRingchanges)
2335
2336   if (eis==0) { i++; continue; }
2337   if (ringischanged==1) {
2338    list erg,hilflist;              // dienen nur zum Sp. von Zwi.erg.
2339    ideal hilfid;
2340    erg=ideal(0); hilflist=erg;
2341
2342    hole=HNE_noparam,transf,x,y;
2343    setring HNE_noparam;
2344    azeilen=imap(letztring,azeilen);
2345    HNEs=imap(letztring,HNEs);
2346
2347    setring EXTHNEring(EXTHNEnumber);
2348    list azeilen=hole(azeilen);
2349    list HNEs=hole(HNEs);
2350    kill letztring;
2351    ringischanged=0;
2352   }
2353
2354 //============ Schleife fuer jeden gefundenen Faktor der Leitform: ===========
2355   for (j=1; j<=size(eis); j++) {
2356 //-- Mache Transf. T1 oder T2, trage Daten in HNEs ein, falls HNE abbricht: --
2357
2358 //------------------------ Fall R==0: ----------------------------------------
2359    if (R==0) {
2360      transformiert = T1_Transform(f,number(deltais[j]),M/ e);
2361      if (defined(Protokoll)) {
2362        "a("+string(zeile)+","+string(Q)+") =",deltais[j];
2363        "transformed polynomial: ",transformiert;
2364      }
2365      if (subst(transformiert,y,0)==0) {
2366       "finite HNE found";
2367       hnezaehler++;
2368 //------------ trage deltais[j],x ein in letzte Zeile, fertig: ---------------
2369       HNEs[hnezaehler]=azeilen+list(poly(0));
2370       hilfid=HNEs[hnezaehler][zeile+2]; hilfid[Q]=deltais[j]; hilfid[Q+1]=x;
2371       HNEs=set_list(HNEs,intvec(hnezaehler,zeile+2),hilfid);
2372       HNEs=set_list(HNEs,intvec(hnezaehler,1,zeile+1),Q);
2373                                  // aktualisiere Vektor mit den hqs
2374       if (eis[j]>1) {
2375        transformiert=transformiert/y;
2376        if (subst(transformiert,y,0)==0) {
2377 "THE TEST FOR SQUAREFREENESS WAS BAD!! The polynomial was NOT squarefree!!!";}
2378        else {
2379 //------ Spezialfall (###) eingetreten: Noch weitere Zweige vorhanden --------
2380          eis[j]=eis[j]-1;
2381        }
2382       }
2383      }
2384    }
2385    else {
2386 //------------------------ Fall R <> 0: --------------------------------------
2387      erg=T2_Transform(f,number(deltais[j]),M,N);
2388      transformiert=erg[1];delta=erg[2];
2389      if (defined(Protokoll)) {"transformed polynomial: ",transformiert;}
2390      if (subst(transformiert,y,0)==0) {
2391       "finite HNE found";
2392       hnezaehler++;
2393 //---------------- trage endliche HNE in HNEs ein: ---------------------------
2394       HNEs[hnezaehler]=azeilen;  // dupliziere den gemeins. Anfang der HNE's
2395       zl=2;
2396 //----------------------------------------------------------------------------
2397 // Werte von:  zeile: aktuelle Zeilennummer der HNE (gemeinsamer Teil)
2398 //             zl   : die HNE spaltet auf; zeile+zl ist der Index fuer die
2399 // Zeile des aktuellen Zweigs; (zeile+zl-2) ist die tatsaechl. Zeilennr.
2400 // (bei 0 angefangen) der HNE  ([1] <- intvec(hqs), [2] <- 0. Zeile usw.)
2401 //----------------------------------------------------------------------------
2402
2403 //---------- vollziehe Euklid.Alg. nach, um die HN-Matrix zu berechnen: ------
2404       M1=M;N1=N;R1=R;Q1=M1/ N1;
2405       while (R1!=0) {
2406        if (defined(Protokoll)) { "h("+string(zeile+zl-2)+") =",Q1; }
2407        HNEs=set_list(HNEs,intvec(hnezaehler,1,zeile+zl-1),Q1);
2408        HNEs=set_list(HNEs,intvec(hnezaehler,zeile+zl,Q1+1),x);
2409                                  // markiere das Zeilenende der HNE
2410        zl=zl+1;
2411 //-------- Bereitstellung von Speicherplatz fuer eine neue Zeile: ------------
2412        HNEs=set_list(HNEs,intvec(hnezaehler,zeile+zl),ideal(0));
2413               
2414        M1=N1; N1=R1; R1=M1%N1; Q1=M1 / N1;
2415       }
2416       if (defined(Protokoll)) {
2417         "a("+string(zeile+zl-2)+","+string(Q1)+") =",delta;
2418       }
2419       hilfid=ideal(0);           // = HNEs[hnezaehler][zeile+zl];
2420       hilfid[Q1]=delta;hilfid[Q1+1]=x;
2421       HNEs=set_list(HNEs,intvec(hnezaehler,zeile+zl),hilfid);
2422       HNEs=set_list(HNEs,intvec(hnezaehler,1,zeile+zl-1),Q1);
2423                                  // aktualisiere Vektor mit hqs
2424       HNEs=set_list(HNEs,intvec(hnezaehler,zeile+zl+1),poly(0));
2425 //-------------------- Ende der Eintragungen in HNEs -------------------------
2426
2427       if (eis[j]>1) {
2428        transformiert=transformiert/y;
2429        if (subst(transformiert,y,0)==0) {
2430 "THE TEST FOR SQUAREFREENESS WAS BAD!! The polynomial was NOT squarefree!!!";}
2431         else {
2432 //--------- Spezialfall (###) eingetreten: Noch weitere Zweige vorhanden -----
2433          eis[j]=eis[j]-1;
2434       }}
2435      }                           // endif (subst()==0)
2436    }                             // endelse (R<>0)
2437
2438 //========== Falls HNE nicht abbricht: Rekursiver Aufruf von HN: =============
2439 //------------------- Berechne HNE von transformiert -------------------------
2440    if (subst(transformiert,y,0)!=0) {
2441     lastRingnumber=EXTHNEnumber;
2442     list HNerg=HN(transformiert,eis[j],Aufruf_Ebene+1);
2443     if (HNerg[2]==-1) {          // kein Ringwechsel in HN aufgetreten
2444       aneu=HNerg[1];  }
2445     else {
2446       if (defined(Protokoll))
2447          {" ring change in HN(",Aufruf_Ebene+1,") detected";}
2448       list aneu=HNerg[1];
2449       poly transfproc=HNerg[2];
2450
2451 //- stelle lokale Var. im neuen Ring wieder her und rette ggf. ihren Inhalt: -
2452       list erg,hilflist,faktoren;
2453       ideal hilfid;
2454       erg=ideal(0); hilflist=erg; faktoren=erg;
2455       poly leitf,teiler,transformiert;
2456
2457       map hole=HNE_noparam,transfproc,x,y;
2458       setring HNE_noparam;
2459       if (lastRingnumber>0) { def letztring=EXTHNEring(lastRingnumber); }
2460       else                  { def letztring=HNEring; }
2461       HNEs=imap(letztring,HNEs);
2462       azeilen=imap(letztring,azeilen);
2463       deltais=imap(letztring,deltais);
2464       delta=imap(letztring,delta);
2465       f=imap(letztring,f);
2466
2467       setring EXTHNEring(EXTHNEnumber);
2468       list HNEs=hole(HNEs);
2469       list azeilen=hole(azeilen);
2470       ideal deltais=hole(deltais);
2471       number delta=number(hole(delta));
2472       poly f=hole(f);
2473     }
2474     kill HNerg;
2475 //----------------------------------------------------------------------------
2476 // HNerg muss jedesmal mit "list" neu definiert werden, weil vorher noch nicht
2477 // ------- klar ist, ob der Ring nach Aufruf von HN noch derselbe ist --------
2478
2479 //============= Verknuepfe bisherige HNE mit von HN gelieferten HNEs: ========
2480     if (R==0) {
2481       HNEs,hnezaehler=constructHNEs(HNEs,hnezaehler,aneu,azeilen,zeile,
2482                       deltais,Q,j);
2483     }
2484     else {
2485      for (zaehler=1; zaehler<=size(aneu); zaehler++) {
2486       hnezaehler++;
2487       HNEs[hnezaehler]=azeilen; // dupliziere den gemeinsamen Anfang der HNE's
2488       zl=2;
2489 //---------------- Trage Beitrag dieser Transformation T2 ein: ---------------
2490 //--------- Zur Bedeutung von zeile, zl: siehe Kommentar weiter oben ---------
2491
2492 //--------- vollziehe Euklid.Alg. nach, um die HN-Matrix zu berechnen: -------
2493       M1=M;N1=N;R1=R;Q1=M1/ N1;
2494       while (R1!=0) {
2495        if (defined(Protokoll)) { "h("+string(zeile+zl-2)+") =",Q1; }
2496        HNEs=set_list(HNEs,intvec(hnezaehler,1,zeile+zl-1),Q1);
2497        HNEs=set_list(HNEs,intvec(hnezaehler,zeile+zl,Q1+1),x);
2498                                 // Markierung des Zeilenendes der HNE
2499        zl=zl+1;
2500 //-------- Bereitstellung von Speicherplatz fuer eine neue Zeile: ------------
2501        HNEs=set_list(HNEs,intvec(hnezaehler,zeile+zl),ideal(0));
2502        M1=N1; N1=R1; R1=M1%N1; Q1=M1 / N1;
2503       }
2504       if (defined(Protokoll)) {
2505         "a("+string(zeile+zl-2)+","+string(Q1)+") =",delta;
2506       }
2507       HNEs=set_list(HNEs,intvec(hnezaehler,zeile+zl,Q1),delta);
2508
2509 //--- Daten aus T2_Transform sind eingetragen; haenge Daten von HN an: -------
2510       hilfid=HNEs[hnezaehler][zeile+zl];
2511       for (zl1=Q1+1; zl1<=ncols(aneu[zaehler][2]); zl1++) {
2512        hilfid[zl1]=aneu[zaehler][2][zl1];
2513       }
2514       HNEs=set_list(HNEs,intvec(hnezaehler,zeile+zl),hilfid);
2515 //--- vorher HNEs[.][zeile+zl]<-aneu[.][2], jetzt [zeile+zl+1] <- [3] usw.: --
2516       for (zl1=3; zl1<=size(aneu[zaehler]); zl1++) {
2517        HNEs=set_list(HNEs,intvec(hnezaehler,zeile+zl+zl1-2),
2518             aneu[zaehler][zl1]);
2519       }
2520 //--- setze die hqs zusammen: HNEs[hnezaehler][1]=HNEs[..][1],aneu[..][1] ----
2521       hilfvec=HNEs[hnezaehler][1],aneu[zaehler][1];
2522       HNEs=set_list(HNEs,intvec(hnezaehler,1),hilfvec);
2523 //----------- weil nicht geht: liste[1]=liste[1],aneu[zaehler][1] ------------
2524      }                     // end(for zaehler)
2525     }                      // endelse (R<>0)
2526    }                       // endif (subst()!=0)  (weiteres Aufblasen mit HN)
2527
2528   }                        // end(for j) (Behandlung der einzelnen delta_i)
2529
2530  }
2531  keepring basering;
2532  if (defined(transfproc)) { return(list(HNEs,transfproc)); }
2533  else                     { return(list(HNEs,poly(-1))); }
2534 // -1 als 2. Rueckgabewert zeigt an, dass kein Ringwechsel stattgefunden hat -
2535 }
2536 else {
2537  HNEs[1]=list(hqs)+azeilen+list(f); // f ist das transform. Poly oder Null
2538  keepring basering;
2539  return(list(HNEs,poly(-1)));
2540 //-- in dieser proc trat keine Verzweigung auf, also auch kein Ringwechsel ---
2541 }
2542}
2543///////////////////////////////////////////////////////////////////////////////
2544
2545proc constructHNEs (list HNEs,int hnezaehler,list aneu,list azeilen,int zeile,ideal deltais,int Q,int j)
2546NOTE: This procedure is only for internal use, it is called via HN
2547{
2548  int zaehler,zl;
2549  ideal hilfid;
2550  list hilflist;
2551  intvec hilfvec;
2552  for (zaehler=1; zaehler<=size(aneu); zaehler++) {
2553     hnezaehler++;
2554     HNEs[hnezaehler]=azeilen;            // dupliziere gemeins. Anfang
2555 //----------------------- trage neu berechnete Daten ein ---------------------
2556     hilfid=HNEs[hnezaehler][zeile+2];
2557     hilfid[Q]=deltais[j];
2558     for (zl=Q+1; zl<=ncols(aneu[zaehler][2]); zl++) {
2559      hilfid[zl]=aneu[zaehler][2][zl];
2560     }
2561     hilflist=HNEs[hnezaehler];hilflist[zeile+2]=hilfid;
2562 //------------------ haenge uebrige Zeilen von aneu[] an: --------------------
2563     for (zl=3; zl<=size(aneu[zaehler]); zl++) {
2564      hilflist[zeile+zl]=aneu[zaehler][zl];
2565     }
2566 //--- setze die hqs zusammen: HNEs[hnezaehler][1]=HNEs[..][1],aneu[..][1] ----
2567     if (hilflist[1]==0) { hilflist[1]=aneu[zaehler][1]; }
2568     else { hilfvec=hilflist[1],aneu[zaehler][1];hilflist[1]=hilfvec; }
2569     HNEs[hnezaehler]=hilflist;
2570  }
2571  return(HNEs,hnezaehler);
2572}
2573///////////////////////////////////////////////////////////////////////////////
2574
2575proc extrafactor (poly leitf, int M, int N)
2576USAGE:   factors,flag=extrafactor(f,M,N);
2577         list factors, int flag,M,N, poly f in x,y
2578ASSUME:  basering is (0,a),(x,y),ds or ls
2579         Newtonpolygon of f is one side with height N, length M
2580RETURN:  for some special f, factors is a list of the factors of
2581         charPoly(f,M,N), same format as factorize
2582         (see help charPoly; help factorize)
2583         In this case, flag!=0 (TRUE). If extrafactor cannot factorize f,
2584         flag will be 0 (FALSE), factors will be the empty list.
2585NOTE:    This procedure is designed to make reddevelop able to compute some
2586         special cases that need a ring extension in char 0.
2587         It becomes obsolete as soon as factorize works also in such rings.
2588EXAMPLE: example extrafactor;  shows an example
2589{
2590 list faktoren;
2591
2592      if (a2==-1) {
2593       poly testpol=charPoly(leitf,M,N);
2594       if (testpol==1+2y2+y4) {
2595         faktoren=list(ideal(y+a,y-a),intvec(2,2));
2596         testpol=0;
2597       }
2598 //------------ ist Poly von der Form q*i+r*y^n, n in N, q,r in Q ?: ----------
2599       if ((size(testpol)==2) && (find(string(lead(testpol)),"a")>0)
2600           && (find(string(testpol-lead(testpol)),"a")==0)) {
2601        faktoren=list(ideal(testpol),intvec(1));
2602        testpol=0;
2603       }
2604      }
2605      if (a4==-625) {
2606        poly testpol=charPoly(leitf,M,N);
2607        if (testpol==4a2-4y2)
2608         { faktoren=list(ideal(-4,y+a,y-a),intvec(1,1,1)); testpol=0;}
2609        if (testpol==-4a2-4y2)
2610         { faktoren=list(ideal(-4,y+1/25*a3,y-1/25*a3),intvec(1,1,1));
2611           testpol=0;}
2612      }
2613      if (defined(testpol)==0) { poly testpol=1; }
2614      if (testpol!=0) {
2615        "factorize not implemented in char (0,a)!";
2616        "could not factorize:",charPoly(leitf,M,N); pause;
2617      }
2618 return(faktoren,(testpol==0)); // Test: faktoren==list() geht leider nicht
2619}
2620example
2621{ "EXAMPLE:"; echo=2;
2622  ring r=(0,a),(x,y),ds;
2623  minpoly=a2+1;
2624  poly f=x4+2x2y2+y4;
2625  charPoly(f,4,4);
2626  list factors;
2627  int flag;
2628  factors,flag=extrafactor(f,4,4);
2629  if (flag!=0) {factors;}
2630}
Note: See TracBrowser for help on using the repository browser.