source: git/libpolys/polys/ext_fields/algext.cc @ 331fd0

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