source: git/libpolys/polys/ext_fields/algext.cc @ 20c540

spielwiese
Last change on this file since 20c540 was 20c540, checked in by Oleksandr Motsak <motsak@…>, 12 years ago
Preparing the removal of Frank's p_Monic/p_Gcd/p_ExtGcd from common use chg: moved most of the functions (with helpers) into algext.cc and made them static NOTE: p_PolyDiv stayed in p_polys.cc as it is used in convFactoryASingA NOTE: p_ExtGcd also is made public via algext.h (needed elsewhere?)
  • Property mode set to 100644
File size: 36.1 KB
RevLine 
[fba6f18]1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
[1f414c8]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
[dd668f]16  *               cf->extRing->qideal is not NULL but an ideal with at
[1f414c8]17  *               least one non-zero generator which may be accessed by
[dd668f]18  *               cf->extRing->qideal->m[0] and which represents the minimal
[1f414c8]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  **/
[fba6f18]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>
[0fb5991]40#include <coeffs/longrat.h>
[fba6f18]41
42#include <polys/monomials/ring.h>
43#include <polys/monomials/p_polys.h>
44#include <polys/simpleideals.h>
45
[dc79bd]46#include <polys/PolyEnumerator.h>
47
[146c603]48#ifdef HAVE_FACTORY
49#include <factory/factory.h>
[dc79bd]50#include <polys/clapconv.h>
51#include <polys/clapsing.h>
[146c603]52#endif
53
[dc79bd]54   
55#include <polys/ext_fields/algext.h>
[331fd0]56#define TRANSEXT_PRIVATES 1
[dc79bd]57#include <polys/ext_fields/transext.h>
[1f414c8]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
[644f81]63#define naTest(a) ((void)(TRUE))
[1f414c8]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 */
[dd668f]79#define naMinpoly naRing->qideal->m[0]
[fba6f18]80
81/// forward declarations
[3c0498]82BOOLEAN  naGreaterZero(number a, const coeffs cf);
[fba6f18]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);
[2f3764]88number   naInit(long i, const coeffs cf);
[fba6f18]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);
[ce1f78]98void     naWriteLong(number &a, const coeffs cf);
99void     naWriteShort(number &a, const coeffs cf);
[fba6f18]100number   naRePart(number a, const coeffs cf);
101number   naImPart(number a, const coeffs cf);
[0fb5991]102number   naGetDenom(number &a, const coeffs cf);
103number   naGetNumerator(number &a, const coeffs cf);
[ba2359]104number   naGcd(number a, number b, const coeffs cf);
[36ef6e0]105//number   naLcm(number a, number b, const coeffs cf);
[ba2359]106int      naSize(number a, const coeffs cf);
[fba6f18]107void     naDelete(number *a, const coeffs cf);
[03f7b5]108void     naCoeffWrite(const coeffs cf, BOOLEAN details);
[dc79bd]109//number   naIntDiv(number a, number b, const coeffs cf);
[fba6f18]110const char * naRead(const char *s, number *a, const coeffs cf);
[03f7b5]111
[fba6f18]112static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param);
113
[20c540]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
[fba6f18]246#ifdef LDEBUG
[ba2359]247BOOLEAN naDBTest(number a, const char *f, const int l, const coeffs cf)
[fba6f18]248{
[1f414c8]249  assume(getCoeffType(cf) == ID);
[f0b01f]250  if (a == NULL) return TRUE;
[c28ecf]251  p_Test((poly)a, naRing);
[3c0498]252  if((((poly)a)!=naMinpoly)
253  && p_Totaldegree((poly)a, naRing) >= p_Totaldegree(naMinpoly, naRing))
[58f11d0]254  {
255    Print("deg >= deg(minpoly) in %s:%d\n",f,l);
256    return FALSE;
257  }
[fba6f18]258  return TRUE;
259}
260#endif
261
[4a2260e]262void heuristicReduce(poly &p, poly reducer, const coeffs cf);
263void definiteReduce(poly &p, poly reducer, const coeffs cf);
[ba2359]264
[488808e]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  {
[6ccdd3a]276    assume(cf->extRing != NULL); assume(cf->extRing->cf != NULL);
277    cf = cf->extRing->cf;
[488808e]278    height++;
279  }
280  return cf;
281}
282
[fba6f18]283BOOLEAN naIsZero(number a, const coeffs cf)
284{
285  naTest(a);
286  return (a == NULL);
287}
288
[c28ecf]289void naDelete(number * a, const coeffs cf)
[fba6f18]290{
[c28ecf]291  if (*a == NULL) return;
[3c0498]292  if (((poly)*a)==naMinpoly) { *a=NULL;return;}
[c28ecf]293  poly aAsPoly = (poly)(*a);
294  p_Delete(&aAsPoly, naRing);
[fba6f18]295  *a = NULL;
296}
297
[2c7f28]298BOOLEAN naEqual(number a, number b, const coeffs cf)
[fba6f18]299{
300  naTest(a); naTest(b);
[3c0498]301
[fba6f18]302  /// simple tests
303  if (a == b) return TRUE;
304  if ((a == NULL) && (b != NULL)) return FALSE;
305  if ((b == NULL) && (a != NULL)) return FALSE;
306
307  /// deg test
308  int aDeg = 0;
[2c7f28]309  if (a != NULL) aDeg = p_Totaldegree((poly)a, naRing);
[fba6f18]310  int bDeg = 0;
[2c7f28]311  if (b != NULL) bDeg = p_Totaldegree((poly)b, naRing);
[fba6f18]312  if (aDeg != bDeg) return FALSE;
[3c0498]313
[fba6f18]314  /// subtraction test
315  number c = naSub(a, b, cf);
316  BOOLEAN result = naIsZero(c, cf);
[e852125]317  naDelete(&c, cf);
[fba6f18]318  return result;
319}
320
[0fb5991]321number naCopy(number a, const coeffs cf)
[fba6f18]322{
323  naTest(a);
[ba2359]324  if (a == NULL) return NULL;
[3c0498]325  if (((poly)a)==naMinpoly) return a;
[fba6f18]326  return (number)p_Copy((poly)a, naRing);
327}
328
[0fb5991]329number naGetNumerator(number &a, const coeffs cf)
330{
331  return naCopy(a, cf);
332}
333
[fba6f18]334number naGetDenom(number &a, const coeffs cf)
335{
336  naTest(a);
337  return naInit(1, cf);
338}
339
340BOOLEAN naIsOne(number a, const coeffs cf)
341{
342  naTest(a);
[2c7f28]343  poly aAsPoly = (poly)a;
[bca341]344  if ((a==NULL) || (!p_IsConstant(aAsPoly, naRing))) return FALSE;
[2c7f28]345  return n_IsOne(p_GetCoeff(aAsPoly, naRing), naCoeffs);
[fba6f18]346}
347
348BOOLEAN naIsMOne(number a, const coeffs cf)
349{
350  naTest(a);
[2c7f28]351  poly aAsPoly = (poly)a;
[bca341]352  if ((a==NULL) || (!p_IsConstant(aAsPoly, naRing))) return FALSE;
[2c7f28]353  return n_IsMOne(p_GetCoeff(aAsPoly, naRing), naCoeffs);
[fba6f18]354}
355
356/// this is in-place, modifies a
357number naNeg(number a, const coeffs cf)
358{
359  naTest(a);
360  if (a != NULL) a = (number)p_Neg((poly)a, naRing);
361  return a;
362}
363
364number naImPart(number a, const coeffs cf)
365{
366  naTest(a);
367  return NULL;
368}
369
[61b2e16]370number naInit_bigint(number longratBigIntNumber, const coeffs src, const coeffs cf)
371{
372  assume( cf != NULL );
373
374  const ring A = cf->extRing;
375
376  assume( A != NULL );
377
378  const coeffs C = A->cf;
379
380  assume( C != NULL );
381
382  number n = n_Init_bigint(longratBigIntNumber, src, C);
383
384  if ( n_IsZero(n, C) )
385  {
386    n_Delete(&n, C);
387    return NULL;
388  }
[3c0498]389
[61b2e16]390  return (number)p_NSet(n, A);
391}
392
393
394
[2f3764]395number naInit(long i, const coeffs cf)
[fba6f18]396{
397  if (i == 0) return NULL;
398  else        return (number)p_ISet(i, naRing);
399}
400
401int naInt(number &a, const coeffs cf)
402{
403  naTest(a);
[2c7f28]404  poly aAsPoly = (poly)a;
[1090a98]405  if(aAsPoly == NULL)
406    return 0;
407  if (!p_IsConstant(aAsPoly, naRing))
408    return 0;
409  assume( aAsPoly != NULL );
[2c7f28]410  return n_Int(p_GetCoeff(aAsPoly, naRing), naCoeffs);
[fba6f18]411}
412
[afda22]413/* TRUE iff (a != 0 and (b == 0 or deg(a) > deg(b) or (deg(a)==deg(b) && lc(a)>lc(b))) */
[fba6f18]414BOOLEAN naGreater(number a, number b, const coeffs cf)
415{
[2c7f28]416  naTest(a); naTest(b);
[afda22]417  if (naIsZero(a, cf))
418  {
419    if (naIsZero(b, cf)) return FALSE;
420    return !n_GreaterZero(pGetCoeff((poly)b),cf);
421  }
422  if (naIsZero(b, cf))
423  {
424    return n_GreaterZero(pGetCoeff((poly)a),cf);
425  }
426  int aDeg = p_Totaldegree((poly)a, naRing);
427  int bDeg = p_Totaldegree((poly)b, naRing);
428  if (aDeg>bDeg) return TRUE;
429  if (aDeg<bDeg) return FALSE;
430  return n_Greater(pGetCoeff((poly)a),pGetCoeff((poly)b),cf);
[fba6f18]431}
432
433/* TRUE iff a != 0 and (LC(a) > 0 or deg(a) > 0) */
434BOOLEAN naGreaterZero(number a, const coeffs cf)
435{
436  naTest(a);
437  if (a == NULL)                                            return FALSE;
438  if (n_GreaterZero(p_GetCoeff((poly)a, naRing), naCoeffs)) return TRUE;
[2c7f28]439  if (p_Totaldegree((poly)a, naRing) > 0)                   return TRUE;
[fba6f18]440  return FALSE;
441}
442
[03f7b5]443void naCoeffWrite(const coeffs cf, BOOLEAN details)
[fba6f18]444{
[a55ef0]445  assume( cf != NULL );
[3c0498]446
[a55ef0]447  const ring A = cf->extRing;
[3c0498]448
[a55ef0]449  assume( A != NULL );
450  assume( A->cf != NULL );
[3c0498]451
[03f7b5]452  n_CoeffWrite(A->cf, details);
[3c0498]453
[a55ef0]454//  rWrite(A);
[3c0498]455
[a55ef0]456  const int P = rVar(A);
457  assume( P > 0 );
[3c0498]458
[a55ef0]459  Print("//   %d parameter    : ", P);
[3c0498]460
[a55ef0]461  for (int nop=0; nop < P; nop ++)
462    Print("%s ", rRingVar(nop, A));
[3c0498]463
[03f7b5]464  PrintLn();
[3c0498]465
[dd668f]466  const ideal I = A->qideal;
[a55ef0]467
468  assume( I != NULL );
469  assume( IDELEMS(I) == 1 );
[3c0498]470
[03f7b5]471
472  if ( details )
473  {
474    PrintS("//   minpoly        : (");
475    p_Write0( I->m[0], A);
476    PrintS(")");
477  }
478  else
479    PrintS("//   minpoly        : ...");
[3c0498]480
[03f7b5]481  PrintLn();
[3c0498]482
[a55ef0]483/*
484  char *x = rRingVar(0, A);
485
[fba6f18]486  Print("//   Coefficients live in the extension field K[%s]/<f(%s)>\n", x, x);
487  Print("//   with the minimal polynomial f(%s) = %s\n", x,
[dd668f]488        p_String(A->qideal->m[0], A));
[a55ef0]489  PrintS("//   and K: ");
490*/
[fba6f18]491}
492
[ba2359]493number naAdd(number a, number b, const coeffs cf)
[fba6f18]494{
[ba2359]495  naTest(a); naTest(b);
496  if (a == NULL) return naCopy(b, cf);
497  if (b == NULL) return naCopy(a, cf);
498  poly aPlusB = p_Add_q(p_Copy((poly)a, naRing),
499                        p_Copy((poly)b, naRing), naRing);
[0fb5991]500  definiteReduce(aPlusB, naMinpoly, cf);
501  return (number)aPlusB;
[fba6f18]502}
503
504number naSub(number a, number b, const coeffs cf)
505{
[ba2359]506  naTest(a); naTest(b);
507  if (b == NULL) return naCopy(a, cf);
508  poly minusB = p_Neg(p_Copy((poly)b, naRing), naRing);
[0fb5991]509  if (a == NULL) return (number)minusB;
[ba2359]510  poly aMinusB = p_Add_q(p_Copy((poly)a, naRing), minusB, naRing);
[0fb5991]511  definiteReduce(aMinusB, naMinpoly, cf);
[ba2359]512  return (number)aMinusB;
513}
514
515number naMult(number a, number b, const coeffs cf)
516{
517  naTest(a); naTest(b);
518  if (a == NULL) return NULL;
519  if (b == NULL) return NULL;
520  poly aTimesB = p_Mult_q(p_Copy((poly)a, naRing),
521                          p_Copy((poly)b, naRing), naRing);
[0fb5991]522  definiteReduce(aTimesB, naMinpoly, cf);
523  return (number)aTimesB;
[ba2359]524}
525
526number naDiv(number a, number b, const coeffs cf)
527{
528  naTest(a); naTest(b);
529  if (b == NULL) WerrorS(nDivBy0);
530  if (a == NULL) return NULL;
531  poly bInverse = (poly)naInvers(b, cf);
[865b20]532  if(bInverse != NULL) // b is non-zero divisor!
533  {
534    poly aDivB = p_Mult_q(p_Copy((poly)a, naRing), bInverse, naRing);
535    definiteReduce(aDivB, naMinpoly, cf);
536    return (number)aDivB;
537  }
538  return NULL;
[ba2359]539}
540
541/* 0^0 = 0;
542   for |exp| <= 7 compute power by a simple multiplication loop;
543   for |exp| >= 8 compute power along binary presentation of |exp|, e.g.
544      p^13 = p^1 * p^4 * p^8, where we utilise that
[2c7f28]545      p^(2^(k+1)) = p^(2^k) * p^(2^k);
[ba2359]546   intermediate reduction modulo the minimal polynomial is controlled by
547   the in-place method heuristicReduce(poly, poly, coeffs); see there.
548*/
549void naPower(number a, int exp, number *b, const coeffs cf)
550{
551  naTest(a);
[3c0498]552
[ba2359]553  /* special cases first */
554  if (a == NULL)
555  {
[0fb5991]556    if (exp >= 0) *b = NULL;
[ba2359]557    else          WerrorS(nDivBy0);
558  }
[35e86e]559  else if (exp ==  0) { *b = naInit(1, cf); return; }
560  else if (exp ==  1) { *b = naCopy(a, cf); return; }
561  else if (exp == -1) { *b = naInvers(a, cf); return; }
[3c0498]562
[ba2359]563  int expAbs = exp; if (expAbs < 0) expAbs = -expAbs;
[3c0498]564
[2c7f28]565  /* now compute a^expAbs */
[ba2359]566  poly pow; poly aAsPoly = (poly)a;
567  if (expAbs <= 7)
568  {
569    pow = p_Copy(aAsPoly, naRing);
570    for (int i = 2; i <= expAbs; i++)
571    {
572      pow = p_Mult_q(pow, p_Copy(aAsPoly, naRing), naRing);
573      heuristicReduce(pow, naMinpoly, cf);
574    }
575    definiteReduce(pow, naMinpoly, cf);
576  }
577  else
578  {
579    pow = p_ISet(1, naRing);
580    poly factor = p_Copy(aAsPoly, naRing);
581    while (expAbs != 0)
582    {
583      if (expAbs & 1)
584      {
585        pow = p_Mult_q(pow, p_Copy(factor, naRing), naRing);
586        heuristicReduce(pow, naMinpoly, cf);
587      }
588      expAbs = expAbs / 2;
589      if (expAbs != 0)
590      {
[f681a60]591        factor = p_Mult_q(factor, p_Copy(factor, naRing), naRing);
[ba2359]592        heuristicReduce(factor, naMinpoly, cf);
593      }
594    }
[0fb5991]595    p_Delete(&factor, naRing);
[ba2359]596    definiteReduce(pow, naMinpoly, cf);
597  }
[3c0498]598
[ba2359]599  /* invert if original exponent was negative */
600  number n = (number)pow;
601  if (exp < 0)
602  {
603    number m = naInvers(n, cf);
604    naDelete(&n, cf);
605    n = m;
606  }
607  *b = n;
608}
609
[2c7f28]610/* may reduce p modulo the reducer by calling definiteReduce;
[ba2359]611   the decision is made based on the following heuristic
612   (which should also only be changed here in this method):
[4a2260e]613      if (deg(p) > 10*deg(reducer) then perform reduction;
614   modifies p */
615void heuristicReduce(poly &p, poly reducer, const coeffs cf)
[ba2359]616{
617  #ifdef LDEBUG
[c28ecf]618  p_Test((poly)p, naRing);
619  p_Test((poly)reducer, naRing);
[ba2359]620  #endif
[2c7f28]621  if (p_Totaldegree(p, naRing) > 10 * p_Totaldegree(reducer, naRing))
[ba2359]622    definiteReduce(p, reducer, cf);
623}
624
[ce1f78]625void naWriteLong(number &a, const coeffs cf)
[ba2359]626{
627  naTest(a);
628  if (a == NULL)
629    StringAppendS("0");
630  else
631  {
632    poly aAsPoly = (poly)a;
633    /* basically, just write aAsPoly using p_Write,
634       but use brackets around the output, if a is not
[6ccdd3a]635       a constant living in naCoeffs = cf->extRing->cf */
[fd01a8]636    BOOLEAN useBrackets = !(p_IsConstant(aAsPoly, naRing));
[ba2359]637    if (useBrackets) StringAppendS("(");
[ce1f78]638    p_String0Long(aAsPoly, naRing, naRing);
639    if (useBrackets) StringAppendS(")");
640  }
641}
642
643void naWriteShort(number &a, const coeffs cf)
644{
645  naTest(a);
646  if (a == NULL)
647    StringAppendS("0");
648  else
649  {
650    poly aAsPoly = (poly)a;
651    /* basically, just write aAsPoly using p_Write,
652       but use brackets around the output, if a is not
653       a constant living in naCoeffs = cf->extRing->cf */
654    BOOLEAN useBrackets = !(p_IsConstant(aAsPoly, naRing));
655    if (useBrackets) StringAppendS("(");
656    p_String0Short(aAsPoly, naRing, naRing);
[ba2359]657    if (useBrackets) StringAppendS(")");
658  }
659}
660
661const char * naRead(const char *s, number *a, const coeffs cf)
662{
663  poly aAsPoly;
664  const char * result = p_Read(s, aAsPoly, naRing);
[58f11d0]665  definiteReduce(aAsPoly, naMinpoly, cf);
[ba2359]666  *a = (number)aAsPoly;
667  return result;
[fba6f18]668}
669
[36ef6e0]670#if 0
[ba2359]671/* implemented by the rule lcm(a, b) = a * b / gcd(a, b) */
672number naLcm(number a, number b, const coeffs cf)
673{
674  naTest(a); naTest(b);
675  if (a == NULL) return NULL;
676  if (b == NULL) return NULL;
677  number theProduct = (number)p_Mult_q(p_Copy((poly)a, naRing),
678                                       p_Copy((poly)b, naRing), naRing);
679  /* note that theProduct needs not be reduced w.r.t. naMinpoly;
680     but the final division will take care of the necessary reduction */
681  number theGcd = naGcd(a, b, cf);
[0fb5991]682  return naDiv(theProduct, theGcd, cf);
[ba2359]683}
[36ef6e0]684#endif
[ba2359]685
[6ccdd3a]686/* expects *param to be castable to AlgExtInfo */
[ba2359]687static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param)
688{
[1f414c8]689  if (ID != n) return FALSE;
[6ccdd3a]690  AlgExtInfo *e = (AlgExtInfo *)param;
[ba2359]691  /* for extension coefficient fields we expect the underlying
[2c7f28]692     polynomial rings to be IDENTICAL, i.e. the SAME OBJECT;
[ba2359]693     this expectation is based on the assumption that we have properly
694     registered cf and perform reference counting rather than creating
695     multiple copies of the same coefficient field/domain/ring */
[4d94c97]696  if (naRing == e->r)
697    return TRUE;
[ba2359]698  /* (Note that then also the minimal ideals will necessarily be
699     the same, as they are attached to the ring.) */
[4d94c97]700
701  // NOTE: Q(a)[x] && Q(a)[y] should better share the _same_ Q(a)...
[7e9f12]702  if( rEqual(naRing, e->r, TRUE) ) // also checks the equality of qideals
[4d94c97]703  {
[dd668f]704    const ideal mi = naRing->qideal; 
[4d94c97]705    assume( IDELEMS(mi) == 1 );
[7e9f12]706    const ideal ii = e->r->qideal;
[4d94c97]707    assume( IDELEMS(ii) == 1 );
708
709    // TODO: the following should be extended for 2 *equal* rings...
[7e9f12]710    assume( p_EqualPolys(mi->m[0], ii->m[0], naRing, e->r) );
711   
712    rDelete(e->r);
713   
714    return TRUE;
[4d94c97]715  }
716
[3c0498]717  return FALSE;
718
[ba2359]719}
720
721int naSize(number a, const coeffs cf)
722{
723  if (a == NULL) return -1;
724  /* this has been taken from the old implementation of field extensions,
725     where we computed the sum of the degree and the number of terms in
726     (poly)a; so we leave it at that, for the time being;
727     maybe, the number of terms alone is a better measure? */
728  poly aAsPoly = (poly)a;
729  int theDegree = 0; int noOfTerms = 0;
730  while (aAsPoly != NULL)
731  {
732    noOfTerms++;
[2c7f28]733    int d = p_GetExp(aAsPoly, 1, naRing);
[ba2359]734    if (d > theDegree) theDegree = d;
735    pIter(aAsPoly);
736  }
737  return theDegree + noOfTerms;
738}
739
740/* performs polynomial division and overrides p by the remainder
[4a2260e]741   of division of p by the reducer;
742   modifies p */
743void definiteReduce(poly &p, poly reducer, const coeffs cf)
[ba2359]744{
745  #ifdef LDEBUG
[c28ecf]746  p_Test((poly)p, naRing);
747  p_Test((poly)reducer, naRing);
[ba2359]748  #endif
[bca341]749  if ((p!=NULL) && (p_GetExp(p,1,naRing)>=p_GetExp(reducer,1,naRing)))
750  {
751    p_PolyDiv(p, reducer, FALSE, naRing);
752  }
[ba2359]753}
754
[146c603]755void  naNormalize(number &a, const coeffs cf)
756{
757  poly aa=(poly)a;
[3c0498]758  if (aa!=naMinpoly)
759    definiteReduce(aa,naMinpoly,cf);
[146c603]760  a=(number)aa;
761}
762
763#ifdef HAVE_FACTORY
764number naConvFactoryNSingN( const CanonicalForm n, const coeffs cf)
765{
766  if (n.isZero()) return NULL;
767  poly p=convFactoryPSingP(n,naRing);
768  return (number)p;
769}
[2d2e40]770CanonicalForm naConvSingNFactoryN( number n, BOOLEAN /*setChar*/, const coeffs cf )
[146c603]771{
772  naTest(n);
773  if (n==NULL) return CanonicalForm(0);
774
775  return convSingPFactoryP((poly)n,naRing);
776}
777#endif
778
779
[cfb500]780/* IMPORTANT NOTE: Since an algebraic field extension is again a field,
781                   the gcd of two elements is not very interesting. (It
782                   is actually any unit in the field, i.e., any non-
783                   zero element.) Note that the below method does not operate
784                   in this strong sense but rather computes the gcd of
785                   two given elements in the underlying polynomial ring. */
[ba2359]786number naGcd(number a, number b, const coeffs cf)
787{
788  naTest(a); naTest(b);
789  if ((a == NULL) && (b == NULL)) WerrorS(nDivBy0);
[dc79bd]790  const ring R = naRing;
791  return (number) singclap_gcd(p_Copy((poly)a, R), p_Copy((poly)b, R), R);
792//  return (number)p_Gcd((poly)a, (poly)b, naRing);
[ba2359]793}
794
795number naInvers(number a, const coeffs cf)
796{
797  naTest(a);
798  if (a == NULL) WerrorS(nDivBy0);
[865b20]799 
[dc79bd]800  poly aFactor = NULL; poly mFactor = NULL; poly theGcd = NULL;
801// singclap_extgcd!
802  const BOOLEAN ret = singclap_extgcd ((poly)a, naMinpoly, theGcd, aFactor, mFactor, naRing);
803
804  assume( !ret );
805
806//  if( ret ) theGcd = p_ExtGcd((poly)a, aFactor, naMinpoly, mFactor, naRing);
[865b20]807 
[4a2260e]808  naTest((number)theGcd); naTest((number)aFactor); naTest((number)mFactor);
[f0b01f]809  p_Delete(&mFactor, naRing);
[865b20]810 
811  //  /* the gcd must be 1 since naMinpoly is irreducible and a != NULL: */
812  //  assume(naIsOne((number)theGcd, cf));
813
814  if( !naIsOne((number)theGcd, cf) )
815  { 
816    WerrorS("zero divisor found - your minpoly is not irreducible");
817    p_Delete(&aFactor, naRing); aFactor = NULL;
818  }
819  p_Delete(&theGcd, naRing);
820
[f0b01f]821  return (number)(aFactor);
[ba2359]822}
823
824/* assumes that src = Q, dst = Q(a) */
825number naMap00(number a, const coeffs src, const coeffs dst)
826{
[2c7f28]827  if (n_IsZero(a, src)) return NULL;
[6ccdd3a]828  assume(src == dst->extRing->cf);
829  poly result = p_One(dst->extRing);
[3c4a33]830  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
[ba2359]831  return (number)result;
832}
833
834/* assumes that src = Z/p, dst = Q(a) */
835number naMapP0(number a, const coeffs src, const coeffs dst)
836{
[2c7f28]837  if (n_IsZero(a, src)) return NULL;
[ba2359]838  /* mapping via intermediate int: */
839  int n = n_Int(a, src);
[6ccdd3a]840  number q = n_Init(n, dst->extRing->cf);
841  poly result = p_One(dst->extRing);
842  p_SetCoeff(result, q, dst->extRing);
[ba2359]843  return (number)result;
844}
845
[c14846c]846#if 0
[ba2359]847/* assumes that either src = Q(a), dst = Q(a), or
[2c7f28]848                       src = Z/p(a), dst = Z/p(a)     */
[ba2359]849number naCopyMap(number a, const coeffs src, const coeffs dst)
850{
851  return naCopy(a, dst);
852}
[c14846c]853#endif
[ba2359]854
[2d2e40]855number naCopyExt(number a, const coeffs src, const coeffs)
[331fd0]856{
857  fraction fa=(fraction)a;
858  return (number)p_Copy(NUM(fa),src->extRing);
859}
860
[ba2359]861/* assumes that src = Q, dst = Z/p(a) */
862number naMap0P(number a, const coeffs src, const coeffs dst)
863{
[2c7f28]864  if (n_IsZero(a, src)) return NULL;
[6ccdd3a]865  int p = rChar(dst->extRing);
[79020f]866
867  number q = nlModP(a, src, dst->extRing->cf);
868
869  poly result = p_NSet(q, dst->extRing);
[3c0498]870
[ba2359]871  return (number)result;
872}
873
874/* assumes that src = Z/p, dst = Z/p(a) */
875number naMapPP(number a, const coeffs src, const coeffs dst)
876{
[2c7f28]877  if (n_IsZero(a, src)) return NULL;
[6ccdd3a]878  assume(src == dst->extRing->cf);
879  poly result = p_One(dst->extRing);
[3c4a33]880  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
[ba2359]881  return (number)result;
882}
883
884/* assumes that src = Z/u, dst = Z/p(a), where u != p */
885number naMapUP(number a, const coeffs src, const coeffs dst)
886{
[2c7f28]887  if (n_IsZero(a, src)) return NULL;
[ba2359]888  /* mapping via intermediate int: */
889  int n = n_Int(a, src);
[6ccdd3a]890  number q = n_Init(n, dst->extRing->cf);
891  poly result = p_One(dst->extRing);
892  p_SetCoeff(result, q, dst->extRing);
[ba2359]893  return (number)result;
894}
895
[0654122]896nMapFunc naSetMap(const coeffs src, const coeffs dst)
[ba2359]897{
[488808e]898  /* dst is expected to be an algebraic field extension */
[1f414c8]899  assume(getCoeffType(dst) == ID);
[da0565b]900
901  if( src == dst ) return ndCopyMap;
[3c0498]902
[488808e]903  int h = 0; /* the height of the extension tower given by dst */
904  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
[331fd0]905  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
[3c0498]906
[488808e]907  /* for the time being, we only provide maps if h = 1 and if b is Q or
908     some field Z/pZ: */
[331fd0]909  if (h==0)
[488808e]910  {
[331fd0]911    if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
912      return naMap00;                            /// Q     -->  Q(a)
913    if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
914      return naMapP0;                            /// Z/p   -->  Q(a)
915    if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
916      return naMap0P;                            /// Q      --> Z/p(a)
917    if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
918    {
919      if (src->ch == dst->ch) return naMapPP;    /// Z/p    --> Z/p(a)
920      else return naMapUP;                       /// Z/u    --> Z/p(a)
921    }
[488808e]922  }
923  if (h != 1) return NULL;
[331fd0]924  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
[488808e]925  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
[3c0498]926
[488808e]927  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
[ba2359]928  {
[2c7f28]929    if (strcmp(rRingVar(0, src->extRing),
930               rRingVar(0, dst->extRing)) == 0)
[331fd0]931    {
932      if (src->type==n_algExt)
[c14846c]933         return ndCopyMap; // naCopyMap;         /// Q(a)   --> Q(a)
[331fd0]934      else
935         return naCopyExt;
936    }
[ba2359]937    else
[331fd0]938      return NULL;                               /// Q(b)   --> Q(a)
[ba2359]939  }
[3c0498]940
[488808e]941  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
[ba2359]942  {
[6f6b9d]943    if (strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0)
[331fd0]944    {
945      if (src->type==n_algExt)
[c14846c]946        return ndCopyMap; // naCopyMap;          /// Z/p(a) --> Z/p(a)
[331fd0]947      else
948         return naCopyExt;
949    }
[ba2359]950    else
[331fd0]951      return NULL;                               /// Z/p(b) --> Z/p(a)
[ba2359]952  }
[3c0498]953
[ba2359]954  return NULL;                                           /// default
955}
[fba6f18]956
[da5d77]957static int naParDeg(number a, const coeffs cf)
[48a41a]958{
959  if (a == NULL) return -1;
960  poly aa=(poly)a;
961  return cf->extRing->pFDeg(aa,cf->extRing);
962}
963
[7fee876]964/// return the specified parameter as a number in the given alg. field
965static number naParameter(const int iParameter, const coeffs cf)
966{
967  assume(getCoeffType(cf) == ID);
968
969  const ring R = cf->extRing;
[3c0498]970  assume( R != NULL );
[7fee876]971  assume( 0 < iParameter && iParameter <= rVar(R) );
972
973  poly p = p_One(R); p_SetExp(p, iParameter, 1, R); p_Setm(p, R);
974
[3c0498]975  return (number) p;
[7fee876]976}
977
978
[3c0498]979/// if m == var(i)/1 => return i,
[7fee876]980int naIsParam(number m, const coeffs cf)
981{
982  assume(getCoeffType(cf) == ID);
983
984  const ring R = cf->extRing;
[3c0498]985  assume( R != NULL );
[7fee876]986
[3c0498]987  return p_Var( (poly)m, R );
[7fee876]988}
989
[dc79bd]990
991static void naClearContent(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
[de88371]992{
993  assume(cf != NULL);
994  assume(getCoeffType(cf) == ID);
[dc79bd]995  assume(nCoeff_is_Q_algext(cf)); // only over (Q[a]/m(a)), while the default impl. is used over Zp[a]/m(a) !
996
997  const ring   R = cf->extRing;
998  assume(R != NULL);
999  const coeffs Q = R->cf; 
1000  assume(Q != NULL); 
1001  assume(nCoeff_is_Q(Q)); 
1002
1003  numberCollectionEnumerator.Reset();
1004
1005  if( !numberCollectionEnumerator.MoveNext() ) // empty zero polynomial?
1006  {
1007    c = n_Init(1, cf);
1008    return;
1009  }
1010
1011  naTest(numberCollectionEnumerator.Current());
1012
1013  // part 1, find a small candidate for gcd
1014  int s1; int s=2147483647; // max. int
1015
1016  const BOOLEAN lc_is_pos=naGreaterZero(numberCollectionEnumerator.Current(),cf);
1017
1018  int normalcount = 0;
1019 
1020  poly cand1, cand;
1021 
1022  do
1023  {
1024    number& n = numberCollectionEnumerator.Current();
1025    naNormalize(n, cf); ++normalcount;
1026
1027    naTest(n);
1028   
1029    cand1 = (poly)n;
1030
1031    s1 = p_Deg(cand1, R); // naSize?
1032    if (s>s1)
1033    {
1034      cand = cand1;
1035      s = s1;
1036    }
1037  } while (numberCollectionEnumerator.MoveNext() );
1038
1039//  assume( nlGreaterZero(cand,cf) ); // cand may be a negative integer!
1040
1041  cand = p_Copy(cand, R);
1042  // part 2: compute gcd(cand,all coeffs)
1043
1044  numberCollectionEnumerator.Reset();
1045
1046  int length = 0;
1047  while (numberCollectionEnumerator.MoveNext() )
1048  {
1049    number& n = numberCollectionEnumerator.Current();
1050    ++length;
1051   
1052    if( (--normalcount) <= 0)
1053      naNormalize(n, cf);
1054   
1055    naTest(n);
1056
1057//    p_InpGcd(cand, (poly)n, R);
1058   
1059    cand = singclap_gcd(cand, p_Copy((poly)n, R), R);
1060
1061//    cand1 = p_Gcd(cand,(poly)n, R); p_Delete(&cand, R); cand = cand1;
1062   
1063    assume( naGreaterZero((number)cand, cf) ); // ???
1064/*
1065    if(p_IsConstant(cand,R))
1066    {
1067      c = cand;
1068
1069      if(!lc_is_pos)
1070      {
1071        // make the leading coeff positive
1072        c = nlNeg(c, cf);
1073        numberCollectionEnumerator.Reset();
1074
1075        while (numberCollectionEnumerator.MoveNext() )
1076        {
1077          number& nn = numberCollectionEnumerator.Current();
1078          nn = nlNeg(nn, cf);
1079        }
1080      }
1081      return;
1082    }
1083*/
1084   
1085  } 
1086
1087  // part3: all coeffs = all coeffs / cand
1088  if (!lc_is_pos)
1089    cand = p_Neg(cand, R);
1090
1091  c = (number)cand; naTest(c); 
1092
1093  poly cInverse = (poly)naInvers(c, cf);
1094  assume(cInverse != NULL); // c is non-zero divisor!?
1095
1096 
1097  numberCollectionEnumerator.Reset();
1098
1099
1100  while (numberCollectionEnumerator.MoveNext() )
1101  {
1102    number& n = numberCollectionEnumerator.Current();
1103
1104    assume( length > 0 );
1105
1106    if( --length > 0 )
1107    {
1108      assume( cInverse != NULL );
1109      n = (number) p_Mult_q(p_Copy(cInverse, R), (poly)n, R);
1110    }
1111    else
1112    {
1113      n = (number) p_Mult_q(cInverse, (poly)n, R);
1114      cInverse = NULL;
1115      assume(length == 0);
1116    }
1117   
1118    definiteReduce((poly &)n, naMinpoly, cf);   
1119  }
1120 
1121  assume(length == 0);
1122  assume(cInverse == NULL); //   p_Delete(&cInverse, R);
1123
1124  // Quick and dirty fix for constant content clearing... !?
1125  CRecursivePolyCoeffsEnumerator<NAConverter> itr(numberCollectionEnumerator); // recursively treat the numbers as polys!
1126
1127  number cc;
1128
1129  extern void nlClearContentNoPositiveLead(ICoeffsEnumerator&, number&, const coeffs);
1130
1131  nlClearContentNoPositiveLead(itr, cc, Q); // TODO: get rid of (-LC) normalization!?
1132
1133  // over alg. ext. of Q // takes over the input number
1134  c = (number) p_Mult_nn( (poly)c, cc, R); 
1135//      p_Mult_q(p_NSet(cc, R), , R);
1136
1137  n_Delete(&cc, Q);
1138
1139  // TODO: the above is not enough! need GCD's of polynomial coeffs...!
1140/*
1141  // old and wrong part of p_Content
1142    if (rField_is_Q_a(r) && !CLEARENUMERATORS) // should not be used anymore if CLEARENUMERATORS is 1
1143    {
1144      // we only need special handling for alg. ext.
1145      if (getCoeffType(r->cf)==n_algExt)
1146      {
1147        number hzz = n_Init(1, r->cf->extRing->cf);
1148        p=ph;
1149        while (p!=NULL)
1150        { // each monom: coeff in Q_a
1151          poly c_n_n=(poly)pGetCoeff(p);
1152          poly c_n=c_n_n;
1153          while (c_n!=NULL)
1154          { // each monom: coeff in Q
1155            d=n_Lcm(hzz,pGetCoeff(c_n),r->cf->extRing->cf);
1156            n_Delete(&hzz,r->cf->extRing->cf);
1157            hzz=d;
1158            pIter(c_n);
1159          }
1160          pIter(p);
1161        }
1162        // hzz contains the 1/lcm of all denominators in c_n_n
1163        h=n_Invers(hzz,r->cf->extRing->cf);
1164        n_Delete(&hzz,r->cf->extRing->cf);
1165        n_Normalize(h,r->cf->extRing->cf);
1166        if(!n_IsOne(h,r->cf->extRing->cf))
1167        {
1168          p=ph;
1169          while (p!=NULL)
1170          { // each monom: coeff in Q_a
1171            poly c_n=(poly)pGetCoeff(p);
1172            while (c_n!=NULL)
1173            { // each monom: coeff in Q
1174              d=n_Mult(h,pGetCoeff(c_n),r->cf->extRing->cf);
1175              n_Normalize(d,r->cf->extRing->cf);
1176              n_Delete(&pGetCoeff(c_n),r->cf->extRing->cf);
1177              pGetCoeff(c_n)=d;
1178              pIter(c_n);
1179            }
1180            pIter(p);
1181          }
1182        }
1183        n_Delete(&h,r->cf->extRing->cf);
1184      }
1185    }
1186*/ 
1187
1188 
1189//  c = n_Init(1, cf); assume(FALSE); // TODO: NOT YET IMPLEMENTED!!!
1190}
1191
1192
1193static void naClearDenominators(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
1194{
1195  assume(cf != NULL);
1196  assume(getCoeffType(cf) == ID);
1197  assume(nCoeff_is_Q_algext(cf)); // only over (Q[a]/m(a)), while the default impl. is used over Zp[a]/m(a) !
1198
1199  assume(cf->extRing != NULL);
1200  const coeffs Q = cf->extRing->cf; 
1201  assume(Q != NULL); 
1202  assume(nCoeff_is_Q(Q)); 
1203  number n;
1204  CRecursivePolyCoeffsEnumerator<NAConverter> itr(numberCollectionEnumerator); // recursively treat the numbers as polys!
1205
1206  extern void nlClearDenominatorsNoPositiveLead(ICoeffsEnumerator&, number&, const coeffs);
1207
1208  nlClearDenominatorsNoPositiveLead(itr, n, Q); // this should probably be fine...
1209  c = (number)p_NSet(n, cf->extRing); // over alg. ext. of Q // takes over the input number
[de88371]1210}
1211
1212
[ba2359]1213BOOLEAN naInitChar(coeffs cf, void * infoStruct)
[3c0498]1214{
[a55ef0]1215  assume( infoStruct != NULL );
1216
[6ccdd3a]1217  AlgExtInfo *e = (AlgExtInfo *)infoStruct;
1218  /// first check whether cf->extRing != NULL and delete old ring???
1219
[ec5ec8]1220  assume(e->r                     != NULL);      // extRing;
1221  assume(e->r->cf                 != NULL);      // extRing->cf;
1222
[7e9f12]1223  assume((e->r->qideal            != NULL) &&    // minideal has one
1224         (IDELEMS(e->r->qideal)   == 1)    &&    // non-zero generator
1225         (e->r->qideal->m[0]      != NULL)    ); // at m[0];
[ec5ec8]1226
1227  assume( cf != NULL );
[1f414c8]1228  assume(getCoeffType(cf) == ID);                     // coeff type;
[7fee876]1229
[7e9f12]1230  e->r->ref ++; // increase the ref.counter for the ground poly. ring!
1231  const ring R = e->r; // no copy!
1232  assume( R->qideal == e->r->qideal );
1233  cf->extRing  = R;
[ec5ec8]1234
[73a9ffb]1235  /* propagate characteristic up so that it becomes
1236     directly accessible in cf: */
[7fee876]1237  cf->ch = R->cf->ch;
1238
[fba6f18]1239  #ifdef LDEBUG
[c28ecf]1240  p_Test((poly)naMinpoly, naRing);
[fba6f18]1241  #endif
[3c0498]1242
[fba6f18]1243  cf->cfGreaterZero  = naGreaterZero;
1244  cf->cfGreater      = naGreater;
1245  cf->cfEqual        = naEqual;
1246  cf->cfIsZero       = naIsZero;
1247  cf->cfIsOne        = naIsOne;
1248  cf->cfIsMOne       = naIsMOne;
1249  cf->cfInit         = naInit;
[3c0498]1250  cf->cfInit_bigint  = naInit_bigint;
[fba6f18]1251  cf->cfInt          = naInt;
1252  cf->cfNeg          = naNeg;
[ba2359]1253  cf->cfAdd          = naAdd;
[fba6f18]1254  cf->cfSub          = naSub;
[ba2359]1255  cf->cfMult         = naMult;
1256  cf->cfDiv          = naDiv;
1257  cf->cfExactDiv     = naDiv;
1258  cf->cfPower        = naPower;
1259  cf->cfCopy         = naCopy;
[ce1f78]1260
1261  cf->cfWriteLong        = naWriteLong;
1262
1263  if( rCanShortOut(naRing) )
1264    cf->cfWriteShort = naWriteShort;
1265  else
1266    cf->cfWriteShort = naWriteLong;
[3c0498]1267
[ba2359]1268  cf->cfRead         = naRead;
[fba6f18]1269  cf->cfDelete       = naDelete;
1270  cf->cfSetMap       = naSetMap;
1271  cf->cfGetDenom     = naGetDenom;
[0fb5991]1272  cf->cfGetNumerator = naGetNumerator;
[ba2359]1273  cf->cfRePart       = naCopy;
[fba6f18]1274  cf->cfImPart       = naImPart;
1275  cf->cfCoeffWrite   = naCoeffWrite;
[146c603]1276  cf->cfNormalize    = naNormalize;
[dbcf787]1277#ifdef LDEBUG
[fba6f18]1278  cf->cfDBTest       = naDBTest;
[dbcf787]1279#endif
[ba2359]1280  cf->cfGcd          = naGcd;
[36ef6e0]1281  //cf->cfLcm          = naLcm;
[ba2359]1282  cf->cfSize         = naSize;
1283  cf->nCoeffIsEqual  = naCoeffIsEqual;
1284  cf->cfInvers       = naInvers;
[dc79bd]1285  cf->cfIntDiv       = naDiv; // ???
[146c603]1286#ifdef HAVE_FACTORY
1287  cf->convFactoryNSingN=naConvFactoryNSingN;
1288  cf->convSingNFactoryN=naConvSingNFactoryN;
1289#endif
[48a41a]1290  cf->cfParDeg = naParDeg;
[3c0498]1291
[7fee876]1292  cf->iNumberOfParameters = rVar(R);
1293  cf->pParameterNames = R->names;
1294  cf->cfParameter = naParameter;
[3c0498]1295
[de88371]1296  if( nCoeff_is_Q(R->cf) )
[dc79bd]1297  {
[de88371]1298    cf->cfClearContent = naClearContent;
[dc79bd]1299    cf->cfClearDenominators = naClearDenominators;
1300  }
[de88371]1301 
[7fee876]1302  return FALSE;
[e82417]1303}
Note: See TracBrowser for help on using the repository browser.