source: git/libpolys/polys/ext_fields/algext.cc @ 9bb5457

spielwiese
Last change on this file since 9bb5457 was 6ccdd3a, checked in by Frank Seelisch <seelisch@…>, 13 years ago
renamed algring; comments; transext.* added
  • Property mode set to 100644
File size: 20.5 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5/*
6* ABSTRACT: numbers in an algebraic extension field K[a] / < f(a) >
7*           Assuming that we have a coeffs object cf, then these numbers
8*           are polynomials in the polynomial ring K[a] represented by
9*           cf->extRing.
10*           IMPORTANT ASSUMPTIONS:
11*           1.) So far we assume that cf->extRing is a valid polynomial
12*               ring in exactly one variable, i.e., K[a], where K is allowed
13*               to be any field (representable in SINGULAR and which may
14*               itself be some extension field, thus allowing for extension
15*               towers).
16*           2.) Moreover, this implementation assumes that
17*               cf->extRing->minideal is not NULL but an ideal with at
18*               least one non-zero generator which may be accessed by
19*               cf->extRing->minideal->m[0] and which represents the minimal
20*               polynomial f(a) of the extension variable 'a' in K[a].
21*           3.) As soon as an std method for polynomial rings becomes
22*               availabe, all reduction steps modulo f(a) should be replaced
23*               by a call to std. Moreover, in this situation one can finally
24*               move from K[a] / < f(a) > to
25*                  K[a_1, ..., a_s] / I, with I some zero-dimensional ideal
26*                                        in K[a_1, ..., a_s] given by a lex
27*                                        Gröbner basis.
28*               The code in algext.h and algext.cc is then capable of
29*               computing in K[a_1, ..., a_s] / I.
30*/
31
32#include "config.h"
33#include <misc/auxiliary.h>
34
35#include <omalloc/omalloc.h>
36
37#include <reporter/reporter.h>
38
39#include <coeffs/coeffs.h>
40#include <coeffs/numbers.h>
41#include <coeffs/longrat.h>
42
43#include <polys/monomials/ring.h>
44#include <polys/monomials/p_polys.h>
45#include <polys/simpleideals.h>
46
47#include <polys/ext_fields/algext.h>
48
49/// our type has been defined as a macro in algext.h
50/// and is accessible by 'naID'
51
52/// forward declarations
53BOOLEAN  naGreaterZero(number a, const coeffs cf); 
54BOOLEAN  naGreater(number a, number b, const coeffs cf);
55BOOLEAN  naEqual(number a, number b, const coeffs cf);
56BOOLEAN  naIsOne(number a, const coeffs cf);
57BOOLEAN  naIsMOne(number a, const coeffs cf);
58BOOLEAN  naIsZero(number a, const coeffs cf);
59number   naInit(int i, const coeffs cf);
60int      naInt(number &a, const coeffs cf);
61number   naNeg(number a, const coeffs cf);
62number   naInvers(number a, const coeffs cf);
63number   naPar(int i, const coeffs cf);
64number   naAdd(number a, number b, const coeffs cf);
65number   naSub(number a, number b, const coeffs cf);
66number   naMult(number a, number b, const coeffs cf);
67number   naDiv(number a, number b, const coeffs cf);
68void     naPower(number a, int exp, number *b, const coeffs cf);
69number   naCopy(number a, const coeffs cf);
70void     naWrite(number &a, const coeffs cf);
71number   naRePart(number a, const coeffs cf);
72number   naImPart(number a, const coeffs cf);
73number   naGetDenom(number &a, const coeffs cf);
74number   naGetNumerator(number &a, const coeffs cf);
75number   naGcd(number a, number b, const coeffs cf);
76number   naLcm(number a, number b, const coeffs cf);
77int      naSize(number a, const coeffs cf);
78void     naDelete(number *a, const coeffs cf);
79void     naCoeffWrite(const coeffs cf);
80number   naIntDiv(number a, number b, const coeffs cf);
81const char * naRead(const char *s, number *a, const coeffs cf);
82static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param);
83
84#ifdef LDEBUG
85BOOLEAN naDBTest(number a, const char *f, const int l, const coeffs cf)
86{
87  assume(getCoeffType(cf) == naID);
88  if (a == NULL) return TRUE;
89  p_Test((poly)a, naRing);
90  assume(p_Deg((poly)a, naRing) <= p_Deg(naMinpoly, naRing));
91  return TRUE;
92}
93#endif
94
95void heuristicReduce(poly &p, poly reducer, const coeffs cf);
96void definiteReduce(poly &p, poly reducer, const coeffs cf);
97
98/* returns the bottom field in this field extension tower; if the tower
99   is flat, i.e., if there is no extension, then r itself is returned;
100   as a side-effect, the counter 'height' is filled with the height of
101   the extension tower (in case the tower is flat, 'height' is zero) */
102static coeffs nCoeff_bottom(const coeffs r, int &height)
103{
104  assume(r != NULL);
105  coeffs cf = r;
106  height = 0;
107  while (nCoeff_is_Extension(cf))
108  {
109    assume(cf->extRing != NULL); assume(cf->extRing->cf != NULL);
110    cf = cf->extRing->cf;
111    height++;
112  }
113  return cf;
114}
115
116BOOLEAN naIsZero(number a, const coeffs cf)
117{
118  naTest(a);
119  return (a == NULL);
120}
121
122void naDelete(number * a, const coeffs cf)
123{
124  if (*a == NULL) return;
125  poly aAsPoly = (poly)(*a);
126  p_Delete(&aAsPoly, naRing);
127  *a = NULL;
128}
129
130BOOLEAN naEqual (number a, number b, const coeffs cf)
131{
132  naTest(a); naTest(b);
133 
134  /// simple tests
135  if (a == b) return TRUE;
136  if ((a == NULL) && (b != NULL)) return FALSE;
137  if ((b == NULL) && (a != NULL)) return FALSE;
138
139  /// deg test
140  int aDeg = 0;
141  if (a != NULL) aDeg = p_Deg((poly)a, naRing);
142  int bDeg = 0;
143  if (b != NULL) bDeg = p_Deg((poly)b, naRing);
144  if (aDeg != bDeg) return FALSE;
145 
146  /// subtraction test
147  number c = naSub(a, b, cf);
148  BOOLEAN result = naIsZero(c, cf);
149  naDelete(&c, naCoeffs);
150  return result;
151}
152
153number naCopy(number a, const coeffs cf)
154{
155  naTest(a);
156  if (a == NULL) return NULL;
157  return (number)p_Copy((poly)a, naRing);
158}
159
160number naGetNumerator(number &a, const coeffs cf)
161{
162  return naCopy(a, cf);
163}
164
165number naGetDenom(number &a, const coeffs cf)
166{
167  naTest(a);
168  return naInit(1, cf);
169}
170
171BOOLEAN naIsOne(number a, const coeffs cf)
172{
173  naTest(a);
174  if (p_GetExp((poly)a, 1, naRing) != 0) return FALSE;
175  return n_IsOne(p_GetCoeff((poly)a, naRing), naCoeffs);
176}
177
178BOOLEAN naIsMOne(number a, const coeffs cf)
179{
180  naTest(a);
181  if (p_GetExp((poly)a, 1, naRing) != 0) return FALSE;
182  return n_IsMOne(p_GetCoeff((poly)a, naRing), naCoeffs);
183}
184
185/// this is in-place, modifies a
186number naNeg(number a, const coeffs cf)
187{
188  naTest(a);
189  if (a != NULL) a = (number)p_Neg((poly)a, naRing);
190  return a;
191}
192
193number naImPart(number a, const coeffs cf)
194{
195  naTest(a);
196  return NULL;
197}
198
199number naInit(int i, const coeffs cf)
200{
201  if (i == 0) return NULL;
202  else        return (number)p_ISet(i, naRing);
203}
204
205int naInt(number &a, const coeffs cf)
206{
207  naTest(a);
208  if (p_GetExp((poly)a, 1, naRing) != 0) return 0;
209  return n_Int(p_GetCoeff((poly)a, naRing), naCoeffs);
210}
211
212/* TRUE iff (a != 0 and (b == 0 or deg(a) > deg(b))) */
213BOOLEAN naGreater(number a, number b, const coeffs cf)
214{
215  if (naIsZero(a, cf)) return FALSE;
216  if (naIsZero(b, cf)) return TRUE;
217  int aDeg = 0;
218  if (a != NULL) aDeg = p_Deg((poly)a, naRing);
219  int bDeg = 0;
220  if (b != NULL) bDeg = p_Deg((poly)b, naRing);
221  return (aDeg > bDeg);
222}
223
224/* TRUE iff a != 0 and (LC(a) > 0 or deg(a) > 0) */
225BOOLEAN naGreaterZero(number a, const coeffs cf)
226{
227  naTest(a);
228  if (a == NULL)                                            return FALSE;
229  if (n_GreaterZero(p_GetCoeff((poly)a, naRing), naCoeffs)) return TRUE;
230  if (p_Deg((poly)a, naRing) > 0)                           return TRUE;
231  return FALSE;
232}
233
234void naCoeffWrite(const coeffs cf)
235{
236  char *x = rRingVar(0, naRing);
237  Print("//   Coefficients live in the extension field K[%s]/<f(%s)>\n", x, x);
238  Print("//   with the minimal polynomial f(%s) = %s\n", x,
239        p_String(naMinpoly, naRing));
240  PrintS("//   and K: "); n_CoeffWrite(cf->extRing->cf);
241}
242
243number naPar(int i, const coeffs cf)
244{
245  assume(i == 1);   // there is only one parameter in this extension field
246  poly p = p_ISet(1, naRing);   // p = 1
247  p_SetExp(p, 1, 1, naRing);    // p = the sole extension variable
248  p_Setm(p, naRing);
249  return (number)p;
250}
251
252number naAdd(number a, number b, const coeffs cf)
253{
254  naTest(a); naTest(b);
255  if (a == NULL) return naCopy(b, cf);
256  if (b == NULL) return naCopy(a, cf);
257  poly aPlusB = p_Add_q(p_Copy((poly)a, naRing),
258                        p_Copy((poly)b, naRing), naRing);
259  definiteReduce(aPlusB, naMinpoly, cf);
260  return (number)aPlusB;
261}
262
263number naSub(number a, number b, const coeffs cf)
264{
265  naTest(a); naTest(b);
266  if (b == NULL) return naCopy(a, cf);
267  poly minusB = p_Neg(p_Copy((poly)b, naRing), naRing);
268  if (a == NULL) return (number)minusB;
269  poly aMinusB = p_Add_q(p_Copy((poly)a, naRing), minusB, naRing);
270  definiteReduce(aMinusB, naMinpoly, cf);
271  return (number)aMinusB;
272}
273
274number naMult(number a, number b, const coeffs cf)
275{
276  naTest(a); naTest(b);
277  if (a == NULL) return NULL;
278  if (b == NULL) return NULL;
279  poly aTimesB = p_Mult_q(p_Copy((poly)a, naRing),
280                          p_Copy((poly)b, naRing), naRing);
281  definiteReduce(aTimesB, naMinpoly, cf);
282  return (number)aTimesB;
283}
284
285number naDiv(number a, number b, const coeffs cf)
286{
287  naTest(a); naTest(b);
288  if (b == NULL) WerrorS(nDivBy0);
289  if (a == NULL) return NULL;
290  poly bInverse = (poly)naInvers(b, cf);
291  poly aDivB = p_Mult_q(p_Copy((poly)a, naRing), bInverse, naRing);
292  definiteReduce(aDivB, naMinpoly, cf);
293  return (number)aDivB;
294}
295
296/* 0^0 = 0;
297   for |exp| <= 7 compute power by a simple multiplication loop;
298   for |exp| >= 8 compute power along binary presentation of |exp|, e.g.
299      p^13 = p^1 * p^4 * p^8, where we utilise that
300      p^(2^(k+1)) = p^(2^k) * p^(2^k)
301   intermediate reduction modulo the minimal polynomial is controlled by
302   the in-place method heuristicReduce(poly, poly, coeffs); see there.
303*/
304void naPower(number a, int exp, number *b, const coeffs cf)
305{
306  naTest(a);
307 
308  /* special cases first */
309  if (a == NULL)
310  {
311    if (exp >= 0) *b = NULL;
312    else          WerrorS(nDivBy0);
313  }
314  else if (exp ==  0) *b = naInit(1, cf);
315  else if (exp ==  1) *b = naCopy(a, cf);
316  else if (exp == -1) *b = naInvers(a, cf);
317 
318  int expAbs = exp; if (expAbs < 0) expAbs = -expAbs;
319 
320  /* now compute 'a' to the 'expAbs'-th power */
321  poly pow; poly aAsPoly = (poly)a;
322  if (expAbs <= 7)
323  {
324    pow = p_Copy(aAsPoly, naRing);
325    for (int i = 2; i <= expAbs; i++)
326    {
327      pow = p_Mult_q(pow, p_Copy(aAsPoly, naRing), naRing);
328      heuristicReduce(pow, naMinpoly, cf);
329    }
330    definiteReduce(pow, naMinpoly, cf);
331  }
332  else
333  {
334    pow = p_ISet(1, naRing);
335    poly factor = p_Copy(aAsPoly, naRing);
336    while (expAbs != 0)
337    {
338      if (expAbs & 1)
339      {
340        pow = p_Mult_q(pow, p_Copy(factor, naRing), naRing);
341        heuristicReduce(pow, naMinpoly, cf);
342      }
343      expAbs = expAbs / 2;
344      if (expAbs != 0)
345      {
346        factor = p_Mult_q(factor, factor, naRing);
347        heuristicReduce(factor, naMinpoly, cf);
348      }
349    }
350    p_Delete(&factor, naRing);
351    definiteReduce(pow, naMinpoly, cf);
352  }
353 
354  /* invert if original exponent was negative */
355  number n = (number)pow;
356  if (exp < 0)
357  {
358    number m = naInvers(n, cf);
359    naDelete(&n, cf);
360    n = m;
361  }
362  *b = n;
363}
364
365/* may reduce p module the reducer by calling definiteReduce;
366   the decision is made based on the following heuristic
367   (which should also only be changed here in this method):
368      if (deg(p) > 10*deg(reducer) then perform reduction;
369   modifies p */
370void heuristicReduce(poly &p, poly reducer, const coeffs cf)
371{
372  #ifdef LDEBUG
373  p_Test((poly)p, naRing);
374  p_Test((poly)reducer, naRing);
375  #endif
376  if (p_Deg(p, naRing) > 10 * p_Deg(reducer, naRing))
377    definiteReduce(p, reducer, cf);
378}
379
380void naWrite(number &a, const coeffs cf)
381{
382  naTest(a);
383  if (a == NULL)
384    StringAppendS("0");
385  else
386  {
387    poly aAsPoly = (poly)a;
388    /* basically, just write aAsPoly using p_Write,
389       but use brackets around the output, if a is not
390       a constant living in naCoeffs = cf->extRing->cf */
391    BOOLEAN useBrackets = !(p_IsConstant(aAsPoly, naRing));
392    if (useBrackets) StringAppendS("(");
393    p_String0(aAsPoly, naRing, naRing);
394    if (useBrackets) StringAppendS(")");
395  }
396}
397
398const char * naRead(const char *s, number *a, const coeffs cf)
399{
400  poly aAsPoly;
401  const char * result = p_Read(s, aAsPoly, naRing);
402  *a = (number)aAsPoly;
403  return result;
404}
405
406/* implemented by the rule lcm(a, b) = a * b / gcd(a, b) */
407number naLcm(number a, number b, const coeffs cf)
408{
409  naTest(a); naTest(b);
410  if (a == NULL) return NULL;
411  if (b == NULL) return NULL;
412  number theProduct = (number)p_Mult_q(p_Copy((poly)a, naRing),
413                                       p_Copy((poly)b, naRing), naRing);
414  /* note that theProduct needs not be reduced w.r.t. naMinpoly;
415     but the final division will take care of the necessary reduction */
416  number theGcd = naGcd(a, b, cf);
417  return naDiv(theProduct, theGcd, cf);
418}
419
420/* expects *param to be castable to AlgExtInfo */
421static BOOLEAN naCoeffIsEqual(const coeffs cf, n_coeffType n, void * param)
422{
423  if (naID != n) return FALSE;
424  AlgExtInfo *e = (AlgExtInfo *)param;
425  /* for extension coefficient fields we expect the underlying
426     polynomials rings to be IDENTICAL, i.e. the SAME OBJECT;
427     this expectation is based on the assumption that we have properly
428     registered cf and perform reference counting rather than creating
429     multiple copies of the same coefficient field/domain/ring */
430  return (naRing == e->r);
431  /* (Note that then also the minimal ideals will necessarily be
432     the same, as they are attached to the ring.) */
433}
434
435int naSize(number a, const coeffs cf)
436{
437  if (a == NULL) return -1;
438  /* this has been taken from the old implementation of field extensions,
439     where we computed the sum of the degree and the number of terms in
440     (poly)a; so we leave it at that, for the time being;
441     maybe, the number of terms alone is a better measure? */
442  poly aAsPoly = (poly)a;
443  int theDegree = 0; int noOfTerms = 0;
444  while (aAsPoly != NULL)
445  {
446    noOfTerms++;
447    int d = 0;
448    for (int i = 1; i <= rVar(naRing); i++)
449      d += p_GetExp(aAsPoly, i, naRing);
450    if (d > theDegree) theDegree = d;
451    pIter(aAsPoly);
452  }
453  return theDegree + noOfTerms;
454}
455
456/* performs polynomial division and overrides p by the remainder
457   of division of p by the reducer;
458   modifies p */
459void definiteReduce(poly &p, poly reducer, const coeffs cf)
460{
461  #ifdef LDEBUG
462  p_Test((poly)p, naRing);
463  p_Test((poly)reducer, naRing);
464  #endif
465  p_PolyDiv(p, reducer, FALSE, naRing);
466}
467
468/* IMPORTANT NOTE: Since an algebraic field extension is again a field,
469                   the gcd of two elements is not very interesting. (It
470                   is actually any unit in the field, i.e., any non-
471                   zero element.) Note that the below method does not operate
472                   in this strong sense but rather computes the gcd of
473                   two given elements in the underlying polynomial ring. */
474number naGcd(number a, number b, const coeffs cf)
475{
476  naTest(a); naTest(b);
477  if ((a == NULL) && (b == NULL)) WerrorS(nDivBy0);
478  return (number)p_Gcd((poly)a, (poly)b, naRing);
479}
480
481number naInvers(number a, const coeffs cf)
482{
483  naTest(a);
484  if (a == NULL) WerrorS(nDivBy0);
485  poly aFactor = NULL; poly mFactor = NULL;
486  poly theGcd = p_ExtGcd((poly)a, aFactor, naMinpoly, mFactor, naRing);
487  naTest((number)theGcd); naTest((number)aFactor); naTest((number)mFactor);
488  /* the gcd must be 1 since naMinpoly is irreducible and a != NULL: */
489  assume(naIsOne((number)theGcd, cf));     
490  p_Delete(&theGcd, naRing);
491  p_Delete(&mFactor, naRing);
492  return (number)(aFactor);
493}
494
495/* assumes that src = Q, dst = Q(a) */
496number naMap00(number a, const coeffs src, const coeffs dst)
497{
498  assume(src == dst->extRing->cf);
499  poly result = p_One(dst->extRing);
500  p_SetCoeff(result, naCopy(a, src), dst->extRing);
501  return (number)result;
502}
503
504/* assumes that src = Z/p, dst = Q(a) */
505number naMapP0(number a, const coeffs src, const coeffs dst)
506{
507  /* mapping via intermediate int: */
508  int n = n_Int(a, src);
509  number q = n_Init(n, dst->extRing->cf);
510  poly result = p_One(dst->extRing);
511  p_SetCoeff(result, q, dst->extRing);
512  return (number)result;
513}
514
515/* assumes that either src = Q(a), dst = Q(a), or
516                       src = Zp(a), dst = Zp(a)     */
517number naCopyMap(number a, const coeffs src, const coeffs dst)
518{
519  return naCopy(a, dst);
520}
521
522/* assumes that src = Q, dst = Z/p(a) */
523number naMap0P(number a, const coeffs src, const coeffs dst)
524{
525  int p = rChar(dst->extRing);
526  int n = nlModP(a, p, src);
527  number q = n_Init(n, dst->extRing->cf);
528  poly result = p_One(dst->extRing);
529  p_SetCoeff(result, q, dst->extRing);
530  return (number)result;
531}
532
533/* assumes that src = Z/p, dst = Z/p(a) */
534number naMapPP(number a, const coeffs src, const coeffs dst)
535{
536  assume(src == dst->extRing->cf);
537  poly result = p_One(dst->extRing);
538  p_SetCoeff(result, naCopy(a, src), dst->extRing);
539  return (number)result;
540}
541
542/* assumes that src = Z/u, dst = Z/p(a), where u != p */
543number naMapUP(number a, const coeffs src, const coeffs dst)
544{
545  /* mapping via intermediate int: */
546  int n = n_Int(a, src);
547  number q = n_Init(n, dst->extRing->cf);
548  poly result = p_One(dst->extRing);
549  p_SetCoeff(result, q, dst->extRing);
550  return (number)result;
551}
552
553nMapFunc naSetMap(const coeffs src, const coeffs dst)
554{
555  /* dst is expected to be an algebraic field extension */
556  assume(getCoeffType(dst) == n_algExt);
557 
558  int h = 0; /* the height of the extension tower given by dst */
559  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
560 
561  /* for the time being, we only provide maps if h = 1 and if b is Q or
562     some field Z/pZ: */
563  if (h != 1) return NULL;
564  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
565 
566  if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
567    return naMap00;                                      /// Q     -->  Q(a)
568 
569  if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
570    return naMapP0;                                      /// Z/p   -->  Q(a)
571 
572  if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
573    return naMap0P;                                      /// Q      --> Z/p(a)
574 
575  if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
576  {
577    if (src->ch == dst->ch) return naMapPP;              /// Z/p    --> Z/p(a)
578    else return naMapUP;                                 /// Z/u    --> Z/p(a)
579  }
580 
581  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
582  if (h != 1) return NULL;
583  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
584 
585  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
586  {
587    if (strcmp(rParameter(src->extRing)[0],
588               rParameter(dst->extRing)[0]) == 0)
589      return naCopyMap;                                  /// Q(a)   --> Q(a)
590    else
591      return NULL;                                       /// Q(b)   --> Q(a)
592  }
593 
594  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
595  {
596    if (strcmp(rParameter(src->extRing)[0],
597               rParameter(dst->extRing)[0]) == 0)
598      return naCopyMap;                                  /// Z/p(a) --> Z/p(a)
599    else
600      return NULL;                                       /// Z/p(b) --> Z/p(a)
601  }
602 
603  return NULL;                                           /// default
604}
605
606BOOLEAN naInitChar(coeffs cf, void * infoStruct)
607{
608  assume( getCoeffType(cf) == naID );
609 
610  AlgExtInfo *e = (AlgExtInfo *)infoStruct;
611  /// first check whether cf->extRing != NULL and delete old ring???
612  cf->extRing           = e->r;
613  cf->extRing->minideal = e->i;
614
615  assume(cf->extRing                     != NULL);      // extRing;
616  assume((cf->extRing->minideal          != NULL) &&    // minideal has one
617         (IDELEMS(cf->extRing->minideal) != 0)    &&    // non-zero generator
618         (cf->extRing->minideal->m[0]    != NULL)    ); // at m[0];
619  assume(cf->extRing->cf                 != NULL);      // extRing->cf;
620  assume(getCoeffType(cf) == naID);                     // coeff type;
621 
622  /* propagate characteristic up so that it becomes
623     directly accessible in cf: */
624  cf->ch = cf->extRing->cf->ch;
625 
626  #ifdef LDEBUG
627  p_Test((poly)naMinpoly, naRing);
628  #endif
629 
630  cf->cfGreaterZero  = naGreaterZero;
631  cf->cfGreater      = naGreater;
632  cf->cfEqual        = naEqual;
633  cf->cfIsZero       = naIsZero;
634  cf->cfIsOne        = naIsOne;
635  cf->cfIsMOne       = naIsMOne;
636  cf->cfInit         = naInit;
637  cf->cfInt          = naInt;
638  cf->cfNeg          = naNeg;
639  cf->cfPar          = naPar;
640  cf->cfAdd          = naAdd;
641  cf->cfSub          = naSub;
642  cf->cfMult         = naMult;
643  cf->cfDiv          = naDiv;
644  cf->cfExactDiv     = naDiv;
645  cf->cfPower        = naPower;
646  cf->cfCopy         = naCopy;
647  cf->cfWrite        = naWrite;
648  cf->cfRead         = naRead;
649  cf->cfDelete       = naDelete;
650  cf->cfSetMap       = naSetMap;
651  cf->cfGetDenom     = naGetDenom;
652  cf->cfGetNumerator = naGetNumerator;
653  cf->cfRePart       = naCopy;
654  cf->cfImPart       = naImPart;
655  cf->cfCoeffWrite   = naCoeffWrite;
656  cf->cfDBTest       = naDBTest;
657  cf->cfGcd          = naGcd;
658  cf->cfLcm          = naLcm;
659  cf->cfSize         = naSize;
660  cf->nCoeffIsEqual  = naCoeffIsEqual;
661  cf->cfInvers       = naInvers;
662  cf->cfIntDiv       = naDiv;
663 
664  return FALSE;
665}
Note: See TracBrowser for help on using the repository browser.