source: git/Singular/LIB/zeroset.lib @ c669be

fieker-DuValspielwiese
Last change on this file since c669be was f267f3, checked in by Hans Schoenemann <hannes@…>, 14 years ago
removed debug stuff git-svn-id: file:///usr/local/Singular/svn/trunk@12853 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 45.3 KB
Line 
1// Last change 12.02.2001 (Eric Westenberger)
2///////////////////////////////////////////////////////////////////////////////
3version="$Id$";
4category="Symbolic-numerical solving";
5info="
6LIBRARY:  zeroset.lib      Procedures for roots and factorization
7AUTHOR:   Thomas Bayer,    email: tbayer@mathematik.uni-kl.de,@*
8          http://wwwmayr.informatik.tu-muenchen.de/personen/bayert/@*
9          Current address: Hochschule Ravensburg-Weingarten
10
11OVERVIEW:
12 Algorithms for finding the zero-set of a zero-dim. ideal in Q(a)[x_1,..,x_n],
13 roots and factorization of univariate polynomials over Q(a)[t]
14 where a is an algebraic number. Written in the scope of the
15 diploma thesis (advisor: Prof. Gert-Martin Greuel) 'Computations of moduli
16 spaces of semiquasihomogeneous singularities and an implementation in Singular'.
17 This library is meant as a preliminary extension of the functionality
18 of @sc{Singular} for univariate factorization of polynomials over simple algebraic
19 extensions in characteristic 0.
20
21 NOTE:
22 Subprocedures with postfix 'Main' require that the ring contains a variable
23 'a' and no parameters, and the ideal 'mpoly', where 'minpoly' from the
24 basering is stored.
25
26PROCEDURES:
27 Quotient(f, g)    quotient q  of f w.r.t. g (in f = q*g + remainder)
28 remainder(f,g)    remainder of the division of f by g
29 roots(f)    computes all roots of f in an extension field of Q
30 sqfrNorm(f)    norm of f (f must be squarefree)
31 zeroSet(I)    zero-set of the 0-dim. ideal I
32
33AUXILIARY PROCEDURES:
34 egcdMain(f, g)    gcd over an algebraic extension field of Q
35 factorMain(f)    factorization of f over an algebraic extension field
36 invertNumberMain(c)  inverts an element of an algebraic extension field
37 quotientMain(f, g)  quotient of f w.r.t. g
38 remainderMain(f,g)  remainder of the division of f by g
39 rootsMain(f)    computes all roots of f, might extend the ground field
40 sqfrNormMain(f)  norm of f (f must be squarefree)
41 containedQ(data, f)  f in data ?
42 sameQ(a, b)    a == b (list a,b)
43";
44
45LIB "primitiv.lib";
46LIB "primdec.lib";
47
48// note : return a ring : ring need not be exported !!!
49
50// Artihmetic in Q(a)[x] without built-in procedures
51// assume basering = Q[x,a] and minpoly is represented by mpoly(a).
52// the algorithms are taken from "Polynomial Algorithms in Computer Algebra",
53// F. Winkler, Springer Verlag Wien, 1996.
54
55
56// To do :
57// squarefree factorization
58// multiplicities
59
60// Improvement :
61// a main problem is the growth of the coefficients. Try roots(x7 - 1)
62// return ideal mpoly !
63// mpoly is not monic, comes from primitive_extra
64
65// IMPLEMENTATION
66//
67// In procedures with name 'proc-name'Main a polynomial ring over a simple
68// extension field is represented as Q[x...,a] together with the ideal
69// 'mpoly' (attribute "isSB"). The arithmetic in the extension field is
70// implemented in the procedures in the procedures 'MultPolys' (multiplication)
71// and 'InvertNumber' (inversion). After addition and substraction one should
72// apply 'SimplifyPoly' to the result to reduce the result w.r.t. 'mpoly'.
73// This is done by reducing each coefficient seperately, which is more
74// efficient for polynomials with many terms.
75
76
77///////////////////////////////////////////////////////////////////////////////
78
79proc roots(poly f)
80"USAGE:   roots(f); where f is a polynomial
81PURPOSE: compute all roots of f in a finite extension of the ground field
82         without multiplicities.
83RETURN:  ring, a polynomial ring over an extension field of the ground field,
84         containing a list 'theRoots' and polynomials 'newA' and 'f':
85  @format
86  - 'theRoots' is the list of roots of the polynomial f (no multiplicities)
87  - if the ground field is Q(a') and the extension field is Q(a), then
88    'newA' is the representation of a' in Q(a).
89    If the basering contains a parameter 'a' and the minpoly remains unchanged
90    then 'newA' = 'a'.
91    If the basering does not contain a parameter then 'newA' = 'a' (default).
92  - 'f' is the polynomial f in Q(a) (a' being substituted by 'newA')
93  @end format
94ASSUME:  ground field to be Q or a simple extension of Q given by a minpoly
95EXAMPLE: example roots; shows an example
96"
97{
98  int dbPrt = printlevel-voice+3;
99
100  // create a new ring where par(1) is replaced by the variable
101  // with the same name or, if basering does not contain a parameter,
102  // with a new variable 'a'.
103
104  def ROB = basering;
105  def ROR = TransferRing(basering);
106  setring ROR;
107  export(ROR);
108
109  // get the polynomial f and find the roots
110
111  poly f = imap(ROB, f);
112  list result = rootsMain(f);  // find roots of f
113
114  // store the roots and the new representation of 'a' and transform
115  // the coefficients of f.
116
117  list theRoots = result[1];
118  poly newA = result[2];
119  map F = basering, maxideal(1);
120  F[nvars(basering)] = newA;
121  poly fn = SimplifyPoly(F(f));
122
123  // create a new ring with minploy = mpoly[1] (from ROR)
124
125  def RON = NewBaseRing();
126  setring(RON);
127  list theRoots = imap(ROR, theRoots);
128  poly newA = imap(ROR, newA);
129  poly f = imap(ROR, fn);
130  kill ROR;
131  export(theRoots);
132  export(newA);
133  export(f); dbprint(dbPrt,"
134// 'roots' created a new ring which contains the list 'theRoots' and
135// the polynomials 'f' and 'newA'
136// To access the roots, newA and the new representation of f, type
137   def R = roots(f); setring R; theRoots; newA; f;
138");
139  return(RON);
140}
141example
142{"EXAMPLE:";  echo = 2;
143  ring R = (0,a), x, lp;
144  minpoly = a2+1;
145  poly f = x3 - a;
146  def R1 = roots(f);
147  setring R1;
148  minpoly;
149  newA;
150  f;
151  theRoots;
152  map F;
153  F[1] = theRoots[1];
154  F(f);
155}
156
157///////////////////////////////////////////////////////////////////////////////
158
159proc rootsMain(poly f)
160"USAGE:   rootsMain(f); where f is a polynomial
161PURPOSE: compute all roots of f in a finite extension of the ground field
162         without multiplicities.
163RETURN:  list, all entries are polynomials
164  @format
165  _[1] = roots of f, each entry is a polynomial
166  _[2] = 'newA' - if the ground field is Q(b) and the extension field
167         is Q(a), then 'newA' is the representation of b in Q(a)
168  _[3] = minpoly of the algebraic extension of the ground field
169  @end format
170ASSUME:  basering = Q[x,a] ideal mpoly must be defined, it might be 0!
171NOTE:    might change the ideal mpoly!!
172EXAMPLE: example rootsMain; shows an example
173"
174{
175  int i, linFactors, nlinFactors, dbPrt;
176  intvec wt = 1,0;    // deg(a) = 0
177  list factorList, nlFactors, nlMult, roots, result;
178  poly fa, lc;
179
180  dbPrt = printlevel-voice+3;
181
182  // factor f in Q(a)[t] to obtain the roots lying in Q(a)
183  // firstly, find roots of the linear factors,
184  // nonlinear factors are processed later
185
186  dbprint(dbPrt, "roots of " + string(f) +  ", minimal polynomial = " + string(mpoly[1]));
187  factorList = factorMain(f);          // Factorize f
188  dbprint(dbPrt, (" prime factors of f are : " + string(factorList[1])));
189
190  linFactors = 0;
191  nlinFactors = 0;
192  for(i = 2; i <= size(factorList[1]); i = i + 1) {  // find linear and nonlinear factors
193    fa = factorList[1][i];
194    if(deg(fa, wt) == 1) {
195      linFactors++;        // get the root from the linear factor
196      lc = LeadTerm(fa, 1)[3];
197      fa = MultPolys(invertNumberMain(lc), fa); // make factor monic
198      roots[linFactors] = var(1) - fa;  // fa is monic !!
199    }
200    else {            // ignore nonlinear factors
201      nlinFactors++;
202      nlFactors[nlinFactors] = factorList[1][i];
203      nlMult[nlinFactors] = factorList[2][i];
204    }
205  }
206  if(linFactors == size(factorList[1]) - 1) {    // all roots of f are contained in the ground field
207    result[1] = roots;
208    result[2] = var(2);
209    result[3] = mpoly[1];
210    return(result);
211  }
212
213  // process the nonlinear factors, i.e., extend the ground field
214  // where a nonlinear factor (irreducible) is a minimal polynomial
215  // compute the primitive element of this extension
216
217  ideal primElem, minPolys, Fid;
218  list partSol;
219  map F, Xchange;
220  poly f1, newA, mp, oldMinPoly;
221
222  Fid = mpoly;
223  F[1] = var(1);
224  Xchange[1] = var(2);      // the variables have to be exchanged
225  Xchange[2] = var(1);      // for the use of 'primitive'
226
227  if(nlinFactors == 1)             // one nl factor
228  {
229    // compute the roots of the nonlinear (irreducible, monic) factor f1 of f
230    // by extending the basefield by a' with minimal polynomial f1
231    // Then call roots(f1) to find the roots of f1 over the new base field
232
233    f1 = nlFactors[1];
234    if(mpoly[1] != 0)
235    {
236      mp = mpoly[1];
237      minPolys = Xchange(mp), Xchange(f1);
238      if (deg(jet(minPolys[2],0,intvec(1,0)))==0)
239      { primElem = primitive(minPolys); } // random coord. change
240      else
241      { primElem = primitive_extra(minPolys); } // no random coord. change
242      mpoly = std(primElem[1]);
243      F = basering, maxideal(1);
244      F[2] = primElem[2];      // transfer all to the new representation
245      newA = primElem[2];      // new representation of a
246      f1 = SimplifyPoly(F(f1));     //reduce(F(f1), mpoly);
247      if(size(roots) > 0) {roots = SimplifyData(F(roots));}
248    }
249    else {
250      mpoly = std(Xchange(f1));
251      newA = var(2);
252    }
253    result[3] = mpoly[1];
254    oldMinPoly = mpoly[1];
255    partSol = rootsMain(f1);    // find roots of f1 over extended field
256
257    if(oldMinPoly != partSol[3]) {    // minpoly has changed ?
258      // all previously computed roots must be transformed
259      // because the minpoly has changed
260      result[3] = partSol[3];    // new minpoly
261      F[2] = partSol[2];    // new representation of algebraic number
262      if(size(roots) > 0) {roots = SimplifyData(F(roots)); }
263      newA = SimplifyPoly(F(newA)); // F(newA);
264    }
265    roots = roots + partSol[1];  // add roots
266    result[2] = newA;
267    result[1] = roots;
268  }
269  else {  // more than one nonlinear (irreducible) factor (f_1,...,f_r)
270    // solve each of them by rootsMain(f_i), append their roots
271    // change the minpoly and transform all previously computed
272    // roots if necessary.
273    // Note that the for-loop is more or less book-keeping
274
275    newA = var(2);
276    result[2] = newA;
277    for(i = 1; i <= size(nlFactors); i = i + 1) {
278      oldMinPoly = mpoly[1];
279      partSol = rootsMain(nlFactors[i]);    // main work
280      nlFactors[i] = 0;        // delete factor
281      result[3] = partSol[3];        // store minpoly
282
283      // book-keeping starts here as in the case 1 nonlinear factor
284
285      if(oldMinPoly != partSol[3]) { // minpoly has changed
286        F = basering, maxideal(1);
287        F[2] = partSol[2];    // transfer all to the new representation
288        newA = SimplifyPoly(F(newA));    // F(newA); new representation of a
289        result[2] = newA;
290        if(i < size(nlFactors)) {
291          nlFactors = SimplifyData(F(nlFactors));
292        } // transform remaining factors
293        if(size(roots) > 0) {roots = SimplifyData(F(roots));}
294      }
295      roots = roots + partSol[1];    // transform roots
296      result[1] = roots;
297    }  // end more than one nl factor
298
299  }
300  return(result);
301}
302
303///////////////////////////////////////////////////////////////////////////////
304
305proc zeroSet(ideal I, list #)
306"USAGE:   zeroSet(I [,opt] ); I=ideal, opt=integer
307PURPOSE: compute the zero-set of the zero-dim. ideal I, in a finite extension
308         of the ground field.
309RETURN:  ring, a polynomial ring over an extension field of the ground field,
310         containing a list 'theZeroset', a polynomial 'newA', and an
311         ideal 'id':
312  @format
313  - 'theZeroset' is the list of the zeros of the ideal I, each zero is an ideal.
314  - if the ground field is Q(b) and the extension field is Q(a), then
315    'newA' is the representation of b in Q(a).
316    If the basering contains a parameter 'a' and the minpoly remains unchanged
317    then 'newA' = 'a'.
318    If the basering does not contain a parameter then 'newA' = 'a' (default).
319  - 'id' is the ideal I in Q(a)[x_1,...] (a' substituted by 'newA')
320  @end format
321ASSUME:  dim(I) = 0, and ground field to be Q or a simple extension of Q given
322         by a minpoly.
323OPTIONS: opt = 0: no primary decomposition (default)
324         opt > 0: primary decomposition
325NOTE:    If I contains an algebraic number (parameter) then I must be
326         transformed w.r.t. 'newA' in the new ring.
327EXAMPLE: example zeroSet; shows an example
328"
329{
330  int primaryDecQ, dbPrt;
331  list rp;
332
333  dbPrt = printlevel-voice+2;
334
335  if(size(#) > 0) { primaryDecQ = #[1]; }
336  else { primaryDecQ = 0; }
337
338  // create a new ring 'ZSR' with one additional variable instead of the
339  // parameter
340  // if the basering does not contain a parameter then 'a' is used as the
341  // additional variable.
342
343  def RZSB = basering;
344  def ZSR = TransferRing(RZSB);
345  setring ZSR;
346
347  // get ideal I and find the zero-set
348
349  ideal id = std(imap(RZSB, I));
350//  print(dim(id));
351  if(dim(id) > 1) {       // new variable adjoined to ZSR
352    ERROR(" ideal not zerodimensional ");
353  }
354
355  list result = zeroSetMain(id, primaryDecQ);
356
357  // store the zero-set, minimal polynomial and the new representative of 'a'
358
359  list theZeroset = result[1];
360  poly newA = result[2];
361  poly minPoly = result[3][1];
362
363  // transform the generators of the ideal I w.r.t. the new representation
364  // of 'a'
365
366  map F = basering, maxideal(1);
367  F[nvars(basering)] = newA;
368  id = SimplifyData(F(id));
369
370  // create a new ring with minpoly = minPoly
371
372  def RZBN = NewBaseRing();
373  setring RZBN;
374
375  list theZeroset = imap(ZSR, theZeroset);
376  poly newA = imap(ZSR, newA);
377  ideal id = imap(ZSR, id);
378  kill ZSR;
379
380  export(id);
381  export(theZeroset);
382  export(newA);
383    dbprint(dbPrt,"
384// 'zeroSet' created a new ring which contains the list 'theZeroset', the ideal
385// 'id' and the polynomial 'newA'. 'id' is the ideal of the input transformed
386// w.r.t. 'newA'.
387// To access the zero-set, 'newA' and the new representation of the ideal, type
388   def R = zeroSet(I); setring R; theZeroset; newA; id;
389");
390  setring RZSB;
391  return(RZBN);
392}
393example
394{"EXAMPLE:";  echo = 2;
395  ring R = (0,a), (x,y,z), lp;
396  minpoly = a2 + 1;
397  ideal I = x2 - 1/2, a*z - 1, y - 2;
398  def T = zeroSet(I);
399  setring T;
400  minpoly;
401  newA;
402  id;
403  theZeroset;
404  map F1 = basering, theZeroset[1];
405  map F2 = basering, theZeroset[2];
406  F1(id);
407  F2(id);
408}
409
410///////////////////////////////////////////////////////////////////////////////
411
412proc invertNumberMain(poly f)
413"USAGE:   invertNumberMain(f); where f is a polynomial
414PURPOSE: compute 1/f if f is a number in Q(a), i.e., f is represented by a
415         polynomial in Q[a].
416RETURN:  poly 1/f
417ASSUME:  basering = Q[x_1,...,x_n,a], ideal mpoly must be defined and != 0 !
418NOTE:    outdated, use / instead
419"
420{
421  if(diff(f, var(1)) != 0) { ERROR("number must not contain variable !");}
422
423  int n = nvars(basering);
424  def RINB = basering;
425  string ringSTR = "ring RINR = 0, " + string(var(n)) + ", dp;";
426  execute(ringSTR);        // new ring = Q[a]
427
428  list gcdList;
429  poly f, g, inv;
430
431  f = imap(RINB, f);
432  g = imap(RINB, mpoly)[1];
433
434  if(diff(f, var(1)) != 0) { inv = extgcd(f, g)[2]; }  // f contains var(1)
435  else {  inv = 1/f;}          // f element in Q
436
437  setring(RINB);
438  return(imap(RINR, inv));
439}
440
441///////////////////////////////////////////////////////////////////////////////
442
443proc MultPolys(poly f, poly g)
444"USAGE:   MultPolys(f, g); poly f,g
445PURPOSE: multiply the polynomials f and g and reduce them w.r.t. mpoly
446RETURN:  poly f*g
447ASSUME:  basering = Q[x,a], ideal mpoly must be defined, it might be 0 !
448"
449{
450  return(SimplifyPoly(f * g));
451}
452
453///////////////////////////////////////////////////////////////////////////////
454
455proc LeadTerm(poly f, int i)
456"USAGE:   LeadTerm(f); poly f, int i
457PURPOSE: compute the leading coef and term of f w.r.t var(i), where the last
458         ring variable is treated as a parameter.
459RETURN:  list of polynomials
460         _[1] = leading term
461         _[2] = leading monomial
462         _[3] = leading coefficient
463ASSUME:  basering = Q[x_1,...,x_n,a]
464"
465{
466  list result;
467  matrix co = coef(f, var(i));
468  result[1] = co[1, 1]*co[2, 1];
469  result[2] = co[1, 1];
470  result[3] = co[2, 1];
471  return(result);
472}
473
474///////////////////////////////////////////////////////////////////////////////
475
476proc Quotient(poly f, poly g)
477"USAGE:   Quotient(f, g); where f,g are polynomials;
478PURPOSE: compute the quotient q and remainder r s.t. f = g*q + r, deg(r) < deg(g)
479RETURN:  list of polynomials
480  @format
481  _[1] = quotient  q
482  _[2] = remainder r
483  @end format
484ASSUME:  basering = Q[x] or Q(a)[x]
485NOTE: This procedure is outdated, and should no longer be used. Use div and mod
486instead.
487EXAMPLE: example Quotient; shows an example
488"
489{
490  def QUOB = basering;
491  def QUOR = TransferRing(basering);  // new ring with parameter 'a' replaced by a variable
492  setring QUOR;
493  export(QUOR);
494  poly f = imap(QUOB, f);
495  poly g = imap(QUOB, g);
496  list result = quotientMain(f, g);
497
498  setring(QUOB);
499  list result = imap(QUOR, result);
500  kill QUOR;
501  return(result);
502}
503example
504{"EXAMPLE:";  echo = 2;
505 ring R = (0,a), x, lp;
506 minpoly = a2+1;
507 poly f =  x4 - 2;
508 poly g = x - a;
509 list qr = Quotient(f, g);
510 qr;
511 qr[1]*g + qr[2] - f;
512}
513
514proc quotientMain(poly f, poly g)
515"USAGE:   quotientMain(f, g); where f,g are polynomials
516PURPOSE: compute the quotient q and remainder r s.th. f = g*q + r, deg(r) < deg(g)
517RETURN:  list of polynomials
518  @format
519  _[1] = quotient  q
520  _[2] = remainder r
521  @end format
522ASSUME:  basering = Q[x,a] and ideal mpoly is defined (it might be 0),
523         this represents the ring Q(a)[x] together with its minimal polynomial.
524NOTE: outdated, use div/mod instead
525"
526{
527  if(g == 0) { ERROR("Division by zero !");}
528
529  def QMB = basering;
530  def QMR = NewBaseRing();
531  setring QMR;
532  poly f, g, h;
533  h = imap(QMB, f) / imap(QMB, g);
534  setring QMB;
535  return(list(imap(QMR, h), 0));
536}
537
538///////////////////////////////////////////////////////////////////////////////
539
540proc remainder(poly f, poly g)
541"USAGE:   remainder(f, g); where f,g are polynomials
542PURPOSE: compute the remainder of the division of f by g, i.e. a polynomial r
543         s.t. f = g*q + r, deg(r) < deg(g).
544RETURN:  poly
545ASSUME:  basering = Q[x] or Q(a)[x]
546NOTE: outdated, use mod/reduce instead
547"
548{
549  def REMB = basering;
550  def REMR = TransferRing(basering);  // new ring with parameter 'a' replaced by a variable
551  setring(REMR);
552  export(REMR);
553  poly f = imap(REMB, f);
554  poly g = imap(REMB, g);
555  poly h = remainderMain(f, g);
556
557  setring(REMB);
558  poly r = imap(REMR, h);
559  kill REMR;
560  return(r);
561}
562example
563{"EXAMPLE:";  echo = 2;
564 ring R = (0,a), x, lp;
565 minpoly = a2+1;
566 poly f =  x4 - 1;
567 poly g = x3 - 1;
568 remainder(f, g);
569}
570
571proc remainderMain(poly f, poly g)
572"USAGE:   remainderMain(f, g); where f,g are polynomials
573PURPOSE: compute the remainder r s.t. f = g*q + r, deg(r) < deg(g)
574RETURN:  poly
575ASSUME:  basering = Q[x,a] and ideal mpoly is defined (it might be 0),
576         this represents the ring Q(a)[x] together with its minimal polynomial.
577NOTE: outdated, use mod/reduce instead
578"
579{
580  int dg;
581  intvec wt = 1,0;;
582  poly lc, g1, r;
583
584  if(deg(g, wt) == 0) { return(0); }
585
586  lc = LeadTerm(g, 1)[3];
587  g1 = MultPolys(invertNumberMain(lc), g);  // make g monic
588
589  return(SimplifyPoly(reduce(f, std(g1))));
590}
591
592///////////////////////////////////////////////////////////////////////////////
593
594proc egcdMain(poly f, poly g)
595"USAGE:   egcdMain(f, g); where f,g are polynomials
596PURPOSE: compute the polynomial gcd of f and g over Q(a)[x]
597RETURN:  poly
598ASSUME:  basering = Q[x,a] and ideal mpoly is defined (it might be 0),
599         this represents the ring Q(a)[x] together with its minimal polynomial.
600NOTE: outdated, use gcd instead
601EXAMPLE: example EGCD; shows an example
602"
603{
604// might be extended to return s1, s2 s.t. f*s1 + g*s2 = gcd
605  int i = 1;
606  poly r1, r2, r;
607
608  r1 = f;
609  r2 = g;
610
611  while(r2 != 0) {
612    r  = remainderMain(r1, r2);
613    r1 = r2;
614    r2 = r;
615  }
616  return(r1);
617}
618
619///////////////////////////////////////////////////////////////////////////////
620
621proc MEGCD(poly f, poly g, int varIndex)
622"USAGE:   MEGCD(f, g, i); poly f, g; int i
623PURPOSE: compute  the polynomial gcd of f and g in the i'th variable
624RETURN:  poly
625ASSUME:  f, g are polynomials in var(i), last variable is the algebraic number
626EXAMPLE: example MEGCD; shows an example
627"
628// might be extended to return s1, s2 s.t. f*s1 + g*s2 = gc
629// not used !
630{
631  string @str, @sf, @sg, @mp, @parName;
632
633  def @RGCDB = basering;
634
635  @sf = string(f);
636  @sg = string(g);
637  @mp = string(minpoly);
638
639  if(npars(basering) == 0) { @parName = "0";}
640  else { @parName = "(0, " + parstr(basering) + ")"; }
641  @str = "ring @RGCD = " + @parName + ", " + string(var(varIndex)) + ", dp;";
642  execute(@str);
643  if(@mp != "0") { execute ("minpoly = " + @mp + ";"); }
644  execute("poly @f = " + @sf + ";");
645  execute("poly @g = " + @sg + ";");
646  export(@RGCD);
647  poly @h = gcd(@f, @g);
648  setring(@RGCDB);
649  poly h = imap(@RGCD, @h);
650  kill @RGCD;
651  return(h);
652}
653
654///////////////////////////////////////////////////////////////////////////////
655
656proc sqfrNorm(poly f)
657"USAGE:   sqfrNorm(f); where f is a polynomial
658PURPOSE: compute the norm of the squarefree polynomial f in Q(a)[x].
659RETURN:  list with 3 entries
660  @format
661  _[1] = squarefree norm of g (poly)
662  _[2] = g (= f(x - s*a)) (poly)
663  _[3] = s (int)
664  @end format
665ASSUME:  f must be squarefree, basering = Q(a)[x] and minpoly != 0.
666NOTE:    the norm is an element of Q[x]
667EXAMPLE: example sqfrNorm; shows an example
668"
669{
670  def SNB = basering;
671  def SNR = TransferRing(SNB);  // new ring with parameter 'a'
672                                // replaced by a variable
673  setring SNR;
674  poly f = imap(SNB, f);
675  list result = sqfrNormMain(f);  // squarefree norm of f
676
677  setring SNB;
678  list result = imap(SNR, result);
679  kill SNR;
680  return(result);
681}
682example
683{"EXAMPLE:";  echo = 2;
684   ring R = (0,a), x, lp;
685   minpoly = a2+1;
686  poly f =  x4 - 2*x + 1;
687  sqfrNorm(f);
688}
689
690proc sqfrNormMain(poly f)
691"USAGE:   sqfrNorm(f); where f is a polynomial
692PURPOSE: compute the norm of the squarefree polynomial f in Q(a)[x].
693RETURN:  list with 3 entries
694  @format
695  _[1] = squarefree norm of g (poly)
696  _[2] = g (= f(x - s*a)) (poly)
697  _[3] = s (int)
698  @end format
699ASSUME:  f must be squarefree, basering = Q[x,a] and ideal mpoly is equal to
700         'minpoly', this represents the ring Q(a)[x] together with 'minpoly'.
701NOTE:   the norm is an element of Q[x]
702EXAMPLE: example SqfrNorm; shows an example
703"
704{
705  def SNRMB = basering;
706  int s = 0;
707  intvec wt = 1,0;
708  ideal mapId;
709  // list result;
710  poly g, N, N1, h;
711  string ringSTR;
712
713  mapId[1] = var(1) - var(2);    // linear transformation
714  mapId[2] = var(2);
715  map Fs = SNRMB, mapId;
716
717  N = resultant(f, mpoly[1], var(2));  // norm of f
718  N1 = diff(N, var(1));
719  g = f;
720
721  ringSTR = "ring SNRM1 = 0, " + string(var(1)) + ", dp;";  // univariate ring
722  execute(ringSTR);
723  poly N, N1, h;        // N, N1 do not contain 'a', use built-in gcd
724  h = gcd(imap(SNRMB, N), imap(SNRMB, N1));
725  setring(SNRMB);
726  h = imap(SNRM1, h);
727  while(deg(h, wt) != 0) {    // while norm is not squarefree
728    s = s + 1;
729    g = reduce(Fs(g), mpoly);
730    N = reduce(resultant(g, mpoly[1], var(2)), mpoly);  // norm of g
731    N1 = reduce(diff(N, var(1)), mpoly);
732    setring(SNRM1);
733    h = gcd(imap(SNRMB, N), imap(SNRMB, N1));
734    setring(SNRMB);
735    h = imap(SNRM1, h);
736  }
737  return(list(N, g, s));
738}
739
740///////////////////////////////////////////////////////////////////////////////
741
742proc factorMain(poly f)
743"USAGE:   factorMain(f); where f is a polynomial
744PURPOSE: compute the factorization of the squarefree polynomial f over Q(a)[t],
745         minpoly  = p(a).
746RETURN:  list with 2 entries
747  @format
748  _[1] = factors, first is a constant
749  _[2] = multiplicities (not yet implemented)
750  @end format
751ASSUME:  basering = Q[x,a], representing Q(a)[x]. An ideal mpoly must
752         be defined, representing the minimal polynomial (it might be 0!).
753NOTE: outdated, use factorize instead
754EXAMPLE: example Factor; shows an example
755"
756{
757// extend this by a squarefree factorization !!
758// multiplicities are not valid !!
759  int i, s;
760  list normList, factorList, quo_rem;
761  poly f1, h, h1, H, g, leadCoef, invCoeff;
762  ideal fac1, fac2;
763  map F;
764
765  // if no minimal polynomial is defined then use 'factorize'
766  // FactorOverQ is wrapped around 'factorize'
767
768  if(mpoly[1] == 0) {
769    // print(" factorize : deg = " + string(deg(f, intvec(1,0))));
770    factorList = factorize(f); // FactorOverQ(f);
771    return(factorList);
772  }
773
774  // if mpoly != 0 and f does not contain the algebraic number, a root of
775  // f might be contained in Q(a). Hence one must not use 'factorize'.
776
777  fac1[1] = 1;
778  fac2[1] = 1;
779  normList = sqfrNormMain(f);
780  // print(" factorize : deg = " + string(deg(normList[1], intvec(1,0))));
781  factorList = factorize(normList[1]);     // factor squarefree norm of f over Q[x]
782  g = normList[2];
783  s = normList[3];
784  F[1] = var(1) + s*var(2);      // inverse transformation
785  F[2] = var(2);
786  fac1[1] = factorList[1][1];
787  fac2[1] = factorList[2][1];
788  for(i = 2; i <= size(factorList[1]); i = i + 1) {
789    H = factorList[1][i];
790    h = egcdMain(H, g);
791    quo_rem = quotientMain(g, h);
792    g = quo_rem[1];
793    fac1[i] = SimplifyPoly(F(h));
794    fac2[i] = 1;        // to be changed later
795  }
796  return(list(fac1, fac2));
797}
798
799///////////////////////////////////////////////////////////////////////////////
800
801proc zeroSetMain(ideal I, int primDecQ)
802"USAGE:   zeroSetMain(ideal I, int opt); ideal I, int opt
803PURPOSE: compute the zero-set of the zero-dim. ideal I, in a simple extension
804         of the ground field.
805RETURN:  list
806         - 'f' is the polynomial f in  Q(a) (a' being substituted by newA)
807         _[1] = zero-set (list), is the list of the zero-set of the ideal I,
808                each entry is an ideal.
809         _[2] = 'newA';  if the ground field is Q(a') and the extension field
810                is Q(a), then 'newA' is the representation of a' in Q(a).
811                If the basering contains a parameter 'a' and the minpoly
812                remains unchanged then 'newA' = 'a'. If the basering does not
813                contain a parameter then 'newA' = 'a' (default).
814         _[3] = 'mpoly' (ideal), the minimal polynomial of the simple extension
815                of the ground field.
816ASSUME:  basering = K[x_1,x_2,...,x_n] where K = Q or a simple extension of Q
817         given by a minpoly; dim(I) = 0.
818NOTE:    opt = 0  no primary decomposition
819         opt > 0  use a primary decomposition
820EXAMPLE: example zeroSetMain; shows an example
821"
822{
823  // main work is done in zeroSetMainWork, here the zero-set of each ideal from the
824  // primary decompostion is coputed by menas of zeroSetMainWork, and then the
825  // minpoly and the parameter representing the algebraic extension are
826  // transformed according to 'newA', i.e., only bookeeping is done.
827
828  def altring=basering;
829  int i, j, n, noMP, dbPrt;
830  intvec w;
831  list currentSol, result, idealList, primDecList, zeroSet;
832  ideal J;
833  map Fa;
834  poly newA, oldMinPoly;
835
836  dbPrt = printlevel-voice+2;
837  dbprint(dbPrt, "zeroSet of " + string(I) + ", minpoly = " + string(minpoly));
838
839  n = nvars(basering) - 1;
840  for(i = 1; i <= n; i++) { w[i] = 1;}
841  w[n + 1] = 0;
842
843  if(primDecQ == 0) { return(zeroSetMainWork(I, w, 0)); }
844
845  newA = var(n + 1);
846  if(mpoly[1] == 0) { noMP = 1;}
847  else {noMP = 0;}
848
849  primDecList = primdecGTZ(I);      // primary decomposition
850  dbprint(dbPrt, "primary decomposition consists of " + string(size(primDecList)) + " primary ideals ");
851  // idealList = PDSort(idealList);    // high degrees first
852
853  for(i = 1; i <= size(primDecList); i = i + 1) {
854    idealList[i] = primDecList[i][2];  // use prime component
855    dbprint(dbPrt, string(i) + "  " + string(idealList[i]));
856  }
857
858  // compute the zero-set of each primary ideal and join them.
859  // If necessary, change the ground field and transform the zero-set
860
861  dbprint(dbPrt, "
862find the zero-set of each primary ideal, form the union
863and keep track of the minimal polynomials ");
864
865  for(i = 1; i <= size(idealList); i = i + 1) {
866    J = idealList[i];
867    idealList[i] = 0;
868    oldMinPoly = mpoly[1];
869    dbprint(dbPrt, " ideal#" + string(i) + " of " + string(size(idealList)) + " = " + string(J));
870    currentSol = zeroSetMainWork(J, w, 0);
871
872    if(oldMinPoly != currentSol[3]) {   // change minpoly and transform solutions
873      dbprint(dbPrt, " change minpoly to " + string(currentSol[3][1]));
874      dbprint(dbPrt, " new representation of algebraic number = " + string(currentSol[2]));
875      if(!noMP) {      // transform the algebraic number a
876        Fa = basering, maxideal(1);
877        Fa[n + 1] = currentSol[2];
878        newA = SimplifyPoly(Fa(newA));  // new representation of a
879        if(size(zeroSet) > 0) {zeroSet = SimplifyZeroset(Fa(zeroSet)); }
880        if(i < size(idealList)) { idealList = SimplifyZeroset(Fa(idealList)); }
881      }
882      else { noMP = 0;}
883    }
884    zeroSet = zeroSet + currentSol[1];    // add new elements
885  }
886  return(list(zeroSet, newA, mpoly));
887}
888
889///////////////////////////////////////////////////////////////////////////////
890
891proc zeroSetMainWork(ideal id, intvec wt, int sVars)
892"USAGE:   zeroSetMainWork(I, wt, sVars);
893PURPOSE: compute the zero-set of the zero-dim. ideal I, in a finite extension
894         of the ground field (without multiplicities).
895RETURN:  list, all entries are polynomials
896         _[1] = zeros, each entry is an ideal
897         _[2] = newA; if the ground field is Q(a') this is the rep. of a' w.r.t. a
898         _[3] = minpoly of the algebraic extension of the ground field (ideal)
899         _[4] = name of algebraic number (default = 'a')
900ASSUME:  basering = Q[x_1,x_2,...,x_n,a]
901         ideal mpoly must be defined, it might be 0!
902NOTE:    might change 'mpoly' !!
903EXAMPLE: example IdealSolve; shows an example
904"
905{
906  def altring=basering;
907  int i, j, k, nrSols, n, noMP;
908  ideal I, generators, gens, solid, partsolid;
909  list linSol, linearSolution, nLinSol, nonlinSolutions, partSol, sol, solutions, result;
910  list linIndex, nlinIndex, index;
911  map Fa, Fsubs;
912  poly oldMinPoly, newA;
913
914  if(mpoly[1] == 0) { noMP = 1;}
915  else { noMP = 0;}
916  n = nvars(basering) - 1;
917  newA = var(n + 1);
918
919  I = std(id);
920
921  // find linear solutions of univariate generators
922
923  linSol = LinearZeroSetMain(I, wt);
924  generators = linSol[3];      // they are a standardbasis
925  linIndex = linSol[2];
926  linearSolution = linSol[1];
927  if(size(linIndex) + sVars == n) {    // all variables solved
928    solid = SubsMapIdeal(linearSolution, linIndex, 0);
929    result[1] = list(solid);
930    result[2] = var(n + 1);
931    result[3] = mpoly;
932    return(result);
933  }
934
935  // find roots of the nonlinear univariate polynomials of generators
936  // if necessary, transform linear solutions w.r.t. newA
937
938  oldMinPoly = mpoly[1];
939  nLinSol =  NonLinearZeroSetMain(generators, wt);    // find solutions of univariate generators
940  nonlinSolutions = nLinSol[1];    // store solutions
941  nlinIndex = nLinSol[4];     // and index of solved variables
942  generators = nLinSol[5];    // new generators
943
944  // change minpoly if necessary and transform the ideal and the partial solutions
945
946  if(oldMinPoly != nLinSol[3]) {
947    newA = nLinSol[2];
948    if(!noMP && size(linearSolution) > 0) {    // transform the algebraic number a
949      Fa = basering, maxideal(1);
950      Fa[n + 1] = newA;
951      linearSolution = SimplifyData(Fa(linearSolution));  // ...
952    }
953  }
954
955  // check if all variables are solved.
956
957  if(size(linIndex) + size(nlinIndex) == n - sVars) {
958    solutions = MergeSolutions(linearSolution, linIndex, nonlinSolutions, nlinIndex, list(), n);
959  }
960
961  else {
962
963  // some variables are not solved.
964  // substitute each partial solution in generators and find the
965  // zero set of the resulting ideal by recursive application
966  // of zeroSetMainWork !
967
968  index = linIndex + nlinIndex;
969  nrSols = 0;
970  for(i = 1; i <=  size(nonlinSolutions); i = i + 1) {
971    sol = linearSolution + nonlinSolutions[i];
972    solid = SubsMapIdeal(sol, index, 1);
973    Fsubs = basering, solid;
974    gens = std(SimplifyData(Fsubs(generators)));    // substitute partial solution
975    oldMinPoly = mpoly[1];
976    partSol = zeroSetMainWork(gens, wt, size(index) + sVars);
977
978    if(oldMinPoly != partSol[3]) {    // minpoly has changed
979      Fa = basering, maxideal(1);
980      Fa[n + 1] = partSol[2];    // a -> p(a), representation of a w.r.t. new minpoly
981      newA = reduce(Fa(newA), mpoly);
982      generators = std(SimplifyData(Fa(generators)));
983      if(size(linearSolution) > 0) { linearSolution = SimplifyData(Fa(linearSolution));}
984      if(size(nonlinSolutions) > 0) {
985        nonlinSolutions = SimplifyZeroset(Fa(nonlinSolutions));
986      }
987      sol = linearSolution + nonlinSolutions[i];
988    }
989
990    for(j = 1; j <= size(partSol[1]); j++) {   // for all partial solutions
991      partsolid = partSol[1][j];
992      for(k = 1; k <= size(index); k++) {
993        partsolid[index[k]] = sol[k];
994       }
995      nrSols++;
996      solutions[nrSols] = partsolid;
997    }
998  }
999
1000  }  // end else
1001  return(list(solutions, newA, mpoly));
1002}
1003
1004///////////////////////////////////////////////////////////////////////////////
1005
1006proc LinearZeroSetMain(ideal I, intvec wt)
1007"USAGE:   LinearZeroSetMain(I, wt)
1008PURPOSE: solve the univariate linear polys in I
1009ASSUME:  basering = Q[x_1,...,x_n,a]
1010RETURN:  list
1011         _[1] = partial solution of I
1012         _[2] = index of solved vars
1013         _[3] = new generators (standardbasis)
1014"
1015{
1016  def altring=basering;
1017  int i, ok, n, found, nrSols;
1018  ideal generators, newGens;
1019  list result, index, totalIndex, vars, sol, temp;
1020  map F;
1021  poly f;
1022
1023  result[1] = index;      // sol[1] should be the empty list
1024  n = nvars(basering) - 1;
1025  generators = I;        // might be wrong, use index !
1026  ok = 1;
1027  nrSols = 0;
1028  while(ok) {
1029    found = 0;
1030    for(i = 1; i <= size(generators); i = i + 1) {
1031      f = generators[i];
1032      vars = Variables(f, n);
1033      if(size(vars) == 1 && deg(f, wt) == 1) {  // univariate,linear
1034        nrSols++; found++;
1035        index[nrSols] = vars[1];
1036        sol[nrSols] = var(vars[1]) - MultPolys(invertNumberMain(LeadTerm(f, vars[1])[3]), f);
1037      }
1038    }
1039    if(found > 0) {
1040      F = basering, SubsMapIdeal(sol, index, 1);
1041      newGens = std(SimplifyData(F(generators)));    // substitute, simplify alg. number
1042      if(size(newGens) == 0) {ok = 0;}
1043      generators = newGens;
1044    }
1045    else {
1046      ok = 0;
1047    }
1048  }
1049  if(nrSols > 0) { result[1] = sol;}
1050  result[2] = index;
1051  result[3] = generators;
1052  return(result);
1053}
1054
1055///////////////////////////////////////////////////////////////////////////////
1056
1057proc NonLinearZeroSetMain(ideal I, intvec wt)
1058"USAGE:   NonLinearZeroSetMain(I, wt);
1059PURPOSE: solves the (nonlinear) univariate polynomials in I
1060         of the ground field (without multiplicities).
1061RETURN:  list, all entries are polynomials
1062         _[1] = list of solutions
1063         _[2] = newA
1064         _[3] = minpoly
1065         _[4] - index of solved variables
1066         _[5] = new representation of I
1067ASSUME:  basering = Q[x_1,x_2,...,x_n,a], ideal 'mpoly' must be defined,
1068         it might be 0 !
1069NOTE:    might change 'mpoly' !!
1070"
1071{
1072  int i, nrSols, ok, n;
1073  ideal generators;
1074  list result, sols, index, vars, partSol;
1075  map F;
1076  poly f, newA;
1077  string ringSTR;
1078
1079  def NLZR = basering;
1080  export(NLZR);
1081
1082  n = nvars(basering) - 1;
1083
1084  generators = I;
1085  newA = var(n + 1);
1086  result[2] = newA;            // default
1087  nrSols = 0;
1088  ok = 1;
1089  i = 1;
1090  while(ok) {
1091
1092    // test if the i-th generator of I is univariate
1093
1094    f = generators[i];
1095    vars = Variables(f, n);
1096    if(size(vars) == 1) {
1097      generators[i] = 0;
1098      generators = simplify(generators, 2);    // remove 0
1099      nrSols++;
1100      index[nrSols] = vars[1];      // store index of solved variable
1101
1102      // create univariate ring
1103
1104      ringSTR = "ring RIS1 = 0, (" + string(var(vars[1])) + ", " + string(var(n+1)) + "), lp;";
1105      execute(ringSTR);
1106      ideal mpoly = std(imap(NLZR, mpoly));
1107      list roots;
1108      poly f = imap(NLZR, f);
1109      export(RIS1);
1110      export(mpoly);
1111      roots = rootsMain(f);
1112
1113      // get "old" basering with new minpoly
1114
1115      setring(NLZR);
1116      partSol = imap(RIS1, roots);
1117      kill RIS1;
1118      if(mpoly[1] != partSol[3]) {      // change minpoly
1119        mpoly = std(partSol[3]);
1120        F = NLZR, maxideal(1);
1121        F[n + 1] = partSol[2];
1122        if(size(sols) > 0) {sols = SimplifyZeroset(F(sols)); }
1123        newA = reduce(F(newA), mpoly);    // normal form
1124        result[2] = newA;
1125        generators = SimplifyData(F(generators));  // does not remove 0's
1126      }
1127      sols = ExtendSolutions(sols, partSol[1]);
1128    } // end univariate
1129    else {
1130      i = i + 1;
1131    }
1132    if(i > size(generators)) { ok = 0;}
1133  }
1134  result[1] = sols;
1135  result[3] = mpoly;
1136  result[4] = index;
1137  result[5] = std(generators);
1138
1139  kill NLZR;
1140  return(result);
1141}
1142
1143///////////////////////////////////////////////////////////////////////////////
1144
1145static proc ExtendSolutions(list solutions, list newSolutions)
1146"USAGE:   ExtendSolutions(sols, newSols); list sols, newSols;
1147PURPOSE: extend the entries of 'sols' by the entries of 'newSols',
1148         each entry of 'newSols' is a number.
1149RETURN:  list
1150ASSUME:  basering = Q[x_1,...,x_n,a], ideal 'mpoly' must be defined,
1151         it might be 0 !
1152NOTE:    used by 'NonLinearZeroSetMain'
1153"
1154{
1155  int i, j, k, n, nrSols;
1156  list newSols, temp;
1157
1158  nrSols = size(solutions);
1159  if(nrSols > 0) {n = size(solutions[1]);}
1160  else {
1161    n = 0;
1162    nrSols = 1;
1163  }
1164  k = 0;
1165  for(i = 1; i <= nrSols; i++) {
1166    for(j = 1; j <= size(newSolutions); j++) {
1167      k++;
1168      if(n == 0) { temp[1] = newSolutions[j];}
1169      else {
1170        temp = solutions[i];
1171        temp[n + 1] = newSolutions[j];
1172      }
1173      newSols[k] = temp;
1174    }
1175  }
1176  return(newSols);
1177}
1178
1179///////////////////////////////////////////////////////////////////////////////
1180
1181static proc MergeSolutions(list sol1, list index1, list sol2, list index2)
1182"USAGE:   MergeSolutions(sol1, index1, sol2, index2); all parameters are lists
1183RETURN:  list
1184PURPOSE: create a list of solutions of size n, each entry of 'sol2' must
1185         have size n. 'sol1' is one partial solution (from 'LinearZeroSetMain')
1186         'sol2' is a list of partial solutions (from 'NonLinearZeroSetMain')
1187ASSUME:  'sol2' is not empty
1188NOTE:    used by 'zeroSetMainWork'
1189{
1190  int i, j, k, m;
1191  ideal sol;
1192  list newSols;
1193
1194  m = 0;
1195  for(i = 1; i <= size(sol2); i++) {
1196    m++;
1197    newSols[m] = SubsMapIdeal(sol1 + sol2[i], index1 + index2, 0);
1198  }
1199  return(newSols);
1200}
1201
1202///////////////////////////////////////////////////////////////////////////////
1203
1204static proc SubsMapIdeal(list sol, list index, int opt)
1205"USAGE:   SubsMapIdeal(sol,index,opt); list sol, index; int opt;
1206PURPOSE: built an ideal I as follows.
1207         if i is contained in 'index' then set I[i] = sol[i]
1208         if i is not contained in 'index' then
1209         - opt = 0: set I[i] = 0
1210         - opt = 1: set I[i] = var(i)
1211         if opt = 1 and n = nvars(basering) then set I[n] = var(n).
1212RETURN:  ideal
1213ASSUME:  size(sol) = size(index) <= nvars(basering)
1214"
1215{
1216  int k = 0;
1217  ideal I;
1218  for(int i = 1; i <= nvars(basering) - 1; i = i + 1) {    // built subs. map
1219    if(containedQ(index, i)) {
1220      k++;
1221      I[index[k]] = sol[k];
1222    }
1223    else {
1224      if(opt) { I[i] = var(i); }
1225      else { I[i] = 0; }
1226    }
1227  }
1228  if(opt) {I[nvars(basering)] = var(nvars(basering));}
1229  return(I);
1230}
1231
1232///////////////////////////////////////////////////////////////////////////////
1233
1234proc SimplifyZeroset(data)
1235"USAGE:   SimplifyZeroset(data); list data
1236PURPOSE: reduce the entries of the elements of 'data' w.r.t. the ideal 'mpoly'
1237         'data' is a list of ideals/lists.
1238RETURN:  list
1239ASSUME:  basering = Q[x_1,...,x_n,a], order = lp
1240         'data' is a list of ideals
1241         ideal 'mpoly' must be defined, it might be 0 !
1242"
1243{
1244  int i;
1245  list result;
1246
1247  for(i = 1; i <= size(data); i++) {
1248    result[i] = SimplifyData(data[i]);
1249  }
1250  return(result);
1251}
1252
1253///////////////////////////////////////////////////////////////////////////////
1254
1255proc Variables(poly f, int n)
1256"USAGE:   Variables(f,n); poly f; int n;
1257PURPOSE: list of variables among var(1),...,var(n) which occur in f.
1258RETURN:  list
1259ASSUME:  n <= nvars(basering)
1260"
1261{
1262  int i, nrV;
1263  list index;
1264
1265  nrV = 0;
1266  for(i = 1; i <= n; i = i + 1) {
1267    if(diff(f, var(i)) != 0) { nrV++; index[nrV] = i; }
1268  }
1269  return(index);
1270}
1271
1272///////////////////////////////////////////////////////////////////////////////
1273
1274proc containedQ(data, f, list #)
1275"USAGE:    containedQ(data, f [, opt]); data=list; f=any type; opt=integer
1276PURPOSE:  test if f is an element of data.
1277RETURN:   int
1278          0 if f not contained in data
1279          1 if f contained in data
1280OPTIONS:  opt = 0 : use '==' for comparing f with elements from data@*
1281          opt = 1 : use @code{sameQ} for comparing f with elements from data
1282"
1283{
1284  int opt, i, found;
1285  if(size(#) > 0) { opt = #[1];}
1286  else { opt = 0; }
1287  i = 1;
1288  found = 0;
1289
1290  while((!found) && (i <= size(data))) {
1291    if(opt == 0) {
1292      if(f == data[i]) { found = 1;}
1293      else {i = i + 1;}
1294    }
1295    else {
1296      if(sameQ(f, data[i])) { found = 1;}
1297      else {i = i + 1;}
1298    }
1299  }
1300  return(found);
1301}
1302
1303//////////////////////////////////////////////////////////////////////////////
1304
1305proc sameQ(a, b)
1306"USAGE:    sameQ(a, b); a,b=list/intvec
1307PURPOSE:  test a == b elementwise, i.e., a[i] = b[i].
1308RETURN:   int
1309          0 if a != b
1310          1 if a == b
1311"
1312{
1313  if(typeof(a) == typeof(b)) {
1314    if(typeof(a) == "list" || typeof(a) == "intvec") {
1315      if(size(a) == size(b)) {
1316        int i = 1;
1317        int ok = 1;
1318        while(ok && (i <= size(a))) {
1319          if(a[i] == b[i]) { i = i + 1;}
1320          else {ok = 0;}
1321        }
1322        return(ok);
1323      }
1324      else { return(0); }
1325    }
1326    else { return(a == b);}
1327  }
1328  else { return(0);}
1329}
1330
1331///////////////////////////////////////////////////////////////////////////////
1332
1333static proc SimplifyPoly(poly f)
1334"USAGE:   SimplifyPoly(f); poly f
1335PURPOSE: reduces the coefficients of f w.r.t. the ideal 'moly' if they contain
1336         the algebraic number 'a'.
1337RETURN:  poly
1338ASSUME:  basering = Q[x_1,...,x_n,a]
1339         ideal mpoly must be defined, it might be 0 !
1340NOTE: outdated, use reduce instead
1341"
1342{
1343  matrix coMx;
1344  poly f1, vp;
1345
1346  vp = 1;
1347  for(int i = 1; i < nvars(basering); i++) { vp = vp * var(i);}
1348
1349  coMx = coef(f, vp);
1350  f1 = 0;
1351  for(i = 1; i <= ncols(coMx); i++) {
1352    f1 = f1 + coMx[1, i] * reduce(coMx[2, i], mpoly);
1353  }
1354  return(f1);
1355}
1356
1357///////////////////////////////////////////////////////////////////////////////
1358
1359static proc SimplifyData(data)
1360"USAGE:   SimplifyData(data); ideal/list data;
1361PURPOSE: reduces the entries of 'data' w.r.t. the ideal 'mpoly' if they contain
1362         the algebraic number 'a'
1363RETURN:  ideal/list
1364ASSUME:  basering = Q[x_1,...,x_n,a]
1365         ideal 'mpoly' must be defined, it might be 0 !
1366"
1367{
1368  def altring=basering;
1369  int n;
1370  poly f;
1371
1372  if(typeof(data) == "ideal") { n = ncols(data); }
1373  else { n = size(data);}
1374
1375  for(int i = 1; i <= n; i++) {
1376    f = data[i];
1377    data[i] = SimplifyPoly(f);
1378  }
1379  return(data);
1380}
1381
1382///////////////////////////////////////////////////////////////////////////////
1383
1384static proc TransferRing(R)
1385"USAGE:   TransferRing(R);
1386PURPOSE: creates a new ring containing the same variables as R, but without
1387         parameters. If R contains a parameter then this parameter is added
1388         as the last variable and 'minpoly' is represented by the ideal 'mpoly'
1389         If the basering does not contain a parameter then 'a' is added and
1390         'mpoly' = 0.
1391RETURN:  ring
1392ASSUME:  R = K[x_1,...,x_n] where K = Q or K = Q(a).
1393NOTE:    Creates the ring needed for all prodecures with name 'proc-name'Main
1394"
1395{
1396  def altring=basering;
1397  string ringSTR, parName, minPoly;
1398
1399  setring(R);
1400
1401  if(npars(basering) == 0) {
1402    parName = "a";
1403    minPoly = "0";
1404  }
1405  else {
1406    parName = parstr(basering);
1407    minPoly = string(minpoly);
1408  }
1409  ringSTR = "ring TR = 0, (" + varstr(basering) + "," + parName + "), lp;";
1410
1411  execute(ringSTR);
1412  execute("ideal mpoly = std(" + minPoly + ");");
1413  export(mpoly);
1414  setring altring;
1415  return(TR);
1416}
1417
1418///////////////////////////////////////////////////////////////////////////////
1419
1420static proc NewBaseRing()
1421"USAGE:   NewBaseRing();
1422PURPOSE: creates a new ring, the last variable is added as a parameter.
1423         minpoly is set to mpoly[1].
1424RETURN:  ring
1425ASSUME:  basering = Q[x_1,...,x_n, a], 'mpoly' must be defined
1426"
1427{
1428  int n = nvars(basering);
1429  int MP;
1430  string ringSTR, parName, varString;
1431
1432  def BR = basering;
1433  if(mpoly[1] != 0) {
1434    parName = "(0, " + string(var(n)) + ")";
1435    MP = 1;
1436  }
1437  else {
1438    parName = "0";
1439    MP = 0;
1440  }
1441
1442
1443  for(int i = 1; i < n - 1; i++) {
1444    varString = varString + string(var(i)) + ",";
1445  }
1446  varString = varString + string(var(n-1));
1447
1448  ringSTR = "ring TR = " + parName + ", (" + varString + "), lp;";
1449  execute(ringSTR);
1450  if(MP) { minpoly = number(imap(BR, mpoly)[1]); }
1451  setring BR;
1452  return(TR);
1453}
1454
1455///////////////////////////////////////////////////////////////////////////////
1456
1457/*
1458                           Examples:
1459
1460
1461// order = 20;
1462ring S1 = 0, (s(1..3)), lp;
1463ideal I = s(2)*s(3), s(1)^2*s(2)+s(1)^2*s(3)-1, s(1)^2*s(3)^2-s(3), s(2)^4-s(3)^4+s(1)^2, s(1)^4+s(2)^3-s(3)^3, s(3)^5-s(1)^2*s(3);
1464ideal mpoly = std(0);
1465
1466// order = 10
1467ring S2 = 0, (s(1..5)), lp;
1468ideal I = s(2)+s(3)-s(5), s(4)^2-s(5), s(1)*s(5)+s(3)*s(4)-s(4)*s(5), s(1)*s(4)+s(3)-s(5), s(3)^2-2*s(3)*s(5), s(1)*s(3)-s(1)*s(5)+s(4)*s(5), s(1)^2+s(4)^2-2*s(5), -s(1)+s(5)^3, s(3)*s(5)^2+s(4)-s(5)^3, s(1)*s(5)^2-1;
1469ideal mpoly = std(0);
1470
1471//order = 126
1472ring S3 =  0, (s(1..5)), lp;
1473ideal I = s(3)*s(4), s(2)*s(4), s(1)*s(3), s(1)*s(2), s(3)^3+s(4)^3-1, s(2)^3+s(4)^3-1, s(1)^3-s(4)^3, s(4)^4-s(4), s(1)*s(4)^3-s(1), s(5)^7-1;
1474ideal mpoly = std(0);
1475
1476// order = 192
1477ring S4 = 0, (s(1..4)), lp;
1478ideal I = s(2)*s(3)^2*s(4)+s(1)*s(3)*s(4)^2, s(2)^2*s(3)*s(4)+s(1)*s(2)*s(4)^2, s(1)*s(3)^3+s(2)*s(4)^3, s(1)*s(2)*s(3)^2+s(1)^2*s(3)*s(4), s(1)^2*s(3)^2-s(2)^2*s(4)^2, s(1)*s(2)^2*s(3)+s(1)^2*s(2)*s(4), s(1)^3*s(3)+s(2)^3*s(4), s(2)^4-s(3)^4, s(1)*s(2)^3+s(3)*s(4)^3, s(1)^2*s(2)^2-s(3)^2*s(4)^2, s(1)^3*s(2)+s(3)^3*s(4), s(1)^4-s(4)^4, s(3)^5*s(4)-s(3)*s(4)^5, s(3)^8+14*s(3)^4*s(4)^4+s(4)^8-1, 15*s(2)*s(3)*s(4)^7-s(1)*s(4)^8+s(1), 15*s(3)^4*s(4)^5+s(4)^9-s(4), 16*s(3)*s(4)^9-s(3)*s(4), 16*s(2)*s(4)^9-s(2)*s(4), 16*s(1)*s(3)*s(4)^8-s(1)*s(3), 16*s(1)*s(2)*s(4)^8-s(1)*s(2), 16*s(1)*s(4)^10-15*s(2)*s(3)*s(4)-16*s(1)*s(4)^2, 16*s(1)^2*s(4)^9-15*s(1)*s(2)*s(3)-16*s(1)^2*s(4), 16*s(4)^13+15*s(3)^4*s(4)-16*s(4)^5;
1479ideal mpoly = std(0);
1480
1481ring R = (0,a), (x,y,z), lp;
1482minpoly = a2 + 1;
1483ideal I1 = x2 - 1/2, a*z - 1, y - 2;
1484ideal I2 = x3 - 1/2, a*z2 - 3, y - 2*a;
1485
1486*/
Note: See TracBrowser for help on using the repository browser.