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

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