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

spielwiese
Last change on this file since e852125 was e852125, checked in by Hans Schoenemann <hannes@…>, 13 years ago
fix naEqual (Tst/Old/agnes.tst)
  • Property mode set to 100644
File size: 22.1 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->minideal is not NULL but an ideal with at
17  *               least one non-zero generator which may be accessed by
18  *               cf->extRing->minideal->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 "ext_fields/algext.h"
47
48#ifdef LDEBUG
49#define naTest(a) naDBTest(a,__FILE__,__LINE__,cf)
50BOOLEAN  naDBTest(number a, const char *f, const int l, const coeffs r);
51#else
52#define naTest(a) (TRUE)
53#endif
54
55/// Our own type!
56static const n_coeffType ID = n_algExt;
57
58/* polynomial ring in which our numbers live */
59#define naRing cf->extRing
60
61/* coeffs object in which the coefficients of our numbers live;
62 * methods attached to naCoeffs may be used to compute with the
63 * coefficients of our numbers, e.g., use naCoeffs->nAdd to add
64 * coefficients of our numbers */
65#define naCoeffs cf->extRing->cf
66
67/* minimal polynomial */
68#define naMinpoly naRing->minideal->m[0]
69
70
71/// forward declarations
72BOOLEAN  naGreaterZero(number a, const coeffs cf); 
73BOOLEAN  naGreater(number a, number b, const coeffs cf);
74BOOLEAN  naEqual(number a, number b, const coeffs cf);
75BOOLEAN  naIsOne(number a, const coeffs cf);
76BOOLEAN  naIsMOne(number a, const coeffs cf);
77BOOLEAN  naIsZero(number a, const coeffs cf);
78number   naInit(int i, const coeffs cf);
79int      naInt(number &a, const coeffs cf);
80number   naNeg(number a, const coeffs cf);
81number   naInvers(number a, const coeffs cf);
82number   naAdd(number a, number b, const coeffs cf);
83number   naSub(number a, number b, const coeffs cf);
84number   naMult(number a, number b, const coeffs cf);
85number   naDiv(number a, number b, const coeffs cf);
86void     naPower(number a, int exp, number *b, const coeffs cf);
87number   naCopy(number a, const coeffs cf);
88void     naWrite(number &a, const coeffs cf);
89number   naRePart(number a, const coeffs cf);
90number   naImPart(number a, const coeffs cf);
91number   naGetDenom(number &a, const coeffs cf);
92number   naGetNumerator(number &a, const coeffs cf);
93number   naGcd(number a, number b, const coeffs cf);
94number   naLcm(number a, number b, const coeffs cf);
95int      naSize(number a, const coeffs cf);
96void     naDelete(number *a, const coeffs cf);
97void     naCoeffWrite(const coeffs cf);
98number   naIntDiv(number a, number b, const coeffs cf);
99const char * naRead(const char *s, number *a, const coeffs cf);
100static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param);
101
102#ifdef LDEBUG
103BOOLEAN naDBTest(number a, const char *f, const int l, const coeffs cf)
104{
105  assume(getCoeffType(cf) == ID);
106  if (a == NULL) return TRUE;
107  p_Test((poly)a, naRing);
108  assume(p_Totaldegree((poly)a, naRing) <= p_Totaldegree(naMinpoly, naRing));
109  return TRUE;
110}
111#endif
112
113void heuristicReduce(poly &p, poly reducer, const coeffs cf);
114void definiteReduce(poly &p, poly reducer, const coeffs cf);
115
116/* returns the bottom field in this field extension tower; if the tower
117   is flat, i.e., if there is no extension, then r itself is returned;
118   as a side-effect, the counter 'height' is filled with the height of
119   the extension tower (in case the tower is flat, 'height' is zero) */
120static coeffs nCoeff_bottom(const coeffs r, int &height)
121{
122  assume(r != NULL);
123  coeffs cf = r;
124  height = 0;
125  while (nCoeff_is_Extension(cf))
126  {
127    assume(cf->extRing != NULL); assume(cf->extRing->cf != NULL);
128    cf = cf->extRing->cf;
129    height++;
130  }
131  return cf;
132}
133
134BOOLEAN naIsZero(number a, const coeffs cf)
135{
136  naTest(a);
137  return (a == NULL);
138}
139
140void naDelete(number * a, const coeffs cf)
141{
142  if (*a == NULL) return;
143  poly aAsPoly = (poly)(*a);
144  p_Delete(&aAsPoly, naRing);
145  *a = NULL;
146}
147
148BOOLEAN naEqual(number a, number b, const coeffs cf)
149{
150  naTest(a); naTest(b);
151 
152  /// simple tests
153  if (a == b) return TRUE;
154  if ((a == NULL) && (b != NULL)) return FALSE;
155  if ((b == NULL) && (a != NULL)) return FALSE;
156
157  /// deg test
158  int aDeg = 0;
159  if (a != NULL) aDeg = p_Totaldegree((poly)a, naRing);
160  int bDeg = 0;
161  if (b != NULL) bDeg = p_Totaldegree((poly)b, naRing);
162  if (aDeg != bDeg) return FALSE;
163 
164  /// subtraction test
165  number c = naSub(a, b, cf);
166  BOOLEAN result = naIsZero(c, cf);
167  naDelete(&c, cf);
168  return result;
169}
170
171number naCopy(number a, const coeffs cf)
172{
173  naTest(a);
174  if (a == NULL) return NULL;
175  return (number)p_Copy((poly)a, naRing);
176}
177
178number naGetNumerator(number &a, const coeffs cf)
179{
180  return naCopy(a, cf);
181}
182
183number naGetDenom(number &a, const coeffs cf)
184{
185  naTest(a);
186  return naInit(1, cf);
187}
188
189BOOLEAN naIsOne(number a, const coeffs cf)
190{
191  naTest(a);
192  poly aAsPoly = (poly)a;
193  if (!p_IsConstant(aAsPoly, naRing)) return FALSE;
194  return n_IsOne(p_GetCoeff(aAsPoly, naRing), naCoeffs);
195}
196
197BOOLEAN naIsMOne(number a, const coeffs cf)
198{
199  naTest(a);
200  poly aAsPoly = (poly)a;
201  if (!p_IsConstant(aAsPoly, naRing)) return FALSE;
202  return n_IsMOne(p_GetCoeff(aAsPoly, naRing), naCoeffs);
203}
204
205/// this is in-place, modifies a
206number naNeg(number a, const coeffs cf)
207{
208  naTest(a);
209  if (a != NULL) a = (number)p_Neg((poly)a, naRing);
210  return a;
211}
212
213number naImPart(number a, const coeffs cf)
214{
215  naTest(a);
216  return NULL;
217}
218
219number naInit(int i, const coeffs cf)
220{
221  if (i == 0) return NULL;
222  else        return (number)p_ISet(i, naRing);
223}
224
225int naInt(number &a, const coeffs cf)
226{
227  naTest(a);
228  poly aAsPoly = (poly)a;
229  if (!p_IsConstant(aAsPoly, naRing)) return 0;
230  return n_Int(p_GetCoeff(aAsPoly, naRing), naCoeffs);
231}
232
233/* TRUE iff (a != 0 and (b == 0 or deg(a) > deg(b))) */
234BOOLEAN naGreater(number a, number b, const coeffs cf)
235{
236  naTest(a); naTest(b);
237  if (naIsZero(a, cf)) return FALSE;
238  if (naIsZero(b, cf)) return TRUE;
239  int aDeg = 0;
240  if (a != NULL) aDeg = p_Totaldegree((poly)a, naRing);
241  int bDeg = 0;
242  if (b != NULL) bDeg = p_Totaldegree((poly)b, naRing);
243  return (aDeg > bDeg);
244}
245
246/* TRUE iff a != 0 and (LC(a) > 0 or deg(a) > 0) */
247BOOLEAN naGreaterZero(number a, const coeffs cf)
248{
249  naTest(a);
250  if (a == NULL)                                            return FALSE;
251  if (n_GreaterZero(p_GetCoeff((poly)a, naRing), naCoeffs)) return TRUE;
252  if (p_Totaldegree((poly)a, naRing) > 0)                   return TRUE;
253  return FALSE;
254}
255
256void naCoeffWrite(const coeffs cf)
257{
258  assume( cf != NULL );
259 
260  const ring A = cf->extRing;
261 
262  assume( A != NULL );
263  assume( A->cf != NULL );
264   
265  n_CoeffWrite(A->cf);
266 
267//  rWrite(A);
268 
269  const int P = rVar(A);
270  assume( P > 0 );
271 
272  Print("//   %d parameter    : ", P);
273 
274  for (int nop=0; nop < P; nop ++)
275    Print("%s ", rRingVar(nop, A));
276 
277  const ideal I = A->minideal;
278
279  assume( I != NULL );
280  assume( IDELEMS(I) == 1 );
281 
282  PrintS("\n//   minpoly        : ("); p_Write0( I->m[0], A); PrintS(")\n");
283 
284/*
285  char *x = rRingVar(0, A);
286
287  Print("//   Coefficients live in the extension field K[%s]/<f(%s)>\n", x, x);
288  Print("//   with the minimal polynomial f(%s) = %s\n", x,
289        p_String(A->minideal->m[0], A));
290  PrintS("//   and K: ");
291*/
292}
293
294number naAdd(number a, number b, const coeffs cf)
295{
296  naTest(a); naTest(b);
297  if (a == NULL) return naCopy(b, cf);
298  if (b == NULL) return naCopy(a, cf);
299  poly aPlusB = p_Add_q(p_Copy((poly)a, naRing),
300                        p_Copy((poly)b, naRing), naRing);
301  definiteReduce(aPlusB, naMinpoly, cf);
302  return (number)aPlusB;
303}
304
305number naSub(number a, number b, const coeffs cf)
306{
307  naTest(a); naTest(b);
308  if (b == NULL) return naCopy(a, cf);
309  poly minusB = p_Neg(p_Copy((poly)b, naRing), naRing);
310  if (a == NULL) return (number)minusB;
311  poly aMinusB = p_Add_q(p_Copy((poly)a, naRing), minusB, naRing);
312  definiteReduce(aMinusB, naMinpoly, cf);
313  return (number)aMinusB;
314}
315
316number naMult(number a, number b, const coeffs cf)
317{
318  naTest(a); naTest(b);
319  if (a == NULL) return NULL;
320  if (b == NULL) return NULL;
321  poly aTimesB = p_Mult_q(p_Copy((poly)a, naRing),
322                          p_Copy((poly)b, naRing), naRing);
323  definiteReduce(aTimesB, naMinpoly, cf);
324  return (number)aTimesB;
325}
326
327number naDiv(number a, number b, const coeffs cf)
328{
329  naTest(a); naTest(b);
330  if (b == NULL) WerrorS(nDivBy0);
331  if (a == NULL) return NULL;
332  poly bInverse = (poly)naInvers(b, cf);
333  poly aDivB = p_Mult_q(p_Copy((poly)a, naRing), bInverse, naRing);
334  definiteReduce(aDivB, naMinpoly, cf);
335  return (number)aDivB;
336}
337
338/* 0^0 = 0;
339   for |exp| <= 7 compute power by a simple multiplication loop;
340   for |exp| >= 8 compute power along binary presentation of |exp|, e.g.
341      p^13 = p^1 * p^4 * p^8, where we utilise that
342      p^(2^(k+1)) = p^(2^k) * p^(2^k);
343   intermediate reduction modulo the minimal polynomial is controlled by
344   the in-place method heuristicReduce(poly, poly, coeffs); see there.
345*/
346void naPower(number a, int exp, number *b, const coeffs cf)
347{
348  naTest(a);
349 
350  /* special cases first */
351  if (a == NULL)
352  {
353    if (exp >= 0) *b = NULL;
354    else          WerrorS(nDivBy0);
355  }
356  else if (exp ==  0) { *b = naInit(1, cf); return; }
357  else if (exp ==  1) { *b = naCopy(a, cf); return; }
358  else if (exp == -1) { *b = naInvers(a, cf); return; }
359 
360  int expAbs = exp; if (expAbs < 0) expAbs = -expAbs;
361 
362  /* now compute a^expAbs */
363  poly pow; poly aAsPoly = (poly)a;
364  if (expAbs <= 7)
365  {
366    pow = p_Copy(aAsPoly, naRing);
367    for (int i = 2; i <= expAbs; i++)
368    {
369      pow = p_Mult_q(pow, p_Copy(aAsPoly, naRing), naRing);
370      heuristicReduce(pow, naMinpoly, cf);
371    }
372    definiteReduce(pow, naMinpoly, cf);
373  }
374  else
375  {
376    pow = p_ISet(1, naRing);
377    poly factor = p_Copy(aAsPoly, naRing);
378    while (expAbs != 0)
379    {
380      if (expAbs & 1)
381      {
382        pow = p_Mult_q(pow, p_Copy(factor, naRing), naRing);
383        heuristicReduce(pow, naMinpoly, cf);
384      }
385      expAbs = expAbs / 2;
386      if (expAbs != 0)
387      {
388        factor = p_Mult_q(factor, factor, naRing);
389        heuristicReduce(factor, naMinpoly, cf);
390      }
391    }
392    p_Delete(&factor, naRing);
393    definiteReduce(pow, naMinpoly, cf);
394  }
395 
396  /* invert if original exponent was negative */
397  number n = (number)pow;
398  if (exp < 0)
399  {
400    number m = naInvers(n, cf);
401    naDelete(&n, cf);
402    n = m;
403  }
404  *b = n;
405}
406
407/* may reduce p modulo the reducer by calling definiteReduce;
408   the decision is made based on the following heuristic
409   (which should also only be changed here in this method):
410      if (deg(p) > 10*deg(reducer) then perform reduction;
411   modifies p */
412void heuristicReduce(poly &p, poly reducer, const coeffs cf)
413{
414  #ifdef LDEBUG
415  p_Test((poly)p, naRing);
416  p_Test((poly)reducer, naRing);
417  #endif
418  if (p_Totaldegree(p, naRing) > 10 * p_Totaldegree(reducer, naRing))
419    definiteReduce(p, reducer, cf);
420}
421
422void naWrite(number &a, const coeffs cf)
423{
424  naTest(a);
425  if (a == NULL)
426    StringAppendS("0");
427  else
428  {
429    poly aAsPoly = (poly)a;
430    /* basically, just write aAsPoly using p_Write,
431       but use brackets around the output, if a is not
432       a constant living in naCoeffs = cf->extRing->cf */
433    BOOLEAN useBrackets = !(p_IsConstant(aAsPoly, naRing));
434    if (useBrackets) StringAppendS("(");
435    p_String0(aAsPoly, naRing, naRing);
436    if (useBrackets) StringAppendS(")");
437  }
438}
439
440const char * naRead(const char *s, number *a, const coeffs cf)
441{
442  poly aAsPoly;
443  const char * result = p_Read(s, aAsPoly, naRing);
444  *a = (number)aAsPoly;
445  return result;
446}
447
448/* implemented by the rule lcm(a, b) = a * b / gcd(a, b) */
449number naLcm(number a, number b, const coeffs cf)
450{
451  naTest(a); naTest(b);
452  if (a == NULL) return NULL;
453  if (b == NULL) return NULL;
454  number theProduct = (number)p_Mult_q(p_Copy((poly)a, naRing),
455                                       p_Copy((poly)b, naRing), naRing);
456  /* note that theProduct needs not be reduced w.r.t. naMinpoly;
457     but the final division will take care of the necessary reduction */
458  number theGcd = naGcd(a, b, cf);
459  return naDiv(theProduct, theGcd, cf);
460}
461
462/* expects *param to be castable to AlgExtInfo */
463static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param)
464{
465  if (ID != n) return FALSE;
466  AlgExtInfo *e = (AlgExtInfo *)param;
467  /* for extension coefficient fields we expect the underlying
468     polynomial rings to be IDENTICAL, i.e. the SAME OBJECT;
469     this expectation is based on the assumption that we have properly
470     registered cf and perform reference counting rather than creating
471     multiple copies of the same coefficient field/domain/ring */
472  return (naRing == e->r);
473  /* (Note that then also the minimal ideals will necessarily be
474     the same, as they are attached to the ring.) */
475}
476
477int naSize(number a, const coeffs cf)
478{
479  if (a == NULL) return -1;
480  /* this has been taken from the old implementation of field extensions,
481     where we computed the sum of the degree and the number of terms in
482     (poly)a; so we leave it at that, for the time being;
483     maybe, the number of terms alone is a better measure? */
484  poly aAsPoly = (poly)a;
485  int theDegree = 0; int noOfTerms = 0;
486  while (aAsPoly != NULL)
487  {
488    noOfTerms++;
489    int d = p_GetExp(aAsPoly, 1, naRing);
490    if (d > theDegree) theDegree = d;
491    pIter(aAsPoly);
492  }
493  return theDegree + noOfTerms;
494}
495
496/* performs polynomial division and overrides p by the remainder
497   of division of p by the reducer;
498   modifies p */
499void definiteReduce(poly &p, poly reducer, const coeffs cf)
500{
501  #ifdef LDEBUG
502  p_Test((poly)p, naRing);
503  p_Test((poly)reducer, naRing);
504  #endif
505  p_PolyDiv(p, reducer, FALSE, naRing);
506}
507
508/* IMPORTANT NOTE: Since an algebraic field extension is again a field,
509                   the gcd of two elements is not very interesting. (It
510                   is actually any unit in the field, i.e., any non-
511                   zero element.) Note that the below method does not operate
512                   in this strong sense but rather computes the gcd of
513                   two given elements in the underlying polynomial ring. */
514number naGcd(number a, number b, const coeffs cf)
515{
516  naTest(a); naTest(b);
517  if ((a == NULL) && (b == NULL)) WerrorS(nDivBy0);
518  return (number)p_Gcd((poly)a, (poly)b, naRing);
519}
520
521number naInvers(number a, const coeffs cf)
522{
523  naTest(a);
524  if (a == NULL) WerrorS(nDivBy0);
525  poly aFactor = NULL; poly mFactor = NULL;
526  poly theGcd = p_ExtGcd((poly)a, aFactor, naMinpoly, mFactor, naRing);
527  naTest((number)theGcd); naTest((number)aFactor); naTest((number)mFactor);
528  /* the gcd must be 1 since naMinpoly is irreducible and a != NULL: */
529  assume(naIsOne((number)theGcd, cf));     
530  p_Delete(&theGcd, naRing);
531  p_Delete(&mFactor, naRing);
532  return (number)(aFactor);
533}
534
535/* assumes that src = Q, dst = Q(a) */
536number naMap00(number a, const coeffs src, const coeffs dst)
537{
538  if (n_IsZero(a, src)) return NULL;
539  assume(src == dst->extRing->cf);
540  poly result = p_One(dst->extRing);
541  p_SetCoeff(result, naCopy(a, src), dst->extRing);
542  return (number)result;
543}
544
545/* assumes that src = Z/p, dst = Q(a) */
546number naMapP0(number a, const coeffs src, const coeffs dst)
547{
548  if (n_IsZero(a, src)) return NULL;
549  /* mapping via intermediate int: */
550  int n = n_Int(a, src);
551  number q = n_Init(n, dst->extRing->cf);
552  poly result = p_One(dst->extRing);
553  p_SetCoeff(result, q, dst->extRing);
554  return (number)result;
555}
556
557/* assumes that either src = Q(a), dst = Q(a), or
558                       src = Z/p(a), dst = Z/p(a)     */
559number naCopyMap(number a, const coeffs src, const coeffs dst)
560{
561  return naCopy(a, dst);
562}
563
564/* assumes that src = Q, dst = Z/p(a) */
565number naMap0P(number a, const coeffs src, const coeffs dst)
566{
567  if (n_IsZero(a, src)) return NULL;
568  int p = rChar(dst->extRing);
569  int n = nlModP(a, p, src);
570  number q = n_Init(n, dst->extRing->cf);
571  poly result = p_One(dst->extRing);
572  p_SetCoeff(result, q, dst->extRing);
573  return (number)result;
574}
575
576/* assumes that src = Z/p, dst = Z/p(a) */
577number naMapPP(number a, const coeffs src, const coeffs dst)
578{
579  if (n_IsZero(a, src)) return NULL;
580  assume(src == dst->extRing->cf);
581  poly result = p_One(dst->extRing);
582  p_SetCoeff(result, naCopy(a, src), dst->extRing);
583  return (number)result;
584}
585
586/* assumes that src = Z/u, dst = Z/p(a), where u != p */
587number naMapUP(number a, const coeffs src, const coeffs dst)
588{
589  if (n_IsZero(a, src)) return NULL;
590  /* mapping via intermediate int: */
591  int n = n_Int(a, src);
592  number q = n_Init(n, dst->extRing->cf);
593  poly result = p_One(dst->extRing);
594  p_SetCoeff(result, q, dst->extRing);
595  return (number)result;
596}
597
598nMapFunc naSetMap(const coeffs src, const coeffs dst)
599{
600  /* dst is expected to be an algebraic field extension */
601  assume(getCoeffType(dst) == ID);
602 
603  int h = 0; /* the height of the extension tower given by dst */
604  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
605 
606  /* for the time being, we only provide maps if h = 1 and if b is Q or
607     some field Z/pZ: */
608  if (h != 1) return NULL;
609  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
610 
611  if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
612    return naMap00;                                      /// Q     -->  Q(a)
613 
614  if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
615    return naMapP0;                                      /// Z/p   -->  Q(a)
616 
617  if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
618    return naMap0P;                                      /// Q      --> Z/p(a)
619 
620  if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
621  {
622    if (src->ch == dst->ch) return naMapPP;              /// Z/p    --> Z/p(a)
623    else return naMapUP;                                 /// Z/u    --> Z/p(a)
624  }
625 
626  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
627  if (h != 1) return NULL;
628  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
629 
630  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
631  {
632    if (strcmp(rRingVar(0, src->extRing),
633               rRingVar(0, dst->extRing)) == 0)
634      return naCopyMap;                                  /// Q(a)   --> Q(a)
635    else
636      return NULL;                                       /// Q(b)   --> Q(a)
637  }
638 
639  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
640  {
641    if (strcmp(rParameter(src->extRing)[0],
642               rParameter(dst->extRing)[0]) == 0)
643      return naCopyMap;                                  /// Z/p(a) --> Z/p(a)
644    else
645      return NULL;                                       /// Z/p(b) --> Z/p(a)
646  }
647 
648  return NULL;                                           /// default
649}
650
651BOOLEAN naInitChar(coeffs cf, void * infoStruct)
652{ 
653  assume( infoStruct != NULL );
654
655  AlgExtInfo *e = (AlgExtInfo *)infoStruct;
656  /// first check whether cf->extRing != NULL and delete old ring???
657
658  assume(e->r                     != NULL);      // extRing;
659  assume(e->r->cf                 != NULL);      // extRing->cf;
660  assume((e->i          != NULL) &&    // minideal has one
661         (IDELEMS(e->i) != 0)    &&    // non-zero generator
662         (e->i->m[0]    != NULL)    ); // at m[0];
663
664  assume( e->r->minideal == NULL );
665
666  assume( cf != NULL );
667  assume(getCoeffType(cf) == ID);                     // coeff type;
668 
669  cf->extRing           = e->r;
670  cf->extRing->ref ++; // increase the ref.counter for the ground poly. ring!
671
672  cf->extRing->minideal = e->i; // make a copy?
673
674  /* propagate characteristic up so that it becomes
675     directly accessible in cf: */
676  cf->ch = cf->extRing->cf->ch;
677 
678  #ifdef LDEBUG
679  p_Test((poly)naMinpoly, naRing);
680  #endif
681 
682  cf->cfGreaterZero  = naGreaterZero;
683  cf->cfGreater      = naGreater;
684  cf->cfEqual        = naEqual;
685  cf->cfIsZero       = naIsZero;
686  cf->cfIsOne        = naIsOne;
687  cf->cfIsMOne       = naIsMOne;
688  cf->cfInit         = naInit;
689  cf->cfInt          = naInt;
690  cf->cfNeg          = naNeg;
691  cf->cfAdd          = naAdd;
692  cf->cfSub          = naSub;
693  cf->cfMult         = naMult;
694  cf->cfDiv          = naDiv;
695  cf->cfExactDiv     = naDiv;
696  cf->cfPower        = naPower;
697  cf->cfCopy         = naCopy;
698  cf->cfWrite        = naWrite;
699  cf->cfRead         = naRead;
700  cf->cfDelete       = naDelete;
701  cf->cfSetMap       = naSetMap;
702  cf->cfGetDenom     = naGetDenom;
703  cf->cfGetNumerator = naGetNumerator;
704  cf->cfRePart       = naCopy;
705  cf->cfImPart       = naImPart;
706  cf->cfCoeffWrite   = naCoeffWrite;
707#ifdef LDEBUG
708  cf->cfDBTest       = naDBTest;
709#endif
710  cf->cfGcd          = naGcd;
711  cf->cfLcm          = naLcm;
712  cf->cfSize         = naSize;
713  cf->nCoeffIsEqual  = naCoeffIsEqual;
714  cf->cfInvers       = naInvers;
715  cf->cfIntDiv       = naDiv;
716 
717  return FALSE;
718}
719
720
721number naParam(const short iParameter, const coeffs cf)
722{
723  assume(getCoeffType(cf) == ID);
724 
725  const ring R = cf->extRing;
726  assume( R != NULL ); 
727  assume( 0 < iParameter && iParameter <= rVar(R) );
728 
729  poly p = p_One(R); p_SetExp(p, iParameter, 1, R); p_Setm(p, R);
730 
731  return (number) p; 
732}
733
734
735/// if m == var(i)/1 => return i,
736int naIsParam(number m, const coeffs cf)
737{
738  assume(getCoeffType(cf) == ID);
739
740  const ring R = cf->extRing;
741  assume( R != NULL ); 
742
743  return p_Var( (poly)m, R ); 
744}
Note: See TracBrowser for help on using the repository browser.