source: git/libpolys/polys/ext_fields/algext.cc @ 865b20

spielwiese
Last change on this file since 865b20 was 865b20, checked in by Oleksandr Motsak <motsak@…>, 12 years ago
fixed a bug in naInvers for the case of non-irreducible minpoly and division by a zero-divisor
  • Property mode set to 100644
File size: 26.8 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->qideal is not NULL but an ideal with at
17  *               least one non-zero generator which may be accessed by
18  *               cf->extRing->qideal->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#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
56#define naTest(a) naDBTest(a,__FILE__,__LINE__,cf)
57BOOLEAN  naDBTest(number a, const char *f, const int l, const coeffs r);
58#else
59#define naTest(a) ((void)(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
70 * coefficients of our numbers, e.g., use naCoeffs->nAdd to add
71 * coefficients of our numbers */
72#define naCoeffs cf->extRing->cf
73
74/* minimal polynomial */
75#define naMinpoly naRing->qideal->m[0]
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(long 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     naWriteLong(number &a, const coeffs cf);
95void     naWriteShort(number &a, const coeffs cf);
96number   naRePart(number a, const coeffs cf);
97number   naImPart(number a, const coeffs cf);
98number   naGetDenom(number &a, const coeffs cf);
99number   naGetNumerator(number &a, const coeffs cf);
100number   naGcd(number a, number b, const coeffs cf);
101//number   naLcm(number a, number b, const coeffs cf);
102int      naSize(number a, const coeffs cf);
103void     naDelete(number *a, const coeffs cf);
104void     naCoeffWrite(const coeffs cf, BOOLEAN details);
105number   naIntDiv(number a, number b, const coeffs cf);
106const char * naRead(const char *s, number *a, const coeffs cf);
107
108static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param);
109
110#ifdef LDEBUG
111BOOLEAN naDBTest(number a, const char *f, const int l, const coeffs cf)
112{
113  assume(getCoeffType(cf) == ID);
114  if (a == NULL) return TRUE;
115  p_Test((poly)a, naRing);
116  if((((poly)a)!=naMinpoly)
117  && p_Totaldegree((poly)a, naRing) >= p_Totaldegree(naMinpoly, naRing))
118  {
119    Print("deg >= deg(minpoly) in %s:%d\n",f,l);
120    return FALSE;
121  }
122  return TRUE;
123}
124#endif
125
126void heuristicReduce(poly &p, poly reducer, const coeffs cf);
127void definiteReduce(poly &p, poly reducer, const coeffs cf);
128
129/* returns the bottom field in this field extension tower; if the tower
130   is flat, i.e., if there is no extension, then r itself is returned;
131   as a side-effect, the counter 'height' is filled with the height of
132   the extension tower (in case the tower is flat, 'height' is zero) */
133static coeffs nCoeff_bottom(const coeffs r, int &height)
134{
135  assume(r != NULL);
136  coeffs cf = r;
137  height = 0;
138  while (nCoeff_is_Extension(cf))
139  {
140    assume(cf->extRing != NULL); assume(cf->extRing->cf != NULL);
141    cf = cf->extRing->cf;
142    height++;
143  }
144  return cf;
145}
146
147BOOLEAN naIsZero(number a, const coeffs cf)
148{
149  naTest(a);
150  return (a == NULL);
151}
152
153void naDelete(number * a, const coeffs cf)
154{
155  if (*a == NULL) return;
156  if (((poly)*a)==naMinpoly) { *a=NULL;return;}
157  poly aAsPoly = (poly)(*a);
158  p_Delete(&aAsPoly, naRing);
159  *a = NULL;
160}
161
162BOOLEAN naEqual(number a, number b, const coeffs cf)
163{
164  naTest(a); naTest(b);
165
166  /// simple tests
167  if (a == b) return TRUE;
168  if ((a == NULL) && (b != NULL)) return FALSE;
169  if ((b == NULL) && (a != NULL)) return FALSE;
170
171  /// deg test
172  int aDeg = 0;
173  if (a != NULL) aDeg = p_Totaldegree((poly)a, naRing);
174  int bDeg = 0;
175  if (b != NULL) bDeg = p_Totaldegree((poly)b, naRing);
176  if (aDeg != bDeg) return FALSE;
177
178  /// subtraction test
179  number c = naSub(a, b, cf);
180  BOOLEAN result = naIsZero(c, cf);
181  naDelete(&c, cf);
182  return result;
183}
184
185number naCopy(number a, const coeffs cf)
186{
187  naTest(a);
188  if (a == NULL) return NULL;
189  if (((poly)a)==naMinpoly) return a;
190  return (number)p_Copy((poly)a, naRing);
191}
192
193number naGetNumerator(number &a, const coeffs cf)
194{
195  return naCopy(a, cf);
196}
197
198number naGetDenom(number &a, const coeffs cf)
199{
200  naTest(a);
201  return naInit(1, cf);
202}
203
204BOOLEAN naIsOne(number a, const coeffs cf)
205{
206  naTest(a);
207  poly aAsPoly = (poly)a;
208  if ((a==NULL) || (!p_IsConstant(aAsPoly, naRing))) return FALSE;
209  return n_IsOne(p_GetCoeff(aAsPoly, naRing), naCoeffs);
210}
211
212BOOLEAN naIsMOne(number a, const coeffs cf)
213{
214  naTest(a);
215  poly aAsPoly = (poly)a;
216  if ((a==NULL) || (!p_IsConstant(aAsPoly, naRing))) return FALSE;
217  return n_IsMOne(p_GetCoeff(aAsPoly, naRing), naCoeffs);
218}
219
220/// this is in-place, modifies a
221number naNeg(number a, const coeffs cf)
222{
223  naTest(a);
224  if (a != NULL) a = (number)p_Neg((poly)a, naRing);
225  return a;
226}
227
228number naImPart(number a, const coeffs cf)
229{
230  naTest(a);
231  return NULL;
232}
233
234number naInit_bigint(number longratBigIntNumber, const coeffs src, const coeffs cf)
235{
236  assume( cf != NULL );
237
238  const ring A = cf->extRing;
239
240  assume( A != NULL );
241
242  const coeffs C = A->cf;
243
244  assume( C != NULL );
245
246  number n = n_Init_bigint(longratBigIntNumber, src, C);
247
248  if ( n_IsZero(n, C) )
249  {
250    n_Delete(&n, C);
251    return NULL;
252  }
253
254  return (number)p_NSet(n, A);
255}
256
257
258
259number naInit(long i, const coeffs cf)
260{
261  if (i == 0) return NULL;
262  else        return (number)p_ISet(i, naRing);
263}
264
265int naInt(number &a, const coeffs cf)
266{
267  naTest(a);
268  poly aAsPoly = (poly)a;
269  if(aAsPoly == NULL)
270    return 0;
271  if (!p_IsConstant(aAsPoly, naRing))
272    return 0;
273  assume( aAsPoly != NULL );
274  return n_Int(p_GetCoeff(aAsPoly, naRing), naCoeffs);
275}
276
277/* TRUE iff (a != 0 and (b == 0 or deg(a) > deg(b) or (deg(a)==deg(b) && lc(a)>lc(b))) */
278BOOLEAN naGreater(number a, number b, const coeffs cf)
279{
280  naTest(a); naTest(b);
281  if (naIsZero(a, cf))
282  {
283    if (naIsZero(b, cf)) return FALSE;
284    return !n_GreaterZero(pGetCoeff((poly)b),cf);
285  }
286  if (naIsZero(b, cf))
287  {
288    return n_GreaterZero(pGetCoeff((poly)a),cf);
289  }
290  int aDeg = p_Totaldegree((poly)a, naRing);
291  int bDeg = p_Totaldegree((poly)b, naRing);
292  if (aDeg>bDeg) return TRUE;
293  if (aDeg<bDeg) return FALSE;
294  return n_Greater(pGetCoeff((poly)a),pGetCoeff((poly)b),cf);
295}
296
297/* TRUE iff a != 0 and (LC(a) > 0 or deg(a) > 0) */
298BOOLEAN naGreaterZero(number a, const coeffs cf)
299{
300  naTest(a);
301  if (a == NULL)                                            return FALSE;
302  if (n_GreaterZero(p_GetCoeff((poly)a, naRing), naCoeffs)) return TRUE;
303  if (p_Totaldegree((poly)a, naRing) > 0)                   return TRUE;
304  return FALSE;
305}
306
307void naCoeffWrite(const coeffs cf, BOOLEAN details)
308{
309  assume( cf != NULL );
310
311  const ring A = cf->extRing;
312
313  assume( A != NULL );
314  assume( A->cf != NULL );
315
316  n_CoeffWrite(A->cf, details);
317
318//  rWrite(A);
319
320  const int P = rVar(A);
321  assume( P > 0 );
322
323  Print("//   %d parameter    : ", P);
324
325  for (int nop=0; nop < P; nop ++)
326    Print("%s ", rRingVar(nop, A));
327
328  PrintLn();
329
330  const ideal I = A->qideal;
331
332  assume( I != NULL );
333  assume( IDELEMS(I) == 1 );
334
335
336  if ( details )
337  {
338    PrintS("//   minpoly        : (");
339    p_Write0( I->m[0], A);
340    PrintS(")");
341  }
342  else
343    PrintS("//   minpoly        : ...");
344
345  PrintLn();
346
347/*
348  char *x = rRingVar(0, A);
349
350  Print("//   Coefficients live in the extension field K[%s]/<f(%s)>\n", x, x);
351  Print("//   with the minimal polynomial f(%s) = %s\n", x,
352        p_String(A->qideal->m[0], A));
353  PrintS("//   and K: ");
354*/
355}
356
357number naAdd(number a, number b, const coeffs cf)
358{
359  naTest(a); naTest(b);
360  if (a == NULL) return naCopy(b, cf);
361  if (b == NULL) return naCopy(a, cf);
362  poly aPlusB = p_Add_q(p_Copy((poly)a, naRing),
363                        p_Copy((poly)b, naRing), naRing);
364  definiteReduce(aPlusB, naMinpoly, cf);
365  return (number)aPlusB;
366}
367
368number naSub(number a, number b, const coeffs cf)
369{
370  naTest(a); naTest(b);
371  if (b == NULL) return naCopy(a, cf);
372  poly minusB = p_Neg(p_Copy((poly)b, naRing), naRing);
373  if (a == NULL) return (number)minusB;
374  poly aMinusB = p_Add_q(p_Copy((poly)a, naRing), minusB, naRing);
375  definiteReduce(aMinusB, naMinpoly, cf);
376  return (number)aMinusB;
377}
378
379number naMult(number a, number b, const coeffs cf)
380{
381  naTest(a); naTest(b);
382  if (a == NULL) return NULL;
383  if (b == NULL) return NULL;
384  poly aTimesB = p_Mult_q(p_Copy((poly)a, naRing),
385                          p_Copy((poly)b, naRing), naRing);
386  definiteReduce(aTimesB, naMinpoly, cf);
387  return (number)aTimesB;
388}
389
390number naDiv(number a, number b, const coeffs cf)
391{
392  naTest(a); naTest(b);
393  if (b == NULL) WerrorS(nDivBy0);
394  if (a == NULL) return NULL;
395  poly bInverse = (poly)naInvers(b, cf);
396  if(bInverse != NULL) // b is non-zero divisor!
397  {
398    poly aDivB = p_Mult_q(p_Copy((poly)a, naRing), bInverse, naRing);
399    definiteReduce(aDivB, naMinpoly, cf);
400    return (number)aDivB;
401  }
402  return NULL;
403}
404
405/* 0^0 = 0;
406   for |exp| <= 7 compute power by a simple multiplication loop;
407   for |exp| >= 8 compute power along binary presentation of |exp|, e.g.
408      p^13 = p^1 * p^4 * p^8, where we utilise that
409      p^(2^(k+1)) = p^(2^k) * p^(2^k);
410   intermediate reduction modulo the minimal polynomial is controlled by
411   the in-place method heuristicReduce(poly, poly, coeffs); see there.
412*/
413void naPower(number a, int exp, number *b, const coeffs cf)
414{
415  naTest(a);
416
417  /* special cases first */
418  if (a == NULL)
419  {
420    if (exp >= 0) *b = NULL;
421    else          WerrorS(nDivBy0);
422  }
423  else if (exp ==  0) { *b = naInit(1, cf); return; }
424  else if (exp ==  1) { *b = naCopy(a, cf); return; }
425  else if (exp == -1) { *b = naInvers(a, cf); return; }
426
427  int expAbs = exp; if (expAbs < 0) expAbs = -expAbs;
428
429  /* now compute a^expAbs */
430  poly pow; poly aAsPoly = (poly)a;
431  if (expAbs <= 7)
432  {
433    pow = p_Copy(aAsPoly, naRing);
434    for (int i = 2; i <= expAbs; i++)
435    {
436      pow = p_Mult_q(pow, p_Copy(aAsPoly, naRing), naRing);
437      heuristicReduce(pow, naMinpoly, cf);
438    }
439    definiteReduce(pow, naMinpoly, cf);
440  }
441  else
442  {
443    pow = p_ISet(1, naRing);
444    poly factor = p_Copy(aAsPoly, naRing);
445    while (expAbs != 0)
446    {
447      if (expAbs & 1)
448      {
449        pow = p_Mult_q(pow, p_Copy(factor, naRing), naRing);
450        heuristicReduce(pow, naMinpoly, cf);
451      }
452      expAbs = expAbs / 2;
453      if (expAbs != 0)
454      {
455        factor = p_Mult_q(factor, p_Copy(factor, naRing), naRing);
456        heuristicReduce(factor, naMinpoly, cf);
457      }
458    }
459    p_Delete(&factor, naRing);
460    definiteReduce(pow, naMinpoly, cf);
461  }
462
463  /* invert if original exponent was negative */
464  number n = (number)pow;
465  if (exp < 0)
466  {
467    number m = naInvers(n, cf);
468    naDelete(&n, cf);
469    n = m;
470  }
471  *b = n;
472}
473
474/* may reduce p modulo the reducer by calling definiteReduce;
475   the decision is made based on the following heuristic
476   (which should also only be changed here in this method):
477      if (deg(p) > 10*deg(reducer) then perform reduction;
478   modifies p */
479void heuristicReduce(poly &p, poly reducer, const coeffs cf)
480{
481  #ifdef LDEBUG
482  p_Test((poly)p, naRing);
483  p_Test((poly)reducer, naRing);
484  #endif
485  if (p_Totaldegree(p, naRing) > 10 * p_Totaldegree(reducer, naRing))
486    definiteReduce(p, reducer, cf);
487}
488
489void naWriteLong(number &a, const coeffs cf)
490{
491  naTest(a);
492  if (a == NULL)
493    StringAppendS("0");
494  else
495  {
496    poly aAsPoly = (poly)a;
497    /* basically, just write aAsPoly using p_Write,
498       but use brackets around the output, if a is not
499       a constant living in naCoeffs = cf->extRing->cf */
500    BOOLEAN useBrackets = !(p_IsConstant(aAsPoly, naRing));
501    if (useBrackets) StringAppendS("(");
502    p_String0Long(aAsPoly, naRing, naRing);
503    if (useBrackets) StringAppendS(")");
504  }
505}
506
507void naWriteShort(number &a, const coeffs cf)
508{
509  naTest(a);
510  if (a == NULL)
511    StringAppendS("0");
512  else
513  {
514    poly aAsPoly = (poly)a;
515    /* basically, just write aAsPoly using p_Write,
516       but use brackets around the output, if a is not
517       a constant living in naCoeffs = cf->extRing->cf */
518    BOOLEAN useBrackets = !(p_IsConstant(aAsPoly, naRing));
519    if (useBrackets) StringAppendS("(");
520    p_String0Short(aAsPoly, naRing, naRing);
521    if (useBrackets) StringAppendS(")");
522  }
523}
524
525const char * naRead(const char *s, number *a, const coeffs cf)
526{
527  poly aAsPoly;
528  const char * result = p_Read(s, aAsPoly, naRing);
529  definiteReduce(aAsPoly, naMinpoly, cf);
530  *a = (number)aAsPoly;
531  return result;
532}
533
534#if 0
535/* implemented by the rule lcm(a, b) = a * b / gcd(a, b) */
536number naLcm(number a, number b, const coeffs cf)
537{
538  naTest(a); naTest(b);
539  if (a == NULL) return NULL;
540  if (b == NULL) return NULL;
541  number theProduct = (number)p_Mult_q(p_Copy((poly)a, naRing),
542                                       p_Copy((poly)b, naRing), naRing);
543  /* note that theProduct needs not be reduced w.r.t. naMinpoly;
544     but the final division will take care of the necessary reduction */
545  number theGcd = naGcd(a, b, cf);
546  return naDiv(theProduct, theGcd, cf);
547}
548#endif
549
550/* expects *param to be castable to AlgExtInfo */
551static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param)
552{
553  if (ID != n) return FALSE;
554  AlgExtInfo *e = (AlgExtInfo *)param;
555  /* for extension coefficient fields we expect the underlying
556     polynomial rings to be IDENTICAL, i.e. the SAME OBJECT;
557     this expectation is based on the assumption that we have properly
558     registered cf and perform reference counting rather than creating
559     multiple copies of the same coefficient field/domain/ring */
560  if (naRing == e->r)
561    return TRUE;
562  /* (Note that then also the minimal ideals will necessarily be
563     the same, as they are attached to the ring.) */
564
565  // NOTE: Q(a)[x] && Q(a)[y] should better share the _same_ Q(a)...
566  if( rEqual(naRing, e->r, TRUE) ) // also checks the equality of qideals
567  {
568    const ideal mi = naRing->qideal; 
569    assume( IDELEMS(mi) == 1 );
570    const ideal ii = e->r->qideal;
571    assume( IDELEMS(ii) == 1 );
572
573    // TODO: the following should be extended for 2 *equal* rings...
574    assume( p_EqualPolys(mi->m[0], ii->m[0], naRing, e->r) );
575   
576    rDelete(e->r);
577   
578    return TRUE;
579  }
580
581  return FALSE;
582
583}
584
585int naSize(number a, const coeffs cf)
586{
587  if (a == NULL) return -1;
588  /* this has been taken from the old implementation of field extensions,
589     where we computed the sum of the degree and the number of terms in
590     (poly)a; so we leave it at that, for the time being;
591     maybe, the number of terms alone is a better measure? */
592  poly aAsPoly = (poly)a;
593  int theDegree = 0; int noOfTerms = 0;
594  while (aAsPoly != NULL)
595  {
596    noOfTerms++;
597    int d = p_GetExp(aAsPoly, 1, naRing);
598    if (d > theDegree) theDegree = d;
599    pIter(aAsPoly);
600  }
601  return theDegree + noOfTerms;
602}
603
604/* performs polynomial division and overrides p by the remainder
605   of division of p by the reducer;
606   modifies p */
607void definiteReduce(poly &p, poly reducer, const coeffs cf)
608{
609  #ifdef LDEBUG
610  p_Test((poly)p, naRing);
611  p_Test((poly)reducer, naRing);
612  #endif
613  if ((p!=NULL) && (p_GetExp(p,1,naRing)>=p_GetExp(reducer,1,naRing)))
614  {
615    p_PolyDiv(p, reducer, FALSE, naRing);
616  }
617}
618
619void  naNormalize(number &a, const coeffs cf)
620{
621  poly aa=(poly)a;
622  if (aa!=naMinpoly)
623    definiteReduce(aa,naMinpoly,cf);
624  a=(number)aa;
625}
626
627#ifdef HAVE_FACTORY
628number naConvFactoryNSingN( const CanonicalForm n, const coeffs cf)
629{
630  if (n.isZero()) return NULL;
631  poly p=convFactoryPSingP(n,naRing);
632  return (number)p;
633}
634CanonicalForm naConvSingNFactoryN( number n, BOOLEAN /*setChar*/, const coeffs cf )
635{
636  naTest(n);
637  if (n==NULL) return CanonicalForm(0);
638
639  return convSingPFactoryP((poly)n,naRing);
640}
641#endif
642
643
644/* IMPORTANT NOTE: Since an algebraic field extension is again a field,
645                   the gcd of two elements is not very interesting. (It
646                   is actually any unit in the field, i.e., any non-
647                   zero element.) Note that the below method does not operate
648                   in this strong sense but rather computes the gcd of
649                   two given elements in the underlying polynomial ring. */
650number naGcd(number a, number b, const coeffs cf)
651{
652  naTest(a); naTest(b);
653  if ((a == NULL) && (b == NULL)) WerrorS(nDivBy0);
654  return (number)p_Gcd((poly)a, (poly)b, naRing);
655}
656
657number naInvers(number a, const coeffs cf)
658{
659  naTest(a);
660  if (a == NULL) WerrorS(nDivBy0);
661 
662  poly aFactor = NULL; poly mFactor = NULL;
663  poly theGcd = p_ExtGcd((poly)a, aFactor, naMinpoly, mFactor, naRing);
664 
665  naTest((number)theGcd); naTest((number)aFactor); naTest((number)mFactor);
666  p_Delete(&mFactor, naRing);
667 
668  //  /* the gcd must be 1 since naMinpoly is irreducible and a != NULL: */
669  //  assume(naIsOne((number)theGcd, cf));
670
671  if( !naIsOne((number)theGcd, cf) )
672  { 
673    WerrorS("zero divisor found - your minpoly is not irreducible");
674    p_Delete(&aFactor, naRing); aFactor = NULL;
675  }
676  p_Delete(&theGcd, naRing);
677
678  return (number)(aFactor);
679}
680
681/* assumes that src = Q, dst = Q(a) */
682number naMap00(number a, const coeffs src, const coeffs dst)
683{
684  if (n_IsZero(a, src)) return NULL;
685  assume(src == dst->extRing->cf);
686  poly result = p_One(dst->extRing);
687  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
688  return (number)result;
689}
690
691/* assumes that src = Z/p, dst = Q(a) */
692number naMapP0(number a, const coeffs src, const coeffs dst)
693{
694  if (n_IsZero(a, src)) return NULL;
695  /* mapping via intermediate int: */
696  int n = n_Int(a, src);
697  number q = n_Init(n, dst->extRing->cf);
698  poly result = p_One(dst->extRing);
699  p_SetCoeff(result, q, dst->extRing);
700  return (number)result;
701}
702
703#if 0
704/* assumes that either src = Q(a), dst = Q(a), or
705                       src = Z/p(a), dst = Z/p(a)     */
706number naCopyMap(number a, const coeffs src, const coeffs dst)
707{
708  return naCopy(a, dst);
709}
710#endif
711
712number naCopyExt(number a, const coeffs src, const coeffs)
713{
714  fraction fa=(fraction)a;
715  return (number)p_Copy(NUM(fa),src->extRing);
716}
717
718/* assumes that src = Q, dst = Z/p(a) */
719number naMap0P(number a, const coeffs src, const coeffs dst)
720{
721  if (n_IsZero(a, src)) return NULL;
722  int p = rChar(dst->extRing);
723
724  number q = nlModP(a, src, dst->extRing->cf);
725
726  poly result = p_NSet(q, dst->extRing);
727
728  return (number)result;
729}
730
731/* assumes that src = Z/p, dst = Z/p(a) */
732number naMapPP(number a, const coeffs src, const coeffs dst)
733{
734  if (n_IsZero(a, src)) return NULL;
735  assume(src == dst->extRing->cf);
736  poly result = p_One(dst->extRing);
737  p_SetCoeff(result, n_Copy(a, src), dst->extRing);
738  return (number)result;
739}
740
741/* assumes that src = Z/u, dst = Z/p(a), where u != p */
742number naMapUP(number a, const coeffs src, const coeffs dst)
743{
744  if (n_IsZero(a, src)) return NULL;
745  /* mapping via intermediate int: */
746  int n = n_Int(a, src);
747  number q = n_Init(n, dst->extRing->cf);
748  poly result = p_One(dst->extRing);
749  p_SetCoeff(result, q, dst->extRing);
750  return (number)result;
751}
752
753nMapFunc naSetMap(const coeffs src, const coeffs dst)
754{
755  /* dst is expected to be an algebraic field extension */
756  assume(getCoeffType(dst) == ID);
757
758  if( src == dst ) return ndCopyMap;
759
760  int h = 0; /* the height of the extension tower given by dst */
761  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
762  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
763
764  /* for the time being, we only provide maps if h = 1 and if b is Q or
765     some field Z/pZ: */
766  if (h==0)
767  {
768    if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
769      return naMap00;                            /// Q     -->  Q(a)
770    if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
771      return naMapP0;                            /// Z/p   -->  Q(a)
772    if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
773      return naMap0P;                            /// Q      --> Z/p(a)
774    if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
775    {
776      if (src->ch == dst->ch) return naMapPP;    /// Z/p    --> Z/p(a)
777      else return naMapUP;                       /// Z/u    --> Z/p(a)
778    }
779  }
780  if (h != 1) return NULL;
781  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
782  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
783
784  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
785  {
786    if (strcmp(rRingVar(0, src->extRing),
787               rRingVar(0, dst->extRing)) == 0)
788    {
789      if (src->type==n_algExt)
790         return ndCopyMap; // naCopyMap;         /// Q(a)   --> Q(a)
791      else
792         return naCopyExt;
793    }
794    else
795      return NULL;                               /// Q(b)   --> Q(a)
796  }
797
798  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
799  {
800    if (strcmp(rRingVar(0,src->extRing),rRingVar(0,dst->extRing))==0)
801    {
802      if (src->type==n_algExt)
803        return ndCopyMap; // naCopyMap;          /// Z/p(a) --> Z/p(a)
804      else
805         return naCopyExt;
806    }
807    else
808      return NULL;                               /// Z/p(b) --> Z/p(a)
809  }
810
811  return NULL;                                           /// default
812}
813
814static int naParDeg(number a, const coeffs cf)
815{
816  if (a == NULL) return -1;
817  poly aa=(poly)a;
818  return cf->extRing->pFDeg(aa,cf->extRing);
819}
820
821/// return the specified parameter as a number in the given alg. field
822static number naParameter(const int iParameter, const coeffs cf)
823{
824  assume(getCoeffType(cf) == ID);
825
826  const ring R = cf->extRing;
827  assume( R != NULL );
828  assume( 0 < iParameter && iParameter <= rVar(R) );
829
830  poly p = p_One(R); p_SetExp(p, iParameter, 1, R); p_Setm(p, R);
831
832  return (number) p;
833}
834
835
836/// if m == var(i)/1 => return i,
837int naIsParam(number m, const coeffs cf)
838{
839  assume(getCoeffType(cf) == ID);
840
841  const ring R = cf->extRing;
842  assume( R != NULL );
843
844  return p_Var( (poly)m, R );
845}
846
847static void naClearContent(ICoeffsEnumerator& /*numberCollectionEnumerator*/, number& c, const coeffs cf)
848{
849  assume(cf != NULL);
850  assume(getCoeffType(cf) == ID);
851  assume(nCoeff_is_Q_a(cf)); // only over Q[a]/m(a), while the default impl. is used over Zp[a]/m(a) !
852  // all coeffs are given by integers!!!
853
854  c = n_Init(1, cf);
855  assume(FALSE); // TODO: NOT YET IMPLEMENTED!!!
856
857//   numberCollectionEnumerator.Reset();
858//
859//   c = numberCollectionEnumerator.Current();
860//
861//   n_Normalize(c, r);
862//
863//   if (!n_IsOne(c, r))
864//   {   
865//     numberCollectionEnumerator.Current() = n_Init(1, r); // ???
866//
867//     number inv = n_Invers(c, r);
868//
869//     while( numberCollectionEnumerator.MoveNext() )
870//     {
871//       number &n = numberCollectionEnumerator.Current();
872//       n_Normalize(n, r); // ?
873//       n_InpMult(n, inv, r);
874//     }
875//
876//     n_Delete(&inv, r);
877//   }
878}
879
880
881BOOLEAN naInitChar(coeffs cf, void * infoStruct)
882{
883  assume( infoStruct != NULL );
884
885  AlgExtInfo *e = (AlgExtInfo *)infoStruct;
886  /// first check whether cf->extRing != NULL and delete old ring???
887
888  assume(e->r                     != NULL);      // extRing;
889  assume(e->r->cf                 != NULL);      // extRing->cf;
890
891  assume((e->r->qideal            != NULL) &&    // minideal has one
892         (IDELEMS(e->r->qideal)   == 1)    &&    // non-zero generator
893         (e->r->qideal->m[0]      != NULL)    ); // at m[0];
894
895  assume( cf != NULL );
896  assume(getCoeffType(cf) == ID);                     // coeff type;
897
898  e->r->ref ++; // increase the ref.counter for the ground poly. ring!
899  const ring R = e->r; // no copy!
900  assume( R->qideal == e->r->qideal );
901  cf->extRing  = R;
902
903  /* propagate characteristic up so that it becomes
904     directly accessible in cf: */
905  cf->ch = R->cf->ch;
906
907  #ifdef LDEBUG
908  p_Test((poly)naMinpoly, naRing);
909  #endif
910
911  cf->cfGreaterZero  = naGreaterZero;
912  cf->cfGreater      = naGreater;
913  cf->cfEqual        = naEqual;
914  cf->cfIsZero       = naIsZero;
915  cf->cfIsOne        = naIsOne;
916  cf->cfIsMOne       = naIsMOne;
917  cf->cfInit         = naInit;
918  cf->cfInit_bigint  = naInit_bigint;
919  cf->cfInt          = naInt;
920  cf->cfNeg          = naNeg;
921  cf->cfAdd          = naAdd;
922  cf->cfSub          = naSub;
923  cf->cfMult         = naMult;
924  cf->cfDiv          = naDiv;
925  cf->cfExactDiv     = naDiv;
926  cf->cfPower        = naPower;
927  cf->cfCopy         = naCopy;
928
929  cf->cfWriteLong        = naWriteLong;
930
931  if( rCanShortOut(naRing) )
932    cf->cfWriteShort = naWriteShort;
933  else
934    cf->cfWriteShort = naWriteLong;
935
936  cf->cfRead         = naRead;
937  cf->cfDelete       = naDelete;
938  cf->cfSetMap       = naSetMap;
939  cf->cfGetDenom     = naGetDenom;
940  cf->cfGetNumerator = naGetNumerator;
941  cf->cfRePart       = naCopy;
942  cf->cfImPart       = naImPart;
943  cf->cfCoeffWrite   = naCoeffWrite;
944  cf->cfNormalize    = naNormalize;
945#ifdef LDEBUG
946  cf->cfDBTest       = naDBTest;
947#endif
948  cf->cfGcd          = naGcd;
949  //cf->cfLcm          = naLcm;
950  cf->cfSize         = naSize;
951  cf->nCoeffIsEqual  = naCoeffIsEqual;
952  cf->cfInvers       = naInvers;
953  cf->cfIntDiv       = naDiv;
954#ifdef HAVE_FACTORY
955  cf->convFactoryNSingN=naConvFactoryNSingN;
956  cf->convSingNFactoryN=naConvSingNFactoryN;
957#endif
958  cf->cfParDeg = naParDeg;
959
960  cf->iNumberOfParameters = rVar(R);
961  cf->pParameterNames = R->names;
962  cf->cfParameter = naParameter;
963
964  if( nCoeff_is_Q(R->cf) )
965    cf->cfClearContent = naClearContent;
966 
967  return FALSE;
968}
Note: See TracBrowser for help on using the repository browser.