source: git/libpolys/polys/ext_fields/algext.cc @ 892dd8

spielwiese
Last change on this file since 892dd8 was 6909cfb, checked in by Yue Ren <ren@…>, 11 years ago
fix: -Wunused-variable warnings
  • Property mode set to 100644
File size: 38.9 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/**
5  * ABSTRACT: numbers in an algebraic extension field K[a] / < f(a) >
6  *           Assuming that we have a coeffs object cf, then these numbers
7  *           are polynomials in the polynomial ring K[a] represented by
8  *           cf->extRing.
9  *           IMPORTANT ASSUMPTIONS:
10  *           1.) So far we assume that cf->extRing is a valid polynomial
11  *               ring in exactly one variable, i.e., K[a], where K is allowed
12  *               to be any field (representable in SINGULAR and which may
13  *               itself be some extension field, thus allowing for extension
14  *               towers).
15  *           2.) Moreover, this implementation assumes that
16  *               cf->extRing->qideal is not NULL but an ideal with at
17  *               least one non-zero generator which may be accessed by
18  *               cf->extRing->qideal->m[0] and which represents the minimal
19  *               polynomial f(a) of the extension variable 'a' in K[a].
20  *           3.) As soon as an std method for polynomial rings becomes
21  *               availabe, all reduction steps modulo f(a) should be replaced
22  *               by a call to std. Moreover, in this situation one can finally
23  *               move from K[a] / < f(a) > to
24  *                  K[a_1, ..., a_s] / I, with I some zero-dimensional ideal
25  *                                        in K[a_1, ..., a_s] given by a lex
26  *                                        Gröbner basis.
27  *               The code in algext.h and algext.cc is then capable of
28  *               computing in K[a_1, ..., a_s] / I.
29  **/
30
31#include "config.h"
32#include <misc/auxiliary.h>
33
34#include <omalloc/omalloc.h>
35
36#include <reporter/reporter.h>
37
38#include <coeffs/coeffs.h>
39#include <coeffs/numbers.h>
40#include <coeffs/longrat.h>
41
42#include <polys/monomials/ring.h>
43#include <polys/monomials/p_polys.h>
44#include <polys/simpleideals.h>
45
46#include <polys/PolyEnumerator.h>
47
48#ifdef HAVE_FACTORY
49#include <factory/factory.h>
50#include <polys/clapconv.h>
51#include <polys/clapsing.h>
52#endif
53
54
55#include <polys/ext_fields/algext.h>
56#define TRANSEXT_PRIVATES 1
57#include <polys/ext_fields/transext.h>
58
59#ifdef LDEBUG
60#define naTest(a) naDBTest(a,__FILE__,__LINE__,cf)
61BOOLEAN  naDBTest(number a, const char *f, const int l, const coeffs r);
62#else
63#define naTest(a) do {} while (0)
64#endif
65
66/// Our own type!
67static const n_coeffType ID = n_algExt;
68
69/* polynomial ring in which our numbers live */
70#define naRing cf->extRing
71
72/* coeffs object in which the coefficients of our numbers live;
73 * methods attached to naCoeffs may be used to compute with the
74 * coefficients of our numbers, e.g., use naCoeffs->nAdd to add
75 * coefficients of our numbers */
76#define naCoeffs cf->extRing->cf
77
78/* minimal polynomial */
79#define naMinpoly naRing->qideal->m[0]
80
81/// forward declarations
82BOOLEAN  naGreaterZero(number a, const coeffs cf);
83BOOLEAN  naGreater(number a, number b, const coeffs cf);
84BOOLEAN  naEqual(number a, number b, const coeffs cf);
85BOOLEAN  naIsOne(number a, const coeffs cf);
86BOOLEAN  naIsMOne(number a, const coeffs cf);
87BOOLEAN  naIsZero(number a, const coeffs cf);
88number   naInit(long i, const coeffs cf);
89int      naInt(number &a, const coeffs cf);
90number   naNeg(number a, const coeffs cf);
91number   naInvers(number a, const coeffs cf);
92number   naAdd(number a, number b, const coeffs cf);
93number   naSub(number a, number b, const coeffs cf);
94number   naMult(number a, number b, const coeffs cf);
95number   naDiv(number a, number b, const coeffs cf);
96void     naPower(number a, int exp, number *b, const coeffs cf);
97number   naCopy(number a, const coeffs cf);
98void     naWriteLong(number &a, const coeffs cf);
99void     naWriteShort(number &a, const coeffs cf);
100number   naRePart(number a, const coeffs cf);
101number   naImPart(number a, const coeffs cf);
102number   naGetDenom(number &a, const coeffs cf);
103number   naGetNumerator(number &a, const coeffs cf);
104number   naGcd(number a, number b, const coeffs cf);
105//number   naLcm(number a, number b, const coeffs cf);
106int      naSize(number a, const coeffs cf);
107void     naDelete(number *a, const coeffs cf);
108void     naCoeffWrite(const coeffs cf, BOOLEAN details);
109//number   naIntDiv(number a, number b, const coeffs cf);
110const char * naRead(const char *s, number *a, const coeffs cf);
111
112static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param);
113
114
115/// returns NULL if p == NULL, otherwise makes p monic by dividing
116///   by its leading coefficient (only done if this is not already 1);
117///   this assumes that we are over a ground field so that division
118///   is well-defined;
119///   modifies p
120// void      p_Monic(poly p, const ring r);
121
122///   assumes that p and q are univariate polynomials in r,
123///   mentioning the same variable;
124///   assumes a global monomial ordering in r;
125///   assumes that not both p and q are NULL;
126///   returns the gcd of p and q;
127///   leaves p and q unmodified
128// poly      p_Gcd(const poly p, const poly q, const ring r);
129
130/* returns NULL if p == NULL, otherwise makes p monic by dividing
131   by its leading coefficient (only done if this is not already 1);
132   this assumes that we are over a ground field so that division
133   is well-defined;
134   modifies p */
135static inline void p_Monic(poly p, const ring r)
136{
137  if (p == NULL) return;
138  number n = n_Init(1, r->cf);
139  if (p->next==NULL) { p_SetCoeff(p,n,r); return; }
140  poly pp = p;
141  number lc = p_GetCoeff(p, r);
142  if (n_IsOne(lc, r->cf)) return;
143  number lcInverse = n_Invers(lc, r->cf);
144  p_SetCoeff(p, n, r);   // destroys old leading coefficient!
145  pIter(p);
146  while (p != NULL)
147  {
148    number n = n_Mult(p_GetCoeff(p, r), lcInverse, r->cf);
149    n_Normalize(n,r->cf);
150    p_SetCoeff(p, n, r);   // destroys old leading coefficient!
151    pIter(p);
152  }
153  n_Delete(&lcInverse, r->cf);
154  p = pp;
155}
156
157/// see p_Gcd;
158///   additional assumption: deg(p) >= deg(q);
159///   must destroy p and q (unless one of them is returned)
160static inline poly p_GcdHelper(poly &p, poly &q, const ring r)
161{
162  while (q != NULL)
163  {
164    p_PolyDiv(p, q, FALSE, r);
165    // swap p and q:
166    poly& t = q;
167    q = p;
168    p = t;
169
170  }
171  return p;
172}
173
174/* assumes that p and q are univariate polynomials in r,
175   mentioning the same variable;
176   assumes a global monomial ordering in r;
177   assumes that not both p and q are NULL;
178   returns the gcd of p and q;
179   leaves p and q unmodified */
180static inline poly      p_Gcd(const poly p, const poly q, const ring r)
181{
182  assume((p != NULL) || (q != NULL));
183
184  poly a = p; poly b = q;
185  if (p_Deg(a, r) < p_Deg(b, r)) { a = q; b = p; }
186  a = p_Copy(a, r); b = p_Copy(b, r);
187
188  /* We have to make p monic before we return it, so that if the
189     gcd is a unit in the ground field, we will actually return 1. */
190  a = p_GcdHelper(a, b, r);
191  p_Monic(a, r);
192  return a;
193}
194
195/* see p_ExtGcd;
196   additional assumption: deg(p) >= deg(q);
197   must destroy p and q (unless one of them is returned) */
198static inline poly p_ExtGcdHelper(poly &p, poly &pFactor, poly &q, poly &qFactor,
199                                  ring r)
200{
201  if (q == NULL)
202  {
203    qFactor = NULL;
204    pFactor = p_ISet(1, r);
205    p_SetCoeff(pFactor, n_Invers(p_GetCoeff(p, r), r->cf), r);
206    p_Monic(p, r);
207    return p;
208  }
209  else
210  {
211    poly pDivQ = p_PolyDiv(p, q, TRUE, r);
212    poly ppFactor = NULL; poly qqFactor = NULL;
213    poly theGcd = p_ExtGcdHelper(q, qqFactor, p, ppFactor, r);
214    pFactor = ppFactor;
215    qFactor = p_Add_q(qqFactor,
216                      p_Neg(p_Mult_q(pDivQ, p_Copy(ppFactor, r), r), r),
217                      r);
218    return theGcd;
219  }
220}
221
222/* assumes that p and q are univariate polynomials in r,
223   mentioning the same variable;
224   assumes a global monomial ordering in r;
225   assumes that not both p and q are NULL;
226   returns the gcd of p and q;
227   moreover, afterwards pFactor and qFactor contain appropriate
228   factors such that gcd(p, q) = p * pFactor + q * qFactor;
229   leaves p and q unmodified */
230poly p_ExtGcd(poly p, poly &pFactor, poly q, poly &qFactor, ring r)
231{
232  assume((p != NULL) || (q != NULL));
233  poly a = p; poly b = q; BOOLEAN aCorrespondsToP = TRUE;
234  if (p_Deg(a, r) < p_Deg(b, r))
235    { a = q; b = p; aCorrespondsToP = FALSE; }
236  a = p_Copy(a, r); b = p_Copy(b, r);
237  poly aFactor = NULL; poly bFactor = NULL;
238  poly theGcd = p_ExtGcdHelper(a, aFactor, b, bFactor, r);
239  if (aCorrespondsToP) { pFactor = aFactor; qFactor = bFactor; }
240  else                 { pFactor = bFactor; qFactor = aFactor; }
241  return theGcd;
242}
243
244
245
246#ifdef LDEBUG
247BOOLEAN naDBTest(number a, const char *f, const int l, const coeffs cf)
248{
249  assume(getCoeffType(cf) == ID);
250  if (a == NULL) return TRUE;
251  p_Test((poly)a, naRing);
252  if((((poly)a)!=naMinpoly)
253  && p_Totaldegree((poly)a, naRing) >= p_Totaldegree(naMinpoly, naRing))
254  {
255    Print("deg >= deg(minpoly) in %s:%d\n",f,l);
256    return FALSE;
257  }
258  return TRUE;
259}
260#endif
261
262void heuristicReduce(poly &p, poly reducer, const coeffs cf);
263void definiteReduce(poly &p, poly reducer, const coeffs cf);
264
265/* returns the bottom field in this field extension tower; if the tower
266   is flat, i.e., if there is no extension, then r itself is returned;
267   as a side-effect, the counter 'height' is filled with the height of
268   the extension tower (in case the tower is flat, 'height' is zero) */
269static coeffs nCoeff_bottom(const coeffs r, int &height)
270{
271  assume(r != NULL);
272  coeffs cf = r;
273  height = 0;
274  while (nCoeff_is_Extension(cf))
275  {
276    assume(cf->extRing != NULL); assume(cf->extRing->cf != NULL);
277    cf = cf->extRing->cf;
278    height++;
279  }
280  return cf;
281}
282
283BOOLEAN naIsZero(number a, const coeffs cf)
284{
285  naTest(a);
286  return (a == NULL);
287}
288
289void naDelete(number * a, const coeffs cf)
290{
291  if (*a == NULL) return;
292  if (((poly)*a)==naMinpoly) { *a=NULL;return;}
293  poly aAsPoly = (poly)(*a);
294  p_Delete(&aAsPoly, naRing);
295  *a = NULL;
296}
297
298BOOLEAN naEqual(number a, number b, const coeffs cf)
299{
300  naTest(a); naTest(b);
301  /// simple tests
302  if (a == NULL) return (b == NULL);
303  if (b == NULL) return (a == NULL);
304  return p_EqualPolys((poly)a,(poly)b,naRing);
305}
306
307number naCopy(number a, const coeffs cf)
308{
309  naTest(a);
310  if (a == NULL) return NULL;
311  if (((poly)a)==naMinpoly) return a;
312  return (number)p_Copy((poly)a, naRing);
313}
314
315number naGetNumerator(number &a, const coeffs cf)
316{
317  return naCopy(a, cf);
318}
319
320number naGetDenom(number &a, const coeffs cf)
321{
322  naTest(a);
323  return naInit(1, cf);
324}
325
326BOOLEAN naIsOne(number a, const coeffs cf)
327{
328  naTest(a);
329  poly aAsPoly = (poly)a;
330  if ((a==NULL) || (!p_IsConstant(aAsPoly, naRing))) return FALSE;
331  return n_IsOne(p_GetCoeff(aAsPoly, naRing), naCoeffs);
332}
333
334BOOLEAN naIsMOne(number a, const coeffs cf)
335{
336  naTest(a);
337  poly aAsPoly = (poly)a;
338  if ((a==NULL) || (!p_IsConstant(aAsPoly, naRing))) return FALSE;
339  return n_IsMOne(p_GetCoeff(aAsPoly, naRing), naCoeffs);
340}
341
342/// this is in-place, modifies a
343number naNeg(number a, const coeffs cf)
344{
345  naTest(a);
346  if (a != NULL) a = (number)p_Neg((poly)a, naRing);
347  return a;
348}
349
350number naImPart(number a, const coeffs cf)
351{
352  naTest(a);
353  return NULL;
354}
355
356number naInit_bigint(number longratBigIntNumber, const coeffs src, const coeffs cf)
357{
358  assume( cf != NULL );
359
360  const ring A = cf->extRing;
361
362  assume( A != NULL );
363
364  const coeffs C = A->cf;
365
366  assume( C != NULL );
367
368  number n = n_Init_bigint(longratBigIntNumber, src, C);
369
370  if ( n_IsZero(n, C) )
371  {
372    n_Delete(&n, C);
373    return NULL;
374  }
375
376  return (number)p_NSet(n, A);
377}
378
379
380
381number naInit(long i, const coeffs cf)
382{
383  if (i == 0) return NULL;
384  else        return (number)p_ISet(i, naRing);
385}
386
387int naInt(number &a, const coeffs cf)
388{
389  naTest(a);
390  poly aAsPoly = (poly)a;
391  if(aAsPoly == NULL)
392    return 0;
393  if (!p_IsConstant(aAsPoly, naRing))
394    return 0;
395  assume( aAsPoly != NULL );
396  return n_Int(p_GetCoeff(aAsPoly, naRing), naCoeffs);
397}
398
399/* TRUE iff (a != 0 and (b == 0 or deg(a) > deg(b) or (deg(a)==deg(b) && lc(a)>lc(b))) */
400BOOLEAN naGreater(number a, number b, const coeffs cf)
401{
402  naTest(a); naTest(b);
403  if (naIsZero(a, cf))
404  {
405    if (naIsZero(b, cf)) return FALSE;
406    return !n_GreaterZero(pGetCoeff((poly)b),cf);
407  }
408  if (naIsZero(b, cf))
409  {
410    return n_GreaterZero(pGetCoeff((poly)a),cf);
411  }
412  int aDeg = p_Totaldegree((poly)a, naRing);
413  int bDeg = p_Totaldegree((poly)b, naRing);
414  if (aDeg>bDeg) return TRUE;
415  if (aDeg<bDeg) return FALSE;
416  return n_Greater(pGetCoeff((poly)a),pGetCoeff((poly)b),naCoeffs);
417}
418
419/* TRUE iff a != 0 and (LC(a) > 0 or deg(a) > 0) */
420BOOLEAN naGreaterZero(number a, const coeffs cf)
421{
422  naTest(a);
423  if (a == NULL)                                            return FALSE;
424  if (n_GreaterZero(p_GetCoeff((poly)a, naRing), naCoeffs)) return TRUE;
425  if (p_Totaldegree((poly)a, naRing) > 0)                   return TRUE;
426  return FALSE;
427}
428
429void naCoeffWrite(const coeffs cf, BOOLEAN details)
430{
431  assume( cf != NULL );
432
433  const ring A = cf->extRing;
434
435  assume( A != NULL );
436  assume( A->cf != NULL );
437
438  n_CoeffWrite(A->cf, details);
439
440//  rWrite(A);
441
442  const int P = rVar(A);
443  assume( P > 0 );
444
445  Print("//   %d parameter    : ", P);
446
447  for (int nop=0; nop < P; nop ++)
448    Print("%s ", rRingVar(nop, A));
449
450  PrintLn();
451
452  const ideal I = A->qideal;
453
454  assume( I != NULL );
455  assume( IDELEMS(I) == 1 );
456
457
458  if ( details )
459  {
460    PrintS("//   minpoly        : (");
461    p_Write0( I->m[0], A);
462    PrintS(")");
463  }
464  else
465    PrintS("//   minpoly        : ...");
466
467  PrintLn();
468
469/*
470  char *x = rRingVar(0, A);
471
472  Print("//   Coefficients live in the extension field K[%s]/<f(%s)>\n", x, x);
473  Print("//   with the minimal polynomial f(%s) = %s\n", x,
474        p_String(A->qideal->m[0], A));
475  PrintS("//   and K: ");
476*/
477}
478
479number naAdd(number a, number b, const coeffs cf)
480{
481  naTest(a); naTest(b);
482  if (a == NULL) return naCopy(b, cf);
483  if (b == NULL) return naCopy(a, cf);
484  poly aPlusB = p_Add_q(p_Copy((poly)a, naRing),
485                        p_Copy((poly)b, naRing), naRing);
486  definiteReduce(aPlusB, naMinpoly, cf);
487  return (number)aPlusB;
488}
489
490number naSub(number a, number b, const coeffs cf)
491{
492  naTest(a); naTest(b);
493  if (b == NULL) return naCopy(a, cf);
494  poly minusB = p_Neg(p_Copy((poly)b, naRing), naRing);
495  if (a == NULL) return (number)minusB;
496  poly aMinusB = p_Add_q(p_Copy((poly)a, naRing), minusB, naRing);
497  definiteReduce(aMinusB, naMinpoly, cf);
498  return (number)aMinusB;
499}
500
501number naMult(number a, number b, const coeffs cf)
502{
503  naTest(a); naTest(b);
504  if ((a == NULL)||(b == NULL)) return NULL;
505  poly aTimesB = p_Mult_q(p_Copy((poly)a, naRing),
506                          p_Copy((poly)b, naRing), naRing);
507  p_Normalize(aTimesB,naRing);
508  definiteReduce(aTimesB, naMinpoly, cf);
509  return (number)aTimesB;
510}
511
512number naDiv(number a, number b, const coeffs cf)
513{
514  naTest(a); naTest(b);
515  if (b == NULL) WerrorS(nDivBy0);
516  if (a == NULL) return NULL;
517  poly bInverse = (poly)naInvers(b, cf);
518  if(bInverse != NULL) // b is non-zero divisor!
519  {
520    poly aDivB = p_Mult_q(p_Copy((poly)a, naRing), bInverse, naRing);
521    definiteReduce(aDivB, naMinpoly, cf);
522    return (number)aDivB;
523  }
524  return NULL;
525}
526
527/* 0^0 = 0;
528   for |exp| <= 7 compute power by a simple multiplication loop;
529   for |exp| >= 8 compute power along binary presentation of |exp|, e.g.
530      p^13 = p^1 * p^4 * p^8, where we utilise that
531      p^(2^(k+1)) = p^(2^k) * p^(2^k);
532   intermediate reduction modulo the minimal polynomial is controlled by
533   the in-place method heuristicReduce(poly, poly, coeffs); see there.
534*/
535void naPower(number a, int exp, number *b, const coeffs cf)
536{
537  naTest(a);
538
539  /* special cases first */
540  if (a == NULL)
541  {
542    if (exp >= 0) *b = NULL;
543    else          WerrorS(nDivBy0);
544    return;
545  }
546  else if (exp ==  0) { *b = naInit(1, cf); return; }
547  else if (exp ==  1) { *b = naCopy(a, cf); return; }
548  else if (exp == -1) { *b = naInvers(a, cf); return; }
549
550  int expAbs = exp; if (expAbs < 0) expAbs = -expAbs;
551
552  /* now compute a^expAbs */
553  poly pow; poly aAsPoly = (poly)a;
554  if (expAbs <= 7)
555  {
556    pow = p_Copy(aAsPoly, naRing);
557    for (int i = 2; i <= expAbs; i++)
558    {
559      pow = p_Mult_q(pow, p_Copy(aAsPoly, naRing), naRing);
560      heuristicReduce(pow, naMinpoly, cf);
561    }
562    definiteReduce(pow, naMinpoly, cf);
563  }
564  else
565  {
566    pow = p_ISet(1, naRing);
567    poly factor = p_Copy(aAsPoly, naRing);
568    while (expAbs != 0)
569    {
570      if (expAbs & 1)
571      {
572        pow = p_Mult_q(pow, p_Copy(factor, naRing), naRing);
573        heuristicReduce(pow, naMinpoly, cf);
574      }
575      expAbs = expAbs / 2;
576      if (expAbs != 0)
577      {
578        factor = p_Mult_q(factor, p_Copy(factor, naRing), naRing);
579        heuristicReduce(factor, naMinpoly, cf);
580      }
581    }
582    p_Delete(&factor, naRing);
583    definiteReduce(pow, naMinpoly, cf);
584  }
585
586  /* invert if original exponent was negative */
587  number n = (number)pow;
588  if (exp < 0)
589  {
590    number m = naInvers(n, cf);
591    naDelete(&n, cf);
592    n = m;
593  }
594  *b = n;
595}
596
597/* may reduce p modulo the reducer by calling definiteReduce;
598   the decision is made based on the following heuristic
599   (which should also only be changed here in this method):
600      if (deg(p) > 10*deg(reducer) then perform reduction;
601   modifies p */
602void heuristicReduce(poly &p, poly reducer, const coeffs cf)
603{
604  #ifdef LDEBUG
605  p_Test((poly)p, naRing);
606  p_Test((poly)reducer, naRing);
607  #endif
608  if (p_Totaldegree(p, naRing) > 10 * p_Totaldegree(reducer, naRing))
609    definiteReduce(p, reducer, cf);
610}
611
612void naWriteLong(number &a, const coeffs cf)
613{
614  naTest(a);
615  if (a == NULL)
616    StringAppendS("0");
617  else
618  {
619    poly aAsPoly = (poly)a;
620    /* basically, just write aAsPoly using p_Write,
621       but use brackets around the output, if a is not
622       a constant living in naCoeffs = cf->extRing->cf */
623    BOOLEAN useBrackets = !(p_IsConstant(aAsPoly, naRing));
624    if (useBrackets) StringAppendS("(");
625    p_String0Long(aAsPoly, naRing, naRing);
626    if (useBrackets) StringAppendS(")");
627  }
628}
629
630void naWriteShort(number &a, const coeffs cf)
631{
632  naTest(a);
633  if (a == NULL)
634    StringAppendS("0");
635  else
636  {
637    poly aAsPoly = (poly)a;
638    /* basically, just write aAsPoly using p_Write,
639       but use brackets around the output, if a is not
640       a constant living in naCoeffs = cf->extRing->cf */
641    BOOLEAN useBrackets = !(p_IsConstant(aAsPoly, naRing));
642    if (useBrackets) StringAppendS("(");
643    p_String0Short(aAsPoly, naRing, naRing);
644    if (useBrackets) StringAppendS(")");
645  }
646}
647
648const char * naRead(const char *s, number *a, const coeffs cf)
649{
650  poly aAsPoly;
651  const char * result = p_Read(s, aAsPoly, naRing);
652  definiteReduce(aAsPoly, naMinpoly, cf);
653  *a = (number)aAsPoly;
654  return result;
655}
656
657#if 0
658/* implemented by the rule lcm(a, b) = a * b / gcd(a, b) */
659number naLcm(number a, number b, const coeffs cf)
660{
661  naTest(a); naTest(b);
662  if (a == NULL) return NULL;
663  if (b == NULL) return NULL;
664  number theProduct = (number)p_Mult_q(p_Copy((poly)a, naRing),
665                                       p_Copy((poly)b, naRing), naRing);
666  /* note that theProduct needs not be reduced w.r.t. naMinpoly;
667     but the final division will take care of the necessary reduction */
668  number theGcd = naGcd(a, b, cf);
669  return naDiv(theProduct, theGcd, cf);
670}
671#endif
672number napLcm(number b, const coeffs cf)
673{
674  number h=n_Init(1,naRing->cf);
675  poly bb=(poly)b;
676  number d;
677  while(bb!=NULL)
678  {
679    d=n_Lcm(h,pGetCoeff(bb), naRing->cf);
680    n_Delete(&h,naRing->cf);
681    h=d;
682    pIter(bb);
683  }
684}
685number naLcmContent(number a, number b, const coeffs cf)
686{
687  if (nCoeff_is_Zp(naRing->cf)) return naCopy(a,cf);
688  else return ndGcd(a,b,cf);
689  #if 0
690  {
691    a=(number)p_Copy((poly)a,naRing);
692    number t=napLcm(b,cf);
693    if(!naIsOne(t,cf))
694    {
695      number bt, rr;
696      poly xx=(poly)a;
697      while (xx!=NULL)
698      {
699        bt = n_Gcd(t, pGetCoeff(xx), naRing->cf);
700        rr = n_Mult(t, pGetCoeff(xx), naRing->cf);
701        n_Delete(&pGetCoeff(xx),naRing->cf);
702        pGetCoeff(xx) = n_Div(rr, bt, naRing->cf);
703        n_Normalize(pGetCoeff(xx),naRing->cf);
704        n_Delete(&bt,naRing->cf);
705        n_Delete(&rr,naRing->cf);
706        pIter(xx);
707      }
708    }
709    n_Delete(&t,naRing->cf);
710    return (number) a;
711  }
712  #endif
713}
714
715/* expects *param to be castable to AlgExtInfo */
716static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param)
717{
718  if (ID != n) return FALSE;
719  AlgExtInfo *e = (AlgExtInfo *)param;
720  /* for extension coefficient fields we expect the underlying
721     polynomial rings to be IDENTICAL, i.e. the SAME OBJECT;
722     this expectation is based on the assumption that we have properly
723     registered cf and perform reference counting rather than creating
724     multiple copies of the same coefficient field/domain/ring */
725  if (naRing == e->r)
726    return TRUE;
727  /* (Note that then also the minimal ideals will necessarily be
728     the same, as they are attached to the ring.) */
729
730  // NOTE: Q(a)[x] && Q(a)[y] should better share the _same_ Q(a)...
731  if( rEqual(naRing, e->r, TRUE) ) // also checks the equality of qideals
732  {
733    const ideal mi = naRing->qideal;
734    assume( IDELEMS(mi) == 1 );
735    const ideal ii = e->r->qideal;
736    assume( IDELEMS(ii) == 1 );
737
738    // TODO: the following should be extended for 2 *equal* rings...
739    assume( p_EqualPolys(mi->m[0], ii->m[0], naRing, e->r) );
740
741    rDelete(e->r);
742
743    return TRUE;
744  }
745
746  return FALSE;
747
748}
749
750int naSize(number a, const coeffs cf)
751{
752  if (a == NULL) return -1;
753  /* this has been taken from the old implementation of field extensions,
754     where we computed the sum of the degree and the number of terms in
755     (poly)a; so we leave it at that, for the time being;
756     maybe, the number of terms alone is a better measure? */
757  poly aAsPoly = (poly)a;
758  int theDegree = 0; int noOfTerms = 0;
759  while (aAsPoly != NULL)
760  {
761    noOfTerms++;
762    int d = p_GetExp(aAsPoly, 1, naRing);
763    if (d > theDegree) theDegree = d;
764    pIter(aAsPoly);
765  }
766  return theDegree + noOfTerms;
767}
768
769/* performs polynomial division and overrides p by the remainder
770   of division of p by the reducer;
771   modifies p */
772void definiteReduce(poly &p, poly reducer, const coeffs cf)
773{
774  #ifdef LDEBUG
775  p_Test((poly)p, naRing);
776  p_Test((poly)reducer, naRing);
777  #endif
778  if ((p!=NULL) && (p_GetExp(p,1,naRing)>=p_GetExp(reducer,1,naRing)))
779  {
780    p_PolyDiv(p, reducer, FALSE, naRing);
781  }
782}
783
784void  naNormalize(number &a, const coeffs cf)
785{
786  poly aa=(poly)a;
787  if (aa!=naMinpoly)
788    definiteReduce(aa,naMinpoly,cf);
789  a=(number)aa;
790}
791
792#ifdef HAVE_FACTORY
793number naConvFactoryNSingN( const CanonicalForm n, const coeffs cf)
794{
795  if (n.isZero()) return NULL;
796  poly p=convFactoryPSingP(n,naRing);
797  return (number)p;
798}
799CanonicalForm naConvSingNFactoryN( number n, BOOLEAN /*setChar*/, const coeffs cf )
800{
801  naTest(n);
802  if (n==NULL) return CanonicalForm(0);
803
804  return convSingPFactoryP((poly)n,naRing);
805}
806#endif
807
808
809/* IMPORTANT NOTE: Since an algebraic field extension is again a field,
810                   the gcd of two elements is not very interesting. (It
811                   is actually any unit in the field, i.e., any non-
812                   zero element.) Note that the below method does not operate
813                   in this strong sense but rather computes the gcd of
814                   two given elements in the underlying polynomial ring. */
815number naGcd(number a, number b, const coeffs cf)
816{
817  if (a==NULL)  return naCopy(b,cf);
818  if (b==NULL)  return naCopy(a,cf);
819
820  poly ax=(poly)a;
821  poly bx=(poly)b;
822  if (pNext(ax)!=NULL)
823    return (number)p_Copy(ax, naRing);
824  else
825  {
826    if(nCoeff_is_Zp(naRing->cf))
827      return naInit(1,cf);
828    else
829    {
830      number x = n_Copy(pGetCoeff((poly)a),naRing->cf);
831      if (n_IsOne(x,naRing->cf))
832        return (number)p_NSet(x,naRing);
833      while (pNext(ax)!=NULL)
834      {
835        pIter(ax);
836        number y = n_Gcd(x, pGetCoeff(ax), naRing->cf);
837        n_Delete(&x,naRing->cf);
838        x = y;
839        if (n_IsOne(x,naRing->cf))
840          return (number)p_NSet(x,naRing);
841      }
842      do
843      {
844        number y = n_Gcd(x, pGetCoeff(bx), naRing->cf);
845        n_Delete(&x,naRing->cf);
846        x = y;
847        if (n_IsOne(x,naRing->cf))
848          return (number)p_NSet(x,naRing);
849        pIter(bx);
850      }
851      while (bx!=NULL);
852      return (number)p_NSet(x,naRing);
853    }
854  }
855#if 0
856  naTest(a); naTest(b);
857  const ring R = naRing;
858  return (number) singclap_gcd(p_Copy((poly)a, R), p_Copy((poly)b, R), R);
859#endif
860//  return (number)p_Gcd((poly)a, (poly)b, naRing);
861}
862
863number naInvers(number a, const coeffs cf)
864{
865  naTest(a);
866  if (a == NULL) WerrorS(nDivBy0);
867
868  poly aFactor = NULL; poly mFactor = NULL; poly theGcd = NULL;
869// singclap_extgcd!
870  const BOOLEAN ret = singclap_extgcd ((poly)a, naMinpoly, theGcd, aFactor, mFactor, naRing);
871
872  assume( !ret );
873
874//  if( ret ) theGcd = p_ExtGcd((poly)a, aFactor, naMinpoly, mFactor, naRing);
875
876  naTest((number)theGcd); naTest((number)aFactor); naTest((number)mFactor);
877  p_Delete(&mFactor, naRing);
878
879  //  /* the gcd must be 1 since naMinpoly is irreducible and a != NULL: */
880  //  assume(naIsOne((number)theGcd, cf));
881
882  if( !naIsOne((number)theGcd, cf) )
883  {
884    WerrorS("zero divisor found - your minpoly is not irreducible");
885    p_Delete(&aFactor, naRing); aFactor = NULL;
886  }
887  p_Delete(&theGcd, naRing);
888
889  return (number)(aFactor);
890}
891
892/* assumes that src = Q, dst = Q(a) */
893number naMap00(number a, const coeffs src, const coeffs dst)
894{
895  if (n_IsZero(a, src)) return NULL;
896  assume(src == dst->extRing->cf);
897  poly result = p_One(dst->extRing);
898  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
899  return (number)result;
900}
901
902/* assumes that src = Z/p, dst = Q(a) */
903number naMapP0(number a, const coeffs src, const coeffs dst)
904{
905  if (n_IsZero(a, src)) return NULL;
906  /* mapping via intermediate int: */
907  int n = n_Int(a, src);
908  number q = n_Init(n, dst->extRing->cf);
909  poly result = p_One(dst->extRing);
910  p_SetCoeff(result, q, dst->extRing);
911  return (number)result;
912}
913
914#if 0
915/* assumes that either src = Q(a), dst = Q(a), or
916                       src = Z/p(a), dst = Z/p(a)     */
917number naCopyMap(number a, const coeffs src, const coeffs dst)
918{
919  return naCopy(a, dst);
920}
921#endif
922
923number naCopyTrans2AlgExt(number a, const coeffs src, const coeffs dst)
924{
925  assume (nCoeff_is_transExt (src));
926  assume (nCoeff_is_algExt (dst));
927  fraction fa=(fraction)a;
928  poly p, q;
929  if (rSamePolyRep(src->extRing, dst->extRing))
930  {
931    p = p_Copy(NUM(fa),src->extRing);
932    if (!DENIS1(fa))
933    {
934      q = p_Copy(DEN(fa),src->extRing);
935      assume (q != NULL);
936    }
937  }
938  else
939  {
940    assume ((strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0) && (rVar (src->extRing) == rVar (dst->extRing)));
941
942    nMapFunc nMap= n_SetMap (src->extRing->cf, dst->extRing->cf);
943
944    assume (nMap != NULL);
945    p= p_PermPoly (NUM (fa), NULL, src->extRing, dst->extRing,nMap, NULL,rVar (src->extRing));
946    if (!DENIS1(fa))
947    {
948      q= p_PermPoly (DEN (fa), NULL, src->extRing, dst->extRing,nMap, NULL,rVar (src->extRing));
949      assume (q != NULL);
950    }
951  }
952  definiteReduce(p, dst->extRing->qideal->m[0], dst);
953  assume (p_Test (p, dst->extRing));
954  if (!DENIS1(fa))
955  {
956    definiteReduce(q, dst->extRing->qideal->m[0], dst);
957    assume (p_Test (q, dst->extRing));
958    if (q != NULL)
959    {
960      number t= naDiv ((number)p,(number)q, dst);
961      p_Delete (&p, dst->extRing);
962      p_Delete (&q, dst->extRing);
963      return t;
964    }
965    WerrorS ("mapping denominator to zero");
966  }
967  return (number) p;
968}
969
970/* assumes that src = Q, dst = Z/p(a) */
971number naMap0P(number a, const coeffs src, const coeffs dst)
972{
973  if (n_IsZero(a, src)) return NULL;
974  // int p = rChar(dst->extRing);
975
976  number q = nlModP(a, src, dst->extRing->cf);
977
978  poly result = p_NSet(q, dst->extRing);
979
980  return (number)result;
981}
982
983/* assumes that src = Z/p, dst = Z/p(a) */
984number naMapPP(number a, const coeffs src, const coeffs dst)
985{
986  if (n_IsZero(a, src)) return NULL;
987  assume(src == dst->extRing->cf);
988  poly result = p_One(dst->extRing);
989  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
990  return (number)result;
991}
992
993/* assumes that src = Z/u, dst = Z/p(a), where u != p */
994number naMapUP(number a, const coeffs src, const coeffs dst)
995{
996  if (n_IsZero(a, src)) return NULL;
997  /* mapping via intermediate int: */
998  int n = n_Int(a, src);
999  number q = n_Init(n, dst->extRing->cf);
1000  poly result = p_One(dst->extRing);
1001  p_SetCoeff(result, q, dst->extRing);
1002  return (number)result;
1003}
1004
1005nMapFunc naSetMap(const coeffs src, const coeffs dst)
1006{
1007  /* dst is expected to be an algebraic field extension */
1008  assume(getCoeffType(dst) == ID);
1009
1010  if( src == dst ) return ndCopyMap;
1011
1012  int h = 0; /* the height of the extension tower given by dst */
1013  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
1014  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
1015
1016  /* for the time being, we only provide maps if h = 1 and if b is Q or
1017     some field Z/pZ: */
1018  if (h==0)
1019  {
1020    if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
1021      return naMap00;                            /// Q     -->  Q(a)
1022    if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
1023      return naMapP0;                            /// Z/p   -->  Q(a)
1024    if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
1025      return naMap0P;                            /// Q      --> Z/p(a)
1026    if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
1027    {
1028      if (src->ch == dst->ch) return naMapPP;    /// Z/p    --> Z/p(a)
1029      else return naMapUP;                       /// Z/u    --> Z/p(a)
1030    }
1031  }
1032  if (h != 1) return NULL;
1033  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
1034  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
1035
1036  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
1037  {
1038    if (rSamePolyRep(src->extRing, dst->extRing) && (strcmp(rRingVar(0, src->extRing), rRingVar(0, dst->extRing)) == 0))
1039    {
1040      if (src->type==n_algExt)
1041         return ndCopyMap; // naCopyMap;         /// Q(a)   --> Q(a)
1042      else
1043         return naCopyTrans2AlgExt;
1044    }
1045    else
1046      return NULL;                               /// Q(b)   --> Q(a)
1047  }
1048
1049  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
1050  {
1051    if (rSamePolyRep(src->extRing, dst->extRing) && (strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0))
1052    {
1053      if (src->type==n_algExt)
1054        return ndCopyMap; // naCopyMap;          /// Z/p(a) --> Z/p(a)
1055      else
1056         return naCopyTrans2AlgExt;
1057    }
1058    else if ((strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0) && (rVar (src->extRing) == rVar (dst->extRing)))
1059    {
1060      if (src->type==n_transExt)
1061        return naCopyTrans2AlgExt;
1062    }
1063  }
1064
1065  return NULL;                                           /// default
1066}
1067
1068static int naParDeg(number a, const coeffs cf)
1069{
1070  if (a == NULL) return -1;
1071  poly aa=(poly)a;
1072  return cf->extRing->pFDeg(aa,cf->extRing);
1073}
1074
1075/// return the specified parameter as a number in the given alg. field
1076static number naParameter(const int iParameter, const coeffs cf)
1077{
1078  assume(getCoeffType(cf) == ID);
1079
1080  const ring R = cf->extRing;
1081  assume( R != NULL );
1082  assume( 0 < iParameter && iParameter <= rVar(R) );
1083
1084  poly p = p_One(R); p_SetExp(p, iParameter, 1, R); p_Setm(p, R);
1085
1086  return (number) p;
1087}
1088
1089
1090/// if m == var(i)/1 => return i,
1091int naIsParam(number m, const coeffs cf)
1092{
1093  assume(getCoeffType(cf) == ID);
1094
1095  const ring R = cf->extRing;
1096  assume( R != NULL );
1097
1098  return p_Var( (poly)m, R );
1099}
1100
1101
1102static void naClearContent(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
1103{
1104  assume(cf != NULL);
1105  assume(getCoeffType(cf) == ID);
1106  assume(nCoeff_is_Q_algext(cf)); // only over (Q[a]/m(a)), while the default impl. is used over Zp[a]/m(a) !
1107
1108  const ring   R = cf->extRing;
1109  assume(R != NULL);
1110  const coeffs Q = R->cf;
1111  assume(Q != NULL);
1112  assume(nCoeff_is_Q(Q));
1113
1114  numberCollectionEnumerator.Reset();
1115
1116  if( !numberCollectionEnumerator.MoveNext() ) // empty zero polynomial?
1117  {
1118    c = n_Init(1, cf);
1119    return;
1120  }
1121
1122  naTest(numberCollectionEnumerator.Current());
1123
1124  // part 1, find a small candidate for gcd
1125  int s1; int s=2147483647; // max. int
1126
1127  const BOOLEAN lc_is_pos=naGreaterZero(numberCollectionEnumerator.Current(),cf);
1128
1129  int normalcount = 0;
1130
1131  poly cand1, cand;
1132
1133  do
1134  {
1135    number& n = numberCollectionEnumerator.Current();
1136    naNormalize(n, cf); ++normalcount;
1137
1138    naTest(n);
1139
1140    cand1 = (poly)n;
1141
1142    s1 = p_Deg(cand1, R); // naSize?
1143    if (s>s1)
1144    {
1145      cand = cand1;
1146      s = s1;
1147    }
1148  } while (numberCollectionEnumerator.MoveNext() );
1149
1150//  assume( nlGreaterZero(cand,cf) ); // cand may be a negative integer!
1151
1152  cand = p_Copy(cand, R);
1153  // part 2: compute gcd(cand,all coeffs)
1154
1155  numberCollectionEnumerator.Reset();
1156
1157  int length = 0;
1158  while (numberCollectionEnumerator.MoveNext() )
1159  {
1160    number& n = numberCollectionEnumerator.Current();
1161    ++length;
1162
1163    if( (--normalcount) <= 0)
1164      naNormalize(n, cf);
1165
1166    naTest(n);
1167
1168//    p_InpGcd(cand, (poly)n, R);
1169
1170    cand = singclap_gcd(cand, p_Copy((poly)n, R), R);
1171
1172//    cand1 = p_Gcd(cand,(poly)n, R); p_Delete(&cand, R); cand = cand1;
1173
1174    assume( naGreaterZero((number)cand, cf) ); // ???
1175/*
1176    if(p_IsConstant(cand,R))
1177    {
1178      c = cand;
1179
1180      if(!lc_is_pos)
1181      {
1182        // make the leading coeff positive
1183        c = nlNeg(c, cf);
1184        numberCollectionEnumerator.Reset();
1185
1186        while (numberCollectionEnumerator.MoveNext() )
1187        {
1188          number& nn = numberCollectionEnumerator.Current();
1189          nn = nlNeg(nn, cf);
1190        }
1191      }
1192      return;
1193    }
1194*/
1195
1196  }
1197
1198  // part3: all coeffs = all coeffs / cand
1199  if (!lc_is_pos)
1200    cand = p_Neg(cand, R);
1201
1202  c = (number)cand; naTest(c);
1203
1204  poly cInverse = (poly)naInvers(c, cf);
1205  assume(cInverse != NULL); // c is non-zero divisor!?
1206
1207
1208  numberCollectionEnumerator.Reset();
1209
1210
1211  while (numberCollectionEnumerator.MoveNext() )
1212  {
1213    number& n = numberCollectionEnumerator.Current();
1214
1215    assume( length > 0 );
1216
1217    if( --length > 0 )
1218    {
1219      assume( cInverse != NULL );
1220      n = (number) p_Mult_q(p_Copy(cInverse, R), (poly)n, R);
1221    }
1222    else
1223    {
1224      n = (number) p_Mult_q(cInverse, (poly)n, R);
1225      cInverse = NULL;
1226      assume(length == 0);
1227    }
1228
1229    definiteReduce((poly &)n, naMinpoly, cf);
1230  }
1231
1232  assume(length == 0);
1233  assume(cInverse == NULL); //   p_Delete(&cInverse, R);
1234
1235  // Quick and dirty fix for constant content clearing... !?
1236  CRecursivePolyCoeffsEnumerator<NAConverter> itr(numberCollectionEnumerator); // recursively treat the numbers as polys!
1237
1238  number cc;
1239
1240  n_ClearContent(itr, cc, Q); // TODO: get rid of (-LC) normalization!?
1241
1242  // over alg. ext. of Q // takes over the input number
1243  c = (number) p_Mult_nn( (poly)c, cc, R);
1244//      p_Mult_q(p_NSet(cc, R), , R);
1245
1246  n_Delete(&cc, Q);
1247
1248  // TODO: the above is not enough! need GCD's of polynomial coeffs...!
1249/*
1250  // old and wrong part of p_Content
1251    if (rField_is_Q_a(r) && !CLEARENUMERATORS) // should not be used anymore if CLEARENUMERATORS is 1
1252    {
1253      // we only need special handling for alg. ext.
1254      if (getCoeffType(r->cf)==n_algExt)
1255      {
1256        number hzz = n_Init(1, r->cf->extRing->cf);
1257        p=ph;
1258        while (p!=NULL)
1259        { // each monom: coeff in Q_a
1260          poly c_n_n=(poly)pGetCoeff(p);
1261          poly c_n=c_n_n;
1262          while (c_n!=NULL)
1263          { // each monom: coeff in Q
1264            d=n_Lcm(hzz,pGetCoeff(c_n),r->cf->extRing->cf);
1265            n_Delete(&hzz,r->cf->extRing->cf);
1266            hzz=d;
1267            pIter(c_n);
1268          }
1269          pIter(p);
1270        }
1271        // hzz contains the 1/lcm of all denominators in c_n_n
1272        h=n_Invers(hzz,r->cf->extRing->cf);
1273        n_Delete(&hzz,r->cf->extRing->cf);
1274        n_Normalize(h,r->cf->extRing->cf);
1275        if(!n_IsOne(h,r->cf->extRing->cf))
1276        {
1277          p=ph;
1278          while (p!=NULL)
1279          { // each monom: coeff in Q_a
1280            poly c_n=(poly)pGetCoeff(p);
1281            while (c_n!=NULL)
1282            { // each monom: coeff in Q
1283              d=n_Mult(h,pGetCoeff(c_n),r->cf->extRing->cf);
1284              n_Normalize(d,r->cf->extRing->cf);
1285              n_Delete(&pGetCoeff(c_n),r->cf->extRing->cf);
1286              pGetCoeff(c_n)=d;
1287              pIter(c_n);
1288            }
1289            pIter(p);
1290          }
1291        }
1292        n_Delete(&h,r->cf->extRing->cf);
1293      }
1294    }
1295*/
1296
1297
1298//  c = n_Init(1, cf); assume(FALSE); // TODO: NOT YET IMPLEMENTED!!!
1299}
1300
1301
1302static void naClearDenominators(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
1303{
1304  assume(cf != NULL);
1305  assume(getCoeffType(cf) == ID);
1306  assume(nCoeff_is_Q_algext(cf)); // only over (Q[a]/m(a)), while the default impl. is used over Zp[a]/m(a) !
1307
1308  assume(cf->extRing != NULL);
1309  const coeffs Q = cf->extRing->cf;
1310  assume(Q != NULL);
1311  assume(nCoeff_is_Q(Q));
1312  number n;
1313  CRecursivePolyCoeffsEnumerator<NAConverter> itr(numberCollectionEnumerator); // recursively treat the numbers as polys!
1314  n_ClearDenominators(itr, n, Q); // this should probably be fine...
1315  c = (number)p_NSet(n, cf->extRing); // over alg. ext. of Q // takes over the input number
1316}
1317
1318void naKillChar(coeffs cf)
1319{
1320   if ((--cf->extRing->ref) == 0)
1321     rDelete(cf->extRing);
1322}
1323
1324
1325
1326BOOLEAN naInitChar(coeffs cf, void * infoStruct)
1327{
1328  assume( infoStruct != NULL );
1329
1330  AlgExtInfo *e = (AlgExtInfo *)infoStruct;
1331  /// first check whether cf->extRing != NULL and delete old ring???
1332
1333  assume(e->r                     != NULL);      // extRing;
1334  assume(e->r->cf                 != NULL);      // extRing->cf;
1335
1336  assume((e->r->qideal            != NULL) &&    // minideal has one
1337         (IDELEMS(e->r->qideal)   == 1)    &&    // non-zero generator
1338         (e->r->qideal->m[0]      != NULL)    ); // at m[0];
1339
1340  assume( cf != NULL );
1341  assume(getCoeffType(cf) == ID);                     // coeff type;
1342
1343  e->r->ref ++; // increase the ref.counter for the ground poly. ring!
1344  const ring R = e->r; // no copy!
1345  assume( R->qideal == e->r->qideal );
1346  cf->extRing  = R;
1347
1348  /* propagate characteristic up so that it becomes
1349     directly accessible in cf: */
1350  cf->ch = R->cf->ch;
1351
1352  #ifdef LDEBUG
1353  p_Test((poly)naMinpoly, naRing);
1354  #endif
1355
1356  cf->cfGreaterZero  = naGreaterZero;
1357  cf->cfGreater      = naGreater;
1358  cf->cfEqual        = naEqual;
1359  cf->cfIsZero       = naIsZero;
1360  cf->cfIsOne        = naIsOne;
1361  cf->cfIsMOne       = naIsMOne;
1362  cf->cfInit         = naInit;
1363  cf->cfInit_bigint  = naInit_bigint;
1364  cf->cfInt          = naInt;
1365  cf->cfNeg          = naNeg;
1366  cf->cfAdd          = naAdd;
1367  cf->cfSub          = naSub;
1368  cf->cfMult         = naMult;
1369  cf->cfDiv          = naDiv;
1370  cf->cfExactDiv     = naDiv;
1371  cf->cfPower        = naPower;
1372  cf->cfCopy         = naCopy;
1373
1374  cf->cfWriteLong        = naWriteLong;
1375
1376  if( rCanShortOut(naRing) )
1377    cf->cfWriteShort = naWriteShort;
1378  else
1379    cf->cfWriteShort = naWriteLong;
1380
1381  cf->cfRead         = naRead;
1382  cf->cfDelete       = naDelete;
1383  cf->cfSetMap       = naSetMap;
1384  cf->cfGetDenom     = naGetDenom;
1385  cf->cfGetNumerator = naGetNumerator;
1386  cf->cfRePart       = naCopy;
1387  cf->cfImPart       = naImPart;
1388  cf->cfCoeffWrite   = naCoeffWrite;
1389  cf->cfNormalize    = naNormalize;
1390  cf->cfKillChar     = naKillChar;
1391#ifdef LDEBUG
1392  cf->cfDBTest       = naDBTest;
1393#endif
1394  cf->cfGcd          = naGcd;
1395  cf->cfLcm          = naLcmContent;
1396  cf->cfSize         = naSize;
1397  cf->nCoeffIsEqual  = naCoeffIsEqual;
1398  cf->cfInvers       = naInvers;
1399  cf->cfIntDiv       = naDiv; // ???
1400#ifdef HAVE_FACTORY
1401  cf->convFactoryNSingN=naConvFactoryNSingN;
1402  cf->convSingNFactoryN=naConvSingNFactoryN;
1403#endif
1404  cf->cfParDeg = naParDeg;
1405
1406  cf->iNumberOfParameters = rVar(R);
1407  cf->pParameterNames = R->names;
1408  cf->cfParameter = naParameter;
1409
1410  if( nCoeff_is_Q(R->cf) )
1411  {
1412    cf->cfClearContent = naClearContent;
1413    cf->cfClearDenominators = naClearDenominators;
1414  }
1415
1416  return FALSE;
1417}
Note: See TracBrowser for help on using the repository browser.