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

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