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

spielwiese
Last change on this file since c14846c was c14846c, checked in by Hans Schoenemann <hannes@…>, 12 years ago
fix: n?SetMap should return ndCopyMap for equal coeffs
• 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 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
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
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)
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, 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, 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);
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);
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);
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#if 0
560/* assumes that either src = Q(a), dst = Q(a), or
561                       src = Z/p(a), dst = Z/p(a)     */
562number naCopyMap(number a, const coeffs src, const coeffs dst)
563{
564  return naCopy(a, dst);
565}
566#endif
567
568number naCopyExt(number a, const coeffs src, const coeffs dst)
569{
570  fraction fa=(fraction)a;
571  return (number)p_Copy(NUM(fa),src->extRing);
572}
573
574/* assumes that src = Q, dst = Z/p(a) */
575number naMap0P(number a, const coeffs src, const coeffs dst)
576{
577  if (n_IsZero(a, src)) return NULL;
578  int p = rChar(dst->extRing);
579  int n = nlModP(a, p, src);
580  number q = n_Init(n, dst->extRing->cf);
581  poly result = p_One(dst->extRing);
582  p_SetCoeff(result, q, dst->extRing);
583  return (number)result;
584}
585
586/* assumes that src = Z/p, dst = Z/p(a) */
587number naMapPP(number a, const coeffs src, const coeffs dst)
588{
589  if (n_IsZero(a, src)) return NULL;
590  assume(src == dst->extRing->cf);
591  poly result = p_One(dst->extRing);
592  p_SetCoeff(result, naCopy(a, src), dst->extRing);
593  return (number)result;
594}
595
596/* assumes that src = Z/u, dst = Z/p(a), where u != p */
597number naMapUP(number a, const coeffs src, const coeffs dst)
598{
599  if (n_IsZero(a, src)) return NULL;
600  /* mapping via intermediate int: */
601  int n = n_Int(a, src);
602  number q = n_Init(n, dst->extRing->cf);
603  poly result = p_One(dst->extRing);
604  p_SetCoeff(result, q, dst->extRing);
605  return (number)result;
606}
607
608nMapFunc naSetMap(const coeffs src, const coeffs dst)
609{
610  /* dst is expected to be an algebraic field extension */
611  assume(getCoeffType(dst) == ID);
612
613  int h = 0; /* the height of the extension tower given by dst */
614  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
615  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
616
617  /* for the time being, we only provide maps if h = 1 and if b is Q or
618     some field Z/pZ: */
619  if (h==0)
620  {
621    if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
622      return naMap00;                            /// Q     -->  Q(a)
623    if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
624      return naMapP0;                            /// Z/p   -->  Q(a)
625    if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
626      return naMap0P;                            /// Q      --> Z/p(a)
627    if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
628    {
629      if (src->ch == dst->ch) return naMapPP;    /// Z/p    --> Z/p(a)
630      else return naMapUP;                       /// Z/u    --> Z/p(a)
631    }
632  }
633  if (h != 1) return NULL;
634  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
635  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
636
637  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
638  {
639    if (strcmp(rRingVar(0, src->extRing),
640               rRingVar(0, dst->extRing)) == 0)
641    {
642      if (src->type==n_algExt)
643         return ndCopyMap; // naCopyMap;         /// Q(a)   --> Q(a)
644      else
645         return naCopyExt;
646    }
647    else
648      return NULL;                               /// Q(b)   --> Q(a)
649  }
650
651  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
652  {
653    if (strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0)
654    {
655      if (src->type==n_algExt)
656        return ndCopyMap; // naCopyMap;          /// Z/p(a) --> Z/p(a)
657      else
658         return naCopyExt;
659    }
660    else
661      return NULL;                               /// Z/p(b) --> Z/p(a)
662  }
663
664  return NULL;                                           /// default
665}
666
667BOOLEAN naInitChar(coeffs cf, void * infoStruct)
668{
669  assume( infoStruct != NULL );
670
671  AlgExtInfo *e = (AlgExtInfo *)infoStruct;
672  /// first check whether cf->extRing != NULL and delete old ring???
673
674  assume(e->r                     != NULL);      // extRing;
675  assume(e->r->cf                 != NULL);      // extRing->cf;
676  assume((e->i          != NULL) &&    // minideal has one
677         (IDELEMS(e->i) != 0)    &&    // non-zero generator
678         (e->i->m    != NULL)    ); // at m;
679
680  assume( e->r->minideal == NULL );
681
682  assume( cf != NULL );
683  assume(getCoeffType(cf) == ID);                     // coeff type;
684
685  cf->extRing           = e->r;
686  cf->extRing->ref ++; // increase the ref.counter for the ground poly. ring!
687
688  cf->extRing->minideal = e->i; // make a copy?
689
690  /* propagate characteristic up so that it becomes
691     directly accessible in cf: */
692  cf->ch = cf->extRing->cf->ch;
693
694  #ifdef LDEBUG
695  p_Test((poly)naMinpoly, naRing);
696  #endif
697
698  cf->cfGreaterZero  = naGreaterZero;
699  cf->cfGreater      = naGreater;
700  cf->cfEqual        = naEqual;
701  cf->cfIsZero       = naIsZero;
702  cf->cfIsOne        = naIsOne;
703  cf->cfIsMOne       = naIsMOne;
704  cf->cfInit         = naInit;
705  cf->cfInt          = naInt;
706  cf->cfNeg          = naNeg;
708  cf->cfSub          = naSub;
709  cf->cfMult         = naMult;
712  cf->cfPower        = naPower;
713  cf->cfCopy         = naCopy;
714  cf->cfWrite        = naWrite;
717  cf->cfSetMap       = naSetMap;
718  cf->cfGetDenom     = naGetDenom;
719  cf->cfGetNumerator = naGetNumerator;
720  cf->cfRePart       = naCopy;
721  cf->cfImPart       = naImPart;
722  cf->cfCoeffWrite   = naCoeffWrite;
723#ifdef LDEBUG
725#endif
726  cf->cfGcd          = naGcd;
727  cf->cfLcm          = naLcm;
728  cf->cfSize         = naSize;
729  cf->nCoeffIsEqual  = naCoeffIsEqual;
730  cf->cfInvers       = naInvers;
732
733  return FALSE;
734}
735
736
737number naParam(const short iParameter, const coeffs cf)
738{
739  assume(getCoeffType(cf) == ID);
740
741  const ring R = cf->extRing;
742  assume( R != NULL );
743  assume( 0 < iParameter && iParameter <= rVar(R) );
744
745  poly p = p_One(R); p_SetExp(p, iParameter, 1, R); p_Setm(p, R);
746
747  return (number) p;
748}
749
750
751/// if m == var(i)/1 => return i,
752int naIsParam(number m, const coeffs cf)
753{
754  assume(getCoeffType(cf) == ID);
755
756  const ring R = cf->extRing;
757  assume( R != NULL );
758
759  return p_Var( (poly)m, R );
760}
Note: See TracBrowser for help on using the repository browser.