# source:git/libpolys/polys/ext_fields/algext.cc@03f7b5

spielwiese
Last change on this file since 03f7b5 was 03f7b5, checked in by Oleksandr Motsak <motsak@…>, 12 years ago
ADD: detailed printing vs typing for coeff. domains (mostly - minpoly related)
• Property mode set to `100644`
File size: 22.5 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 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
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
66 * coefficients of our numbers */
67#define naCoeffs cf->extRing->cf
68
69/* minimal polynomial */
70#define naMinpoly naRing->minideal->m
71
72/// forward declarations
73BOOLEAN  naGreaterZero(number a, const coeffs cf);
74BOOLEAN  naGreater(number a, number b, const coeffs cf);
75BOOLEAN  naEqual(number a, number b, const coeffs cf);
76BOOLEAN  naIsOne(number a, const coeffs cf);
77BOOLEAN  naIsMOne(number a, const coeffs cf);
78BOOLEAN  naIsZero(number a, const coeffs cf);
79number   naInit(int i, const coeffs cf);
80int      naInt(number &a, const coeffs cf);
81number   naNeg(number a, const coeffs cf);
82number   naInvers(number a, const coeffs cf);
83number   naAdd(number a, number b, const coeffs cf);
84number   naSub(number a, number b, const coeffs cf);
85number   naMult(number a, number b, const coeffs cf);
86number   naDiv(number a, number b, const coeffs cf);
87void     naPower(number a, int exp, number *b, const coeffs cf);
88number   naCopy(number a, const coeffs cf);
89void     naWrite(number &a, const coeffs cf);
90number   naRePart(number a, const coeffs cf);
91number   naImPart(number a, const coeffs cf);
92number   naGetDenom(number &a, const coeffs cf);
93number   naGetNumerator(number &a, const coeffs cf);
94number   naGcd(number a, number b, const coeffs cf);
95//number   naLcm(number a, number b, const coeffs cf);
96int      naSize(number a, const coeffs cf);
97void     naDelete(number *a, const coeffs cf);
98void     naCoeffWrite(const coeffs cf, BOOLEAN details);
99number   naIntDiv(number a, number b, const coeffs cf);
100const char * naRead(const char *s, number *a, const coeffs cf);
101
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
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);
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;
242  if (a != NULL) aDeg = p_Totaldegree((poly)a, naRing);
243  int bDeg = 0;
244  if (b != NULL) bDeg = p_Totaldegree((poly)b, naRing);
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, BOOLEAN details)
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, details);
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  PrintLn();
280
281  const ideal I = A->minideal;
282
283  assume( I != NULL );
284  assume( IDELEMS(I) == 1 );
285
286
287  if ( details )
288  {
289    PrintS("//   minpoly        : (");
290    p_Write0( I->m, A);
291    PrintS(")");
292  }
293  else
294    PrintS("//   minpoly        : ...");
295
296  PrintLn();
297
298/*
299  char *x = rRingVar(0, A);
300
301  Print("//   Coefficients live in the extension field K[%s]/<f(%s)>\n", x, x);
302  Print("//   with the minimal polynomial f(%s) = %s\n", x,
303        p_String(A->minideal->m, A));
304  PrintS("//   and K: ");
305*/
306}
307
308number naAdd(number a, number b, const coeffs cf)
309{
310  naTest(a); naTest(b);
311  if (a == NULL) return naCopy(b, cf);
312  if (b == NULL) return naCopy(a, cf);
313  poly aPlusB = p_Add_q(p_Copy((poly)a, naRing),
314                        p_Copy((poly)b, naRing), naRing);
315  definiteReduce(aPlusB, naMinpoly, cf);
316  return (number)aPlusB;
317}
318
319number naSub(number a, number b, const coeffs cf)
320{
321  naTest(a); naTest(b);
322  if (b == NULL) return naCopy(a, cf);
323  poly minusB = p_Neg(p_Copy((poly)b, naRing), naRing);
324  if (a == NULL) return (number)minusB;
325  poly aMinusB = p_Add_q(p_Copy((poly)a, naRing), minusB, naRing);
326  definiteReduce(aMinusB, naMinpoly, cf);
327  return (number)aMinusB;
328}
329
330number naMult(number a, number b, const coeffs cf)
331{
332  naTest(a); naTest(b);
333  if (a == NULL) return NULL;
334  if (b == NULL) return NULL;
335  poly aTimesB = p_Mult_q(p_Copy((poly)a, naRing),
336                          p_Copy((poly)b, naRing), naRing);
337  definiteReduce(aTimesB, naMinpoly, cf);
338  return (number)aTimesB;
339}
340
341number naDiv(number a, number b, const coeffs cf)
342{
343  naTest(a); naTest(b);
344  if (b == NULL) WerrorS(nDivBy0);
345  if (a == NULL) return NULL;
346  poly bInverse = (poly)naInvers(b, cf);
347  poly aDivB = p_Mult_q(p_Copy((poly)a, naRing), bInverse, naRing);
350}
351
352/* 0^0 = 0;
353   for |exp| <= 7 compute power by a simple multiplication loop;
354   for |exp| >= 8 compute power along binary presentation of |exp|, e.g.
355      p^13 = p^1 * p^4 * p^8, where we utilise that
356      p^(2^(k+1)) = p^(2^k) * p^(2^k);
357   intermediate reduction modulo the minimal polynomial is controlled by
358   the in-place method heuristicReduce(poly, poly, coeffs); see there.
359*/
360void naPower(number a, int exp, number *b, const coeffs cf)
361{
362  naTest(a);
363
364  /* special cases first */
365  if (a == NULL)
366  {
367    if (exp >= 0) *b = NULL;
368    else          WerrorS(nDivBy0);
369  }
370  else if (exp ==  0) { *b = naInit(1, cf); return; }
371  else if (exp ==  1) { *b = naCopy(a, cf); return; }
372  else if (exp == -1) { *b = naInvers(a, cf); return; }
373
374  int expAbs = exp; if (expAbs < 0) expAbs = -expAbs;
375
376  /* now compute a^expAbs */
377  poly pow; poly aAsPoly = (poly)a;
378  if (expAbs <= 7)
379  {
380    pow = p_Copy(aAsPoly, naRing);
381    for (int i = 2; i <= expAbs; i++)
382    {
383      pow = p_Mult_q(pow, p_Copy(aAsPoly, naRing), naRing);
384      heuristicReduce(pow, naMinpoly, cf);
385    }
386    definiteReduce(pow, naMinpoly, cf);
387  }
388  else
389  {
390    pow = p_ISet(1, naRing);
391    poly factor = p_Copy(aAsPoly, naRing);
392    while (expAbs != 0)
393    {
394      if (expAbs & 1)
395      {
396        pow = p_Mult_q(pow, p_Copy(factor, naRing), naRing);
397        heuristicReduce(pow, naMinpoly, cf);
398      }
399      expAbs = expAbs / 2;
400      if (expAbs != 0)
401      {
402        factor = p_Mult_q(factor, p_Copy(factor, naRing), naRing);
403        heuristicReduce(factor, naMinpoly, cf);
404      }
405    }
406    p_Delete(&factor, naRing);
407    definiteReduce(pow, naMinpoly, cf);
408  }
409
410  /* invert if original exponent was negative */
411  number n = (number)pow;
412  if (exp < 0)
413  {
414    number m = naInvers(n, cf);
416    n = m;
417  }
418  *b = n;
419}
420
421/* may reduce p modulo the reducer by calling definiteReduce;
422   the decision is made based on the following heuristic
423   (which should also only be changed here in this method):
424      if (deg(p) > 10*deg(reducer) then perform reduction;
425   modifies p */
426void heuristicReduce(poly &p, poly reducer, const coeffs cf)
427{
428  #ifdef LDEBUG
429  p_Test((poly)p, naRing);
430  p_Test((poly)reducer, naRing);
431  #endif
432  if (p_Totaldegree(p, naRing) > 10 * p_Totaldegree(reducer, naRing))
433    definiteReduce(p, reducer, cf);
434}
435
436void naWrite(number &a, const coeffs cf)
437{
438  naTest(a);
439  if (a == NULL)
440    StringAppendS("0");
441  else
442  {
443    poly aAsPoly = (poly)a;
444    /* basically, just write aAsPoly using p_Write,
445       but use brackets around the output, if a is not
446       a constant living in naCoeffs = cf->extRing->cf */
447    BOOLEAN useBrackets = !(p_IsConstant(aAsPoly, naRing));
448    if (useBrackets) StringAppendS("(");
449    p_String0(aAsPoly, naRing, naRing);
450    if (useBrackets) StringAppendS(")");
451  }
452}
453
454const char * naRead(const char *s, number *a, const coeffs cf)
455{
456  poly aAsPoly;
457  const char * result = p_Read(s, aAsPoly, naRing);
458  *a = (number)aAsPoly;
459  return result;
460}
461
462#if 0
463/* implemented by the rule lcm(a, b) = a * b / gcd(a, b) */
464number naLcm(number a, number b, const coeffs cf)
465{
466  naTest(a); naTest(b);
467  if (a == NULL) return NULL;
468  if (b == NULL) return NULL;
469  number theProduct = (number)p_Mult_q(p_Copy((poly)a, naRing),
470                                       p_Copy((poly)b, naRing), naRing);
471  /* note that theProduct needs not be reduced w.r.t. naMinpoly;
472     but the final division will take care of the necessary reduction */
473  number theGcd = naGcd(a, b, cf);
475}
476#endif
477
478/* expects *param to be castable to AlgExtInfo */
479static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param)
480{
481  if (ID != n) return FALSE;
482  AlgExtInfo *e = (AlgExtInfo *)param;
483  /* for extension coefficient fields we expect the underlying
484     polynomial rings to be IDENTICAL, i.e. the SAME OBJECT;
485     this expectation is based on the assumption that we have properly
486     registered cf and perform reference counting rather than creating
487     multiple copies of the same coefficient field/domain/ring */
488  return (naRing == e->r);
489  /* (Note that then also the minimal ideals will necessarily be
490     the same, as they are attached to the ring.) */
491}
492
493int naSize(number a, const coeffs cf)
494{
495  if (a == NULL) return -1;
496  /* this has been taken from the old implementation of field extensions,
497     where we computed the sum of the degree and the number of terms in
498     (poly)a; so we leave it at that, for the time being;
499     maybe, the number of terms alone is a better measure? */
500  poly aAsPoly = (poly)a;
501  int theDegree = 0; int noOfTerms = 0;
502  while (aAsPoly != NULL)
503  {
504    noOfTerms++;
505    int d = p_GetExp(aAsPoly, 1, naRing);
506    if (d > theDegree) theDegree = d;
507    pIter(aAsPoly);
508  }
509  return theDegree + noOfTerms;
510}
511
512/* performs polynomial division and overrides p by the remainder
513   of division of p by the reducer;
514   modifies p */
515void definiteReduce(poly &p, poly reducer, const coeffs cf)
516{
517  #ifdef LDEBUG
518  p_Test((poly)p, naRing);
519  p_Test((poly)reducer, naRing);
520  #endif
521  p_PolyDiv(p, reducer, FALSE, naRing);
522}
523
524/* IMPORTANT NOTE: Since an algebraic field extension is again a field,
525                   the gcd of two elements is not very interesting. (It
526                   is actually any unit in the field, i.e., any non-
527                   zero element.) Note that the below method does not operate
528                   in this strong sense but rather computes the gcd of
529                   two given elements in the underlying polynomial ring. */
530number naGcd(number a, number b, const coeffs cf)
531{
532  naTest(a); naTest(b);
533  if ((a == NULL) && (b == NULL)) WerrorS(nDivBy0);
534  return (number)p_Gcd((poly)a, (poly)b, naRing);
535}
536
537number naInvers(number a, const coeffs cf)
538{
539  naTest(a);
540  if (a == NULL) WerrorS(nDivBy0);
541  poly aFactor = NULL; poly mFactor = NULL;
542  poly theGcd = p_ExtGcd((poly)a, aFactor, naMinpoly, mFactor, naRing);
543  naTest((number)theGcd); naTest((number)aFactor); naTest((number)mFactor);
544  /* the gcd must be 1 since naMinpoly is irreducible and a != NULL: */
545  assume(naIsOne((number)theGcd, cf));
546  p_Delete(&theGcd, naRing);
547  p_Delete(&mFactor, naRing);
548  return (number)(aFactor);
549}
550
551/* assumes that src = Q, dst = Q(a) */
552number naMap00(number a, const coeffs src, const coeffs dst)
553{
554  if (n_IsZero(a, src)) return NULL;
555  assume(src == dst->extRing->cf);
556  poly result = p_One(dst->extRing);
557  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
558  return (number)result;
559}
560
561/* assumes that src = Z/p, dst = Q(a) */
562number naMapP0(number a, const coeffs src, const coeffs dst)
563{
564  if (n_IsZero(a, src)) return NULL;
565  /* mapping via intermediate int: */
566  int n = n_Int(a, src);
567  number q = n_Init(n, dst->extRing->cf);
568  poly result = p_One(dst->extRing);
569  p_SetCoeff(result, q, dst->extRing);
570  return (number)result;
571}
572
573#if 0
574/* assumes that either src = Q(a), dst = Q(a), or
575                       src = Z/p(a), dst = Z/p(a)     */
576number naCopyMap(number a, const coeffs src, const coeffs dst)
577{
578  return naCopy(a, dst);
579}
580#endif
581
582number naCopyExt(number a, const coeffs src, const coeffs dst)
583{
584  fraction fa=(fraction)a;
585  return (number)p_Copy(NUM(fa),src->extRing);
586}
587
588/* assumes that src = Q, dst = Z/p(a) */
589number naMap0P(number a, const coeffs src, const coeffs dst)
590{
591  if (n_IsZero(a, src)) return NULL;
592  int p = rChar(dst->extRing);
593  int n = nlModP(a, p, src);
594  number q = n_Init(n, dst->extRing->cf);
595  poly result = p_One(dst->extRing);
596  p_SetCoeff(result, q, dst->extRing);
597  return (number)result;
598}
599
600/* assumes that src = Z/p, dst = Z/p(a) */
601number naMapPP(number a, const coeffs src, const coeffs dst)
602{
603  if (n_IsZero(a, src)) return NULL;
604  assume(src == dst->extRing->cf);
605  poly result = p_One(dst->extRing);
606  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
607  return (number)result;
608}
609
610/* assumes that src = Z/u, dst = Z/p(a), where u != p */
611number naMapUP(number a, const coeffs src, const coeffs dst)
612{
613  if (n_IsZero(a, src)) return NULL;
614  /* mapping via intermediate int: */
615  int n = n_Int(a, src);
616  number q = n_Init(n, dst->extRing->cf);
617  poly result = p_One(dst->extRing);
618  p_SetCoeff(result, q, dst->extRing);
619  return (number)result;
620}
621
622nMapFunc naSetMap(const coeffs src, const coeffs dst)
623{
624  /* dst is expected to be an algebraic field extension */
625  assume(getCoeffType(dst) == ID);
626
627  int h = 0; /* the height of the extension tower given by dst */
628  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
629  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
630
631  /* for the time being, we only provide maps if h = 1 and if b is Q or
632     some field Z/pZ: */
633  if (h==0)
634  {
635    if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
636      return naMap00;                            /// Q     -->  Q(a)
637    if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
638      return naMapP0;                            /// Z/p   -->  Q(a)
639    if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
640      return naMap0P;                            /// Q      --> Z/p(a)
641    if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
642    {
643      if (src->ch == dst->ch) return naMapPP;    /// Z/p    --> Z/p(a)
644      else return naMapUP;                       /// Z/u    --> Z/p(a)
645    }
646  }
647  if (h != 1) return NULL;
648  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
649  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
650
651  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
652  {
653    if (strcmp(rRingVar(0, src->extRing),
654               rRingVar(0, dst->extRing)) == 0)
655    {
656      if (src->type==n_algExt)
657         return ndCopyMap; // naCopyMap;         /// Q(a)   --> Q(a)
658      else
659         return naCopyExt;
660    }
661    else
662      return NULL;                               /// Q(b)   --> Q(a)
663  }
664
665  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
666  {
667    if (strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0)
668    {
669      if (src->type==n_algExt)
670        return ndCopyMap; // naCopyMap;          /// Z/p(a) --> Z/p(a)
671      else
672         return naCopyExt;
673    }
674    else
675      return NULL;                               /// Z/p(b) --> Z/p(a)
676  }
677
678  return NULL;                                           /// default
679}
680
681BOOLEAN naInitChar(coeffs cf, void * infoStruct)
682{
683  assume( infoStruct != NULL );
684
685  AlgExtInfo *e = (AlgExtInfo *)infoStruct;
686  /// first check whether cf->extRing != NULL and delete old ring???
687
688  assume(e->r                     != NULL);      // extRing;
689  assume(e->r->cf                 != NULL);      // extRing->cf;
690  assume((e->i          != NULL) &&    // minideal has one
691         (IDELEMS(e->i) != 0)    &&    // non-zero generator
692         (e->i->m    != NULL)    ); // at m;
693
694  assume( e->r->minideal == NULL );
695
696  assume( cf != NULL );
697  assume(getCoeffType(cf) == ID);                     // coeff type;
698
699  cf->extRing           = e->r;
700  cf->extRing->ref ++; // increase the ref.counter for the ground poly. ring!
701
702  cf->extRing->minideal = e->i; // make a copy?
703
704  /* propagate characteristic up so that it becomes
705     directly accessible in cf: */
706  cf->ch = cf->extRing->cf->ch;
707
708  #ifdef LDEBUG
709  p_Test((poly)naMinpoly, naRing);
710  #endif
711
712  cf->cfGreaterZero  = naGreaterZero;
713  cf->cfGreater      = naGreater;
714  cf->cfEqual        = naEqual;
715  cf->cfIsZero       = naIsZero;
716  cf->cfIsOne        = naIsOne;
717  cf->cfIsMOne       = naIsMOne;
718  cf->cfInit         = naInit;
719  cf->cfInt          = naInt;
720  cf->cfNeg          = naNeg;
722  cf->cfSub          = naSub;
723  cf->cfMult         = naMult;
726  cf->cfPower        = naPower;
727  cf->cfCopy         = naCopy;
728  cf->cfWrite        = naWrite;
731  cf->cfSetMap       = naSetMap;
732  cf->cfGetDenom     = naGetDenom;
733  cf->cfGetNumerator = naGetNumerator;
734  cf->cfRePart       = naCopy;
735  cf->cfImPart       = naImPart;
736  cf->cfCoeffWrite   = naCoeffWrite;
737#ifdef LDEBUG
739#endif
740  cf->cfGcd          = naGcd;
741  //cf->cfLcm          = naLcm;
742  cf->cfSize         = naSize;
743  cf->nCoeffIsEqual  = naCoeffIsEqual;
744  cf->cfInvers       = naInvers;
746
747  return FALSE;
748}
749
750
751number naParam(const short iParameter, const coeffs cf)
752{
753  assume(getCoeffType(cf) == ID);
754
755  const ring R = cf->extRing;
756  assume( R != NULL );
757  assume( 0 < iParameter && iParameter <= rVar(R) );
758
759  poly p = p_One(R); p_SetExp(p, iParameter, 1, R); p_Setm(p, R);
760
761  return (number) p;
762}
763
764
765/// if m == var(i)/1 => return i,
766int naIsParam(number m, const coeffs cf)
767{
768  assume(getCoeffType(cf) == ID);
769
770  const ring R = cf->extRing;
771  assume( R != NULL );
772
773  return p_Var( (poly)m, R );
774}
Note: See TracBrowser for help on using the repository browser.