source: git/libpolys/polys/ext_fields/algext.cc @ 5523765

spielwiese
Last change on this file since 5523765 was 5523765, checked in by Martin Lee <martinlee84@…>, 11 years ago
chg: extended naCopyTrans2AlgExt
  • Property mode set to 100644
File size: 38.4 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  if (!DENIS1 (fa))
929    WarnS ("ignoring denominators in naCopyTrans2AlgExt");
930  poly p;
931  if (rSamePolyRep(src->extRing, dst->extRing))
932  {
933    p = p_Copy(NUM(fa),src->extRing);
934  }
935  else
936  {
937    assume ((strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0) && (rVar (src->extRing) == rVar (dst->extRing)));
938
939    nMapFunc nMap= n_SetMap (src->extRing->cf, dst->extRing->cf);
940
941    assume (nMap != NULL);
942    p= p_PermPoly (NUM (fa), NULL, src->extRing, dst->extRing,nMap, NULL,rVar (src->extRing));
943  }
944  definiteReduce(p, dst->extRing->qideal->m[0], dst);
945  assume (p_Test (p, dst->extRing));
946  return (number)p;
947}
948
949/* assumes that src = Q, dst = Z/p(a) */
950number naMap0P(number a, const coeffs src, const coeffs dst)
951{
952  if (n_IsZero(a, src)) return NULL;
953  int p = rChar(dst->extRing);
954
955  number q = nlModP(a, src, dst->extRing->cf);
956
957  poly result = p_NSet(q, dst->extRing);
958
959  return (number)result;
960}
961
962/* assumes that src = Z/p, dst = Z/p(a) */
963number naMapPP(number a, const coeffs src, const coeffs dst)
964{
965  if (n_IsZero(a, src)) return NULL;
966  assume(src == dst->extRing->cf);
967  poly result = p_One(dst->extRing);
968  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
969  return (number)result;
970}
971
972/* assumes that src = Z/u, dst = Z/p(a), where u != p */
973number naMapUP(number a, const coeffs src, const coeffs dst)
974{
975  if (n_IsZero(a, src)) return NULL;
976  /* mapping via intermediate int: */
977  int n = n_Int(a, src);
978  number q = n_Init(n, dst->extRing->cf);
979  poly result = p_One(dst->extRing);
980  p_SetCoeff(result, q, dst->extRing);
981  return (number)result;
982}
983
984nMapFunc naSetMap(const coeffs src, const coeffs dst)
985{
986  /* dst is expected to be an algebraic field extension */
987  assume(getCoeffType(dst) == ID);
988
989  if( src == dst ) return ndCopyMap;
990
991  int h = 0; /* the height of the extension tower given by dst */
992  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
993  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
994
995  /* for the time being, we only provide maps if h = 1 and if b is Q or
996     some field Z/pZ: */
997  if (h==0)
998  {
999    if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
1000      return naMap00;                            /// Q     -->  Q(a)
1001    if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
1002      return naMapP0;                            /// Z/p   -->  Q(a)
1003    if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
1004      return naMap0P;                            /// Q      --> Z/p(a)
1005    if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
1006    {
1007      if (src->ch == dst->ch) return naMapPP;    /// Z/p    --> Z/p(a)
1008      else return naMapUP;                       /// Z/u    --> Z/p(a)
1009    }
1010  }
1011  if (h != 1) return NULL;
1012  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
1013  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
1014
1015  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
1016  {
1017    if (rSamePolyRep(src->extRing, dst->extRing) && (strcmp(rRingVar(0, src->extRing), rRingVar(0, dst->extRing)) == 0))
1018    {
1019      if (src->type==n_algExt)
1020         return ndCopyMap; // naCopyMap;         /// Q(a)   --> Q(a)
1021      else
1022         return naCopyTrans2AlgExt;
1023    }
1024    else
1025      return NULL;                               /// Q(b)   --> Q(a)
1026  }
1027
1028  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
1029  {
1030    if (rSamePolyRep(src->extRing, dst->extRing) && (strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0))
1031    {
1032      if (src->type==n_algExt)
1033        return ndCopyMap; // naCopyMap;          /// Z/p(a) --> Z/p(a)
1034      else
1035         return naCopyTrans2AlgExt;
1036    }
1037    else if ((strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0) && (rVar (src->extRing) == rVar (dst->extRing)))
1038    {
1039      if (src->type==n_transExt)
1040        return naCopyTrans2AlgExt;
1041    }
1042  }
1043
1044  return NULL;                                           /// default
1045}
1046
1047static int naParDeg(number a, const coeffs cf)
1048{
1049  if (a == NULL) return -1;
1050  poly aa=(poly)a;
1051  return cf->extRing->pFDeg(aa,cf->extRing);
1052}
1053
1054/// return the specified parameter as a number in the given alg. field
1055static number naParameter(const int iParameter, const coeffs cf)
1056{
1057  assume(getCoeffType(cf) == ID);
1058
1059  const ring R = cf->extRing;
1060  assume( R != NULL );
1061  assume( 0 < iParameter && iParameter <= rVar(R) );
1062
1063  poly p = p_One(R); p_SetExp(p, iParameter, 1, R); p_Setm(p, R);
1064
1065  return (number) p;
1066}
1067
1068
1069/// if m == var(i)/1 => return i,
1070int naIsParam(number m, const coeffs cf)
1071{
1072  assume(getCoeffType(cf) == ID);
1073
1074  const ring R = cf->extRing;
1075  assume( R != NULL );
1076
1077  return p_Var( (poly)m, R );
1078}
1079
1080
1081static void naClearContent(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
1082{
1083  assume(cf != NULL);
1084  assume(getCoeffType(cf) == ID);
1085  assume(nCoeff_is_Q_algext(cf)); // only over (Q[a]/m(a)), while the default impl. is used over Zp[a]/m(a) !
1086
1087  const ring   R = cf->extRing;
1088  assume(R != NULL);
1089  const coeffs Q = R->cf;
1090  assume(Q != NULL);
1091  assume(nCoeff_is_Q(Q));
1092
1093  numberCollectionEnumerator.Reset();
1094
1095  if( !numberCollectionEnumerator.MoveNext() ) // empty zero polynomial?
1096  {
1097    c = n_Init(1, cf);
1098    return;
1099  }
1100
1101  naTest(numberCollectionEnumerator.Current());
1102
1103  // part 1, find a small candidate for gcd
1104  int s1; int s=2147483647; // max. int
1105
1106  const BOOLEAN lc_is_pos=naGreaterZero(numberCollectionEnumerator.Current(),cf);
1107
1108  int normalcount = 0;
1109
1110  poly cand1, cand;
1111
1112  do
1113  {
1114    number& n = numberCollectionEnumerator.Current();
1115    naNormalize(n, cf); ++normalcount;
1116
1117    naTest(n);
1118
1119    cand1 = (poly)n;
1120
1121    s1 = p_Deg(cand1, R); // naSize?
1122    if (s>s1)
1123    {
1124      cand = cand1;
1125      s = s1;
1126    }
1127  } while (numberCollectionEnumerator.MoveNext() );
1128
1129//  assume( nlGreaterZero(cand,cf) ); // cand may be a negative integer!
1130
1131  cand = p_Copy(cand, R);
1132  // part 2: compute gcd(cand,all coeffs)
1133
1134  numberCollectionEnumerator.Reset();
1135
1136  int length = 0;
1137  while (numberCollectionEnumerator.MoveNext() )
1138  {
1139    number& n = numberCollectionEnumerator.Current();
1140    ++length;
1141
1142    if( (--normalcount) <= 0)
1143      naNormalize(n, cf);
1144
1145    naTest(n);
1146
1147//    p_InpGcd(cand, (poly)n, R);
1148
1149    cand = singclap_gcd(cand, p_Copy((poly)n, R), R);
1150
1151//    cand1 = p_Gcd(cand,(poly)n, R); p_Delete(&cand, R); cand = cand1;
1152
1153    assume( naGreaterZero((number)cand, cf) ); // ???
1154/*
1155    if(p_IsConstant(cand,R))
1156    {
1157      c = cand;
1158
1159      if(!lc_is_pos)
1160      {
1161        // make the leading coeff positive
1162        c = nlNeg(c, cf);
1163        numberCollectionEnumerator.Reset();
1164
1165        while (numberCollectionEnumerator.MoveNext() )
1166        {
1167          number& nn = numberCollectionEnumerator.Current();
1168          nn = nlNeg(nn, cf);
1169        }
1170      }
1171      return;
1172    }
1173*/
1174
1175  }
1176
1177  // part3: all coeffs = all coeffs / cand
1178  if (!lc_is_pos)
1179    cand = p_Neg(cand, R);
1180
1181  c = (number)cand; naTest(c);
1182
1183  poly cInverse = (poly)naInvers(c, cf);
1184  assume(cInverse != NULL); // c is non-zero divisor!?
1185
1186
1187  numberCollectionEnumerator.Reset();
1188
1189
1190  while (numberCollectionEnumerator.MoveNext() )
1191  {
1192    number& n = numberCollectionEnumerator.Current();
1193
1194    assume( length > 0 );
1195
1196    if( --length > 0 )
1197    {
1198      assume( cInverse != NULL );
1199      n = (number) p_Mult_q(p_Copy(cInverse, R), (poly)n, R);
1200    }
1201    else
1202    {
1203      n = (number) p_Mult_q(cInverse, (poly)n, R);
1204      cInverse = NULL;
1205      assume(length == 0);
1206    }
1207
1208    definiteReduce((poly &)n, naMinpoly, cf);
1209  }
1210
1211  assume(length == 0);
1212  assume(cInverse == NULL); //   p_Delete(&cInverse, R);
1213
1214  // Quick and dirty fix for constant content clearing... !?
1215  CRecursivePolyCoeffsEnumerator<NAConverter> itr(numberCollectionEnumerator); // recursively treat the numbers as polys!
1216
1217  number cc;
1218
1219  n_ClearContent(itr, cc, Q); // TODO: get rid of (-LC) normalization!?
1220
1221  // over alg. ext. of Q // takes over the input number
1222  c = (number) p_Mult_nn( (poly)c, cc, R);
1223//      p_Mult_q(p_NSet(cc, R), , R);
1224
1225  n_Delete(&cc, Q);
1226
1227  // TODO: the above is not enough! need GCD's of polynomial coeffs...!
1228/*
1229  // old and wrong part of p_Content
1230    if (rField_is_Q_a(r) && !CLEARENUMERATORS) // should not be used anymore if CLEARENUMERATORS is 1
1231    {
1232      // we only need special handling for alg. ext.
1233      if (getCoeffType(r->cf)==n_algExt)
1234      {
1235        number hzz = n_Init(1, r->cf->extRing->cf);
1236        p=ph;
1237        while (p!=NULL)
1238        { // each monom: coeff in Q_a
1239          poly c_n_n=(poly)pGetCoeff(p);
1240          poly c_n=c_n_n;
1241          while (c_n!=NULL)
1242          { // each monom: coeff in Q
1243            d=n_Lcm(hzz,pGetCoeff(c_n),r->cf->extRing->cf);
1244            n_Delete(&hzz,r->cf->extRing->cf);
1245            hzz=d;
1246            pIter(c_n);
1247          }
1248          pIter(p);
1249        }
1250        // hzz contains the 1/lcm of all denominators in c_n_n
1251        h=n_Invers(hzz,r->cf->extRing->cf);
1252        n_Delete(&hzz,r->cf->extRing->cf);
1253        n_Normalize(h,r->cf->extRing->cf);
1254        if(!n_IsOne(h,r->cf->extRing->cf))
1255        {
1256          p=ph;
1257          while (p!=NULL)
1258          { // each monom: coeff in Q_a
1259            poly c_n=(poly)pGetCoeff(p);
1260            while (c_n!=NULL)
1261            { // each monom: coeff in Q
1262              d=n_Mult(h,pGetCoeff(c_n),r->cf->extRing->cf);
1263              n_Normalize(d,r->cf->extRing->cf);
1264              n_Delete(&pGetCoeff(c_n),r->cf->extRing->cf);
1265              pGetCoeff(c_n)=d;
1266              pIter(c_n);
1267            }
1268            pIter(p);
1269          }
1270        }
1271        n_Delete(&h,r->cf->extRing->cf);
1272      }
1273    }
1274*/
1275
1276
1277//  c = n_Init(1, cf); assume(FALSE); // TODO: NOT YET IMPLEMENTED!!!
1278}
1279
1280
1281static void naClearDenominators(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
1282{
1283  assume(cf != NULL);
1284  assume(getCoeffType(cf) == ID);
1285  assume(nCoeff_is_Q_algext(cf)); // only over (Q[a]/m(a)), while the default impl. is used over Zp[a]/m(a) !
1286
1287  assume(cf->extRing != NULL);
1288  const coeffs Q = cf->extRing->cf;
1289  assume(Q != NULL);
1290  assume(nCoeff_is_Q(Q));
1291  number n;
1292  CRecursivePolyCoeffsEnumerator<NAConverter> itr(numberCollectionEnumerator); // recursively treat the numbers as polys!
1293  n_ClearDenominators(itr, n, Q); // this should probably be fine...
1294  c = (number)p_NSet(n, cf->extRing); // over alg. ext. of Q // takes over the input number
1295}
1296
1297void naKillChar(coeffs cf)
1298{
1299   if ((--cf->extRing->ref) == 0)
1300     rDelete(cf->extRing);
1301}
1302
1303
1304
1305BOOLEAN naInitChar(coeffs cf, void * infoStruct)
1306{
1307  assume( infoStruct != NULL );
1308
1309  AlgExtInfo *e = (AlgExtInfo *)infoStruct;
1310  /// first check whether cf->extRing != NULL and delete old ring???
1311
1312  assume(e->r                     != NULL);      // extRing;
1313  assume(e->r->cf                 != NULL);      // extRing->cf;
1314
1315  assume((e->r->qideal            != NULL) &&    // minideal has one
1316         (IDELEMS(e->r->qideal)   == 1)    &&    // non-zero generator
1317         (e->r->qideal->m[0]      != NULL)    ); // at m[0];
1318
1319  assume( cf != NULL );
1320  assume(getCoeffType(cf) == ID);                     // coeff type;
1321
1322  e->r->ref ++; // increase the ref.counter for the ground poly. ring!
1323  const ring R = e->r; // no copy!
1324  assume( R->qideal == e->r->qideal );
1325  cf->extRing  = R;
1326
1327  /* propagate characteristic up so that it becomes
1328     directly accessible in cf: */
1329  cf->ch = R->cf->ch;
1330
1331  #ifdef LDEBUG
1332  p_Test((poly)naMinpoly, naRing);
1333  #endif
1334
1335  cf->cfGreaterZero  = naGreaterZero;
1336  cf->cfGreater      = naGreater;
1337  cf->cfEqual        = naEqual;
1338  cf->cfIsZero       = naIsZero;
1339  cf->cfIsOne        = naIsOne;
1340  cf->cfIsMOne       = naIsMOne;
1341  cf->cfInit         = naInit;
1342  cf->cfInit_bigint  = naInit_bigint;
1343  cf->cfInt          = naInt;
1344  cf->cfNeg          = naNeg;
1345  cf->cfAdd          = naAdd;
1346  cf->cfSub          = naSub;
1347  cf->cfMult         = naMult;
1348  cf->cfDiv          = naDiv;
1349  cf->cfExactDiv     = naDiv;
1350  cf->cfPower        = naPower;
1351  cf->cfCopy         = naCopy;
1352
1353  cf->cfWriteLong        = naWriteLong;
1354
1355  if( rCanShortOut(naRing) )
1356    cf->cfWriteShort = naWriteShort;
1357  else
1358    cf->cfWriteShort = naWriteLong;
1359
1360  cf->cfRead         = naRead;
1361  cf->cfDelete       = naDelete;
1362  cf->cfSetMap       = naSetMap;
1363  cf->cfGetDenom     = naGetDenom;
1364  cf->cfGetNumerator = naGetNumerator;
1365  cf->cfRePart       = naCopy;
1366  cf->cfImPart       = naImPart;
1367  cf->cfCoeffWrite   = naCoeffWrite;
1368  cf->cfNormalize    = naNormalize;
1369  cf->cfKillChar     = naKillChar;
1370#ifdef LDEBUG
1371  cf->cfDBTest       = naDBTest;
1372#endif
1373  cf->cfGcd          = naGcd;
1374  cf->cfLcm          = naLcmContent;
1375  cf->cfSize         = naSize;
1376  cf->nCoeffIsEqual  = naCoeffIsEqual;
1377  cf->cfInvers       = naInvers;
1378  cf->cfIntDiv       = naDiv; // ???
1379#ifdef HAVE_FACTORY
1380  cf->convFactoryNSingN=naConvFactoryNSingN;
1381  cf->convSingNFactoryN=naConvSingNFactoryN;
1382#endif
1383  cf->cfParDeg = naParDeg;
1384
1385  cf->iNumberOfParameters = rVar(R);
1386  cf->pParameterNames = R->names;
1387  cf->cfParameter = naParameter;
1388
1389  if( nCoeff_is_Q(R->cf) )
1390  {
1391    cf->cfClearContent = naClearContent;
1392    cf->cfClearDenominators = naClearDenominators;
1393  }
1394
1395  return FALSE;
1396}
Note: See TracBrowser for help on using the repository browser.