source: git/libpolys/polys/ext_fields/algext.cc @ 36ef6e0

spielwiese
Last change on this file since 36ef6e0 was 36ef6e0, checked in by Hans Schoenemann <hannes@…>, 13 years ago
fix: naLcm was implemented in a wrong way
  • 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);
96//number   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#if 0
451/* implemented by the rule lcm(a, b) = a * b / gcd(a, b) */
452number naLcm(number a, number b, const coeffs cf)
453{
454  naTest(a); naTest(b);
455  if (a == NULL) return NULL;
456  if (b == NULL) return NULL;
457  number theProduct = (number)p_Mult_q(p_Copy((poly)a, naRing),
458                                       p_Copy((poly)b, naRing), naRing);
459  /* note that theProduct needs not be reduced w.r.t. naMinpoly;
460     but the final division will take care of the necessary reduction */
461  number theGcd = naGcd(a, b, cf);
462  return naDiv(theProduct, theGcd, cf);
463}
464#endif
465
466/* expects *param to be castable to AlgExtInfo */
467static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param)
468{
469  if (ID != n) return FALSE;
470  AlgExtInfo *e = (AlgExtInfo *)param;
471  /* for extension coefficient fields we expect the underlying
472     polynomial rings to be IDENTICAL, i.e. the SAME OBJECT;
473     this expectation is based on the assumption that we have properly
474     registered cf and perform reference counting rather than creating
475     multiple copies of the same coefficient field/domain/ring */
476  return (naRing == e->r);
477  /* (Note that then also the minimal ideals will necessarily be
478     the same, as they are attached to the ring.) */
479}
480
481int naSize(number a, const coeffs cf)
482{
483  if (a == NULL) return -1;
484  /* this has been taken from the old implementation of field extensions,
485     where we computed the sum of the degree and the number of terms in
486     (poly)a; so we leave it at that, for the time being;
487     maybe, the number of terms alone is a better measure? */
488  poly aAsPoly = (poly)a;
489  int theDegree = 0; int noOfTerms = 0;
490  while (aAsPoly != NULL)
491  {
492    noOfTerms++;
493    int d = p_GetExp(aAsPoly, 1, naRing);
494    if (d > theDegree) theDegree = d;
495    pIter(aAsPoly);
496  }
497  return theDegree + noOfTerms;
498}
499
500/* performs polynomial division and overrides p by the remainder
501   of division of p by the reducer;
502   modifies p */
503void definiteReduce(poly &p, poly reducer, const coeffs cf)
504{
505  #ifdef LDEBUG
506  p_Test((poly)p, naRing);
507  p_Test((poly)reducer, naRing);
508  #endif
509  p_PolyDiv(p, reducer, FALSE, naRing);
510}
511
512/* IMPORTANT NOTE: Since an algebraic field extension is again a field,
513                   the gcd of two elements is not very interesting. (It
514                   is actually any unit in the field, i.e., any non-
515                   zero element.) Note that the below method does not operate
516                   in this strong sense but rather computes the gcd of
517                   two given elements in the underlying polynomial ring. */
518number naGcd(number a, number b, const coeffs cf)
519{
520  naTest(a); naTest(b);
521  if ((a == NULL) && (b == NULL)) WerrorS(nDivBy0);
522  return (number)p_Gcd((poly)a, (poly)b, naRing);
523}
524
525number naInvers(number a, const coeffs cf)
526{
527  naTest(a);
528  if (a == NULL) WerrorS(nDivBy0);
529  poly aFactor = NULL; poly mFactor = NULL;
530  poly theGcd = p_ExtGcd((poly)a, aFactor, naMinpoly, mFactor, naRing);
531  naTest((number)theGcd); naTest((number)aFactor); naTest((number)mFactor);
532  /* the gcd must be 1 since naMinpoly is irreducible and a != NULL: */
533  assume(naIsOne((number)theGcd, cf));     
534  p_Delete(&theGcd, naRing);
535  p_Delete(&mFactor, naRing);
536  return (number)(aFactor);
537}
538
539/* assumes that src = Q, dst = Q(a) */
540number naMap00(number a, const coeffs src, const coeffs dst)
541{
542  if (n_IsZero(a, src)) return NULL;
543  assume(src == dst->extRing->cf);
544  poly result = p_One(dst->extRing);
545  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
546  return (number)result;
547}
548
549/* assumes that src = Z/p, dst = Q(a) */
550number naMapP0(number a, const coeffs src, const coeffs dst)
551{
552  if (n_IsZero(a, src)) return NULL;
553  /* mapping via intermediate int: */
554  int n = n_Int(a, src);
555  number q = n_Init(n, dst->extRing->cf);
556  poly result = p_One(dst->extRing);
557  p_SetCoeff(result, q, dst->extRing);
558  return (number)result;
559}
560
561#if 0
562/* assumes that either src = Q(a), dst = Q(a), or
563                       src = Z/p(a), dst = Z/p(a)     */
564number naCopyMap(number a, const coeffs src, const coeffs dst)
565{
566  return naCopy(a, dst);
567}
568#endif
569
570number naCopyExt(number a, const coeffs src, const coeffs dst)
571{
572  fraction fa=(fraction)a;
573  return (number)p_Copy(NUM(fa),src->extRing);
574}
575
576/* assumes that src = Q, dst = Z/p(a) */
577number naMap0P(number a, const coeffs src, const coeffs dst)
578{
579  if (n_IsZero(a, src)) return NULL;
580  int p = rChar(dst->extRing);
581  int n = nlModP(a, p, src);
582  number q = n_Init(n, dst->extRing->cf);
583  poly result = p_One(dst->extRing);
584  p_SetCoeff(result, q, dst->extRing);
585  return (number)result;
586}
587
588/* assumes that src = Z/p, dst = Z/p(a) */
589number naMapPP(number a, const coeffs src, const coeffs dst)
590{
591  if (n_IsZero(a, src)) return NULL;
592  assume(src == dst->extRing->cf);
593  poly result = p_One(dst->extRing);
594  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
595  return (number)result;
596}
597
598/* assumes that src = Z/u, dst = Z/p(a), where u != p */
599number naMapUP(number a, const coeffs src, const coeffs dst)
600{
601  if (n_IsZero(a, src)) return NULL;
602  /* mapping via intermediate int: */
603  int n = n_Int(a, src);
604  number q = n_Init(n, dst->extRing->cf);
605  poly result = p_One(dst->extRing);
606  p_SetCoeff(result, q, dst->extRing);
607  return (number)result;
608}
609
610nMapFunc naSetMap(const coeffs src, const coeffs dst)
611{
612  /* dst is expected to be an algebraic field extension */
613  assume(getCoeffType(dst) == ID);
614 
615  int h = 0; /* the height of the extension tower given by dst */
616  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
617  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
618 
619  /* for the time being, we only provide maps if h = 1 and if b is Q or
620     some field Z/pZ: */
621  if (h==0)
622  {
623    if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
624      return naMap00;                            /// Q     -->  Q(a)
625    if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
626      return naMapP0;                            /// Z/p   -->  Q(a)
627    if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
628      return naMap0P;                            /// Q      --> Z/p(a)
629    if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
630    {
631      if (src->ch == dst->ch) return naMapPP;    /// Z/p    --> Z/p(a)
632      else return naMapUP;                       /// Z/u    --> Z/p(a)
633    }
634  }
635  if (h != 1) return NULL;
636  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
637  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
638 
639  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
640  {
641    if (strcmp(rRingVar(0, src->extRing),
642               rRingVar(0, dst->extRing)) == 0)
643    {
644      if (src->type==n_algExt)
645         return ndCopyMap; // naCopyMap;         /// Q(a)   --> Q(a)
646      else
647         return naCopyExt;
648    }
649    else
650      return NULL;                               /// Q(b)   --> Q(a)
651  }
652 
653  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
654  {
655    if (strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0)
656    {
657      if (src->type==n_algExt)
658        return ndCopyMap; // naCopyMap;          /// Z/p(a) --> Z/p(a)
659      else
660         return naCopyExt;
661    }
662    else
663      return NULL;                               /// Z/p(b) --> Z/p(a)
664  }
665 
666  return NULL;                                           /// default
667}
668
669BOOLEAN naInitChar(coeffs cf, void * infoStruct)
670{ 
671  assume( infoStruct != NULL );
672
673  AlgExtInfo *e = (AlgExtInfo *)infoStruct;
674  /// first check whether cf->extRing != NULL and delete old ring???
675
676  assume(e->r                     != NULL);      // extRing;
677  assume(e->r->cf                 != NULL);      // extRing->cf;
678  assume((e->i          != NULL) &&    // minideal has one
679         (IDELEMS(e->i) != 0)    &&    // non-zero generator
680         (e->i->m[0]    != NULL)    ); // at m[0];
681
682  assume( e->r->minideal == NULL );
683
684  assume( cf != NULL );
685  assume(getCoeffType(cf) == ID);                     // coeff type;
686 
687  cf->extRing           = e->r;
688  cf->extRing->ref ++; // increase the ref.counter for the ground poly. ring!
689
690  cf->extRing->minideal = e->i; // make a copy?
691
692  /* propagate characteristic up so that it becomes
693     directly accessible in cf: */
694  cf->ch = cf->extRing->cf->ch;
695 
696  #ifdef LDEBUG
697  p_Test((poly)naMinpoly, naRing);
698  #endif
699 
700  cf->cfGreaterZero  = naGreaterZero;
701  cf->cfGreater      = naGreater;
702  cf->cfEqual        = naEqual;
703  cf->cfIsZero       = naIsZero;
704  cf->cfIsOne        = naIsOne;
705  cf->cfIsMOne       = naIsMOne;
706  cf->cfInit         = naInit;
707  cf->cfInt          = naInt;
708  cf->cfNeg          = naNeg;
709  cf->cfAdd          = naAdd;
710  cf->cfSub          = naSub;
711  cf->cfMult         = naMult;
712  cf->cfDiv          = naDiv;
713  cf->cfExactDiv     = naDiv;
714  cf->cfPower        = naPower;
715  cf->cfCopy         = naCopy;
716  cf->cfWrite        = naWrite;
717  cf->cfRead         = naRead;
718  cf->cfDelete       = naDelete;
719  cf->cfSetMap       = naSetMap;
720  cf->cfGetDenom     = naGetDenom;
721  cf->cfGetNumerator = naGetNumerator;
722  cf->cfRePart       = naCopy;
723  cf->cfImPart       = naImPart;
724  cf->cfCoeffWrite   = naCoeffWrite;
725#ifdef LDEBUG
726  cf->cfDBTest       = naDBTest;
727#endif
728  cf->cfGcd          = naGcd;
729  //cf->cfLcm          = naLcm;
730  cf->cfSize         = naSize;
731  cf->nCoeffIsEqual  = naCoeffIsEqual;
732  cf->cfInvers       = naInvers;
733  cf->cfIntDiv       = naDiv;
734 
735  return FALSE;
736}
737
738
739number naParam(const short iParameter, const coeffs cf)
740{
741  assume(getCoeffType(cf) == ID);
742 
743  const ring R = cf->extRing;
744  assume( R != NULL ); 
745  assume( 0 < iParameter && iParameter <= rVar(R) );
746 
747  poly p = p_One(R); p_SetExp(p, iParameter, 1, R); p_Setm(p, R);
748 
749  return (number) p; 
750}
751
752
753/// if m == var(i)/1 => return i,
754int naIsParam(number m, const coeffs cf)
755{
756  assume(getCoeffType(cf) == ID);
757
758  const ring R = cf->extRing;
759  assume( R != NULL ); 
760
761  return p_Var( (poly)m, R ); 
762}
Note: See TracBrowser for help on using the repository browser.