source: git/Singular/LIB/zeroset.lib @ 7de8e4

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