source: git/libpolys/polys/ext_fields/transext.cc @ 06df101

spielwiese
Last change on this file since 06df101 was 06df101, checked in by Frank Seelisch <seelisch@…>, 13 years ago
handled nested fractions (when over Q), found bug in longrat.cc (see coeffs_test.h:507)
  • Property mode set to 100644
File size: 34.4 KB
RevLine 
[6ccdd3a]1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5/*
[2c7f28]6* ABSTRACT: numbers in a rational function field K(t_1, .., t_s) with
7*           transcendental variables t_1, ..., t_s, where s >= 1.
8*           Denoting the implemented coeffs object by cf, then these numbers
[06df101]9*           are represented as quotients of polynomials living in the
10*           polynomial ring K[t_1, .., t_s] represented by cf->extring.
11*
12*           An element of K(t_1, .., t_s) may have numerous representations,
13*           due to the possibility of common polynomial factors in the
14*           numerator and denominator. This problem is handled by a
15*           cancellation heuristic: Each number "knows" its complexity
16*           which is 0 if and only if common factors have definitely been
17*           cancelled, and some positive integer otherwise.
18*           Each arithmetic operation of two numbers with complexities c1
19*           and c2 will result in a number of complexity c1 + c2 + some
20*           penalty (specific for each arithmetic operation; see constants
21*           in the *.h file). Whenever the resulting complexity exceeds a
22*           certain threshold (see constant in the *.h file), then the
23*           cancellation heuristic will call 'factory' to compute the gcd
24*           and cancel it out in the given number. (This definite cancel-
25*           lation will also be performed at the beginning of ntWrite,
26*           ensuring that any output is free of common factors.
27*           For the special case of K = Q (i.e., when computing over the
28*           rationals), this definite cancellation procedure will also take
29*           care of nested fractions: If there are fractional coefficients
30*           in the numerator or denominator of a number, then this number
31*           is being replaced by a quotient of two polynomials over Z, or
32*           - if the denominator is a constant - by a polynomial over Q.
[6ccdd3a]33*/
34
35#include "config.h"
36#include <misc/auxiliary.h>
37
38#include <omalloc/omalloc.h>
39
40#include <reporter/reporter.h>
41
42#include <coeffs/coeffs.h>
43#include <coeffs/numbers.h>
44#include <coeffs/longrat.h>
45
46#include <polys/monomials/ring.h>
47#include <polys/monomials/p_polys.h>
48#include <polys/simpleideals.h>
49
[e5d267]50#ifdef HAVE_FACTORY
51#include <polys/clapsing.h>
52#endif
53
[6ccdd3a]54#include <polys/ext_fields/transext.h>
55
56/// our type has been defined as a macro in transext.h
57/// and is accessible by 'ntID'
58
[de90c01]59extern omBin fractionObjectBin = omGetSpecBin(sizeof(fractionObject));
60
[6ccdd3a]61/// forward declarations
62BOOLEAN  ntGreaterZero(number a, const coeffs cf); 
63BOOLEAN  ntGreater(number a, number b, const coeffs cf);
64BOOLEAN  ntEqual(number a, number b, const coeffs cf);
65BOOLEAN  ntIsOne(number a, const coeffs cf);
66BOOLEAN  ntIsMOne(number a, const coeffs cf);
67BOOLEAN  ntIsZero(number a, const coeffs cf);
68number   ntInit(int i, const coeffs cf);
69int      ntInt(number &a, const coeffs cf);
70number   ntNeg(number a, const coeffs cf);
71number   ntInvers(number a, const coeffs cf);
72number   ntPar(int i, const coeffs cf);
73number   ntAdd(number a, number b, const coeffs cf);
74number   ntSub(number a, number b, const coeffs cf);
75number   ntMult(number a, number b, const coeffs cf);
76number   ntDiv(number a, number b, const coeffs cf);
77void     ntPower(number a, int exp, number *b, const coeffs cf);
78number   ntCopy(number a, const coeffs cf);
79void     ntWrite(number &a, const coeffs cf);
80number   ntRePart(number a, const coeffs cf);
81number   ntImPart(number a, const coeffs cf);
82number   ntGetDenom(number &a, const coeffs cf);
83number   ntGetNumerator(number &a, const coeffs cf);
84number   ntGcd(number a, number b, const coeffs cf);
85number   ntLcm(number a, number b, const coeffs cf);
[2c7f28]86int      ntSize(number a, const coeffs cf);
[6ccdd3a]87void     ntDelete(number * a, const coeffs cf);
88void     ntCoeffWrite(const coeffs cf);
89number   ntIntDiv(number a, number b, const coeffs cf);
90const char * ntRead(const char *s, number *a, const coeffs cf);
91static BOOLEAN ntCoeffIsEqual(const coeffs cf, n_coeffType n, void * param);
92
[2c7f28]93void heuristicGcdCancellation(number a, const coeffs cf);
[010f3b]94void definiteGcdCancellation(number a, const coeffs cf,
[06df101]95                             BOOLEAN simpleTestsHaveAlreadyBeenPerformed);
96void handleNestedFractionsOverQ(fraction f, const coeffs cf);
[2c7f28]97
[6ccdd3a]98#ifdef LDEBUG
99BOOLEAN ntDBTest(number a, const char *f, const int l, const coeffs cf)
100{
101  assume(getCoeffType(cf) == ntID);
[2c7f28]102  fraction t = (fraction)a;
[e5d267]103  if (IS0(t)) return TRUE;
104  assume(NUM(t) != NULL);   /**< t != 0 ==> numerator(t) != 0 */
105  p_Test(NUM(t), ntRing);
106  if (!DENIS1(t)) p_Test(DEN(t), ntRing);
[6ccdd3a]107  return TRUE;
108}
109#endif
110
111/* returns the bottom field in this field extension tower; if the tower
112   is flat, i.e., if there is no extension, then r itself is returned;
113   as a side-effect, the counter 'height' is filled with the height of
114   the extension tower (in case the tower is flat, 'height' is zero) */
115static coeffs nCoeff_bottom(const coeffs r, int &height)
116{
117  assume(r != NULL);
118  coeffs cf = r;
119  height = 0;
120  while (nCoeff_is_Extension(cf))
121  {
122    assume(cf->extRing != NULL); assume(cf->extRing->cf != NULL);
123    cf = cf->extRing->cf;
124    height++;
125  }
126  return cf;
127}
128
[2c7f28]129BOOLEAN ntIsZero(number a, const coeffs cf)
[6ccdd3a]130{
[2c7f28]131  ntTest(a);
[e5d267]132  return (IS0(a));
[6ccdd3a]133}
134
[2c7f28]135void ntDelete(number * a, const coeffs cf)
[6ccdd3a]136{
[2c7f28]137  fraction f = (fraction)(*a);
[e5d267]138  if (IS0(f)) return;
139  p_Delete(&NUM(f), ntRing);
140  if (!DENIS1(f)) p_Delete(&DEN(f), ntRing);
[2c7f28]141  omFreeBin((ADDRESS)f, fractionObjectBin);
[6ccdd3a]142  *a = NULL;
143}
144
[2c7f28]145BOOLEAN ntEqual(number a, number b, const coeffs cf)
[6ccdd3a]146{
[2c7f28]147  ntTest(a); ntTest(b);
[6ccdd3a]148 
149  /// simple tests
150  if (a == b) return TRUE;
[e5d267]151  if ((IS0(a)) && (!IS0(b))) return FALSE;
152  if ((IS0(b)) && (!IS0(a))) return FALSE;
[2c7f28]153 
154  /// cheap test if gcd's have been cancelled in both numbers
155  fraction fa = (fraction)a;
156  fraction fb = (fraction)b;
[e5d267]157  if ((COM(fa) == 1) && (COM(fb) == 1))
[2c7f28]158  {
[e5d267]159    poly f = p_Add_q(p_Copy(NUM(fa), ntRing),
160                     p_Neg(p_Copy(NUM(fb), ntRing), ntRing),
[2c7f28]161                     ntRing);
162    if (f != NULL) { p_Delete(&f, ntRing); return FALSE; }
[e5d267]163    if (DENIS1(fa) && DENIS1(fb))  return TRUE;
164    if (DENIS1(fa) && !DENIS1(fb)) return FALSE;
165    if (!DENIS1(fa) && DENIS1(fb)) return FALSE;
166    f = p_Add_q(p_Copy(DEN(fa), ntRing),
167                p_Neg(p_Copy(DEN(fb), ntRing), ntRing),
[2c7f28]168                ntRing);
169    if (f != NULL) { p_Delete(&f, ntRing); return FALSE; }
170    return TRUE;
171  }
[6ccdd3a]172 
[2c7f28]173  /* default: the more expensive multiplication test
174              a/b = c/d  <==>  a*d = b*c */
[e5d267]175  poly f = p_Copy(NUM(fa), ntRing);
176  if (!DENIS1(fb)) f = p_Mult_q(f, p_Copy(DEN(fb), ntRing), ntRing);
177  poly g = p_Copy(NUM(fb), ntRing);
178  if (!DENIS1(fa)) g = p_Mult_q(g, p_Copy(DEN(fa), ntRing), ntRing);
[2c7f28]179  poly h = p_Add_q(f, p_Neg(g, ntRing), ntRing);
180  if (h == NULL) return TRUE;
181  else
182  {
183    p_Delete(&h, ntRing);
184    return FALSE;
185  }
[6ccdd3a]186}
187
[2c7f28]188number ntCopy(number a, const coeffs cf)
[6ccdd3a]189{
[2c7f28]190  ntTest(a);
[e5d267]191  if (IS0(a)) return NULL;
[2c7f28]192  fraction f = (fraction)a;
[e5d267]193  poly g = p_Copy(NUM(f), ntRing);
194  poly h = NULL; if (!DENIS1(f)) h = p_Copy(DEN(f), ntRing);
[2c7f28]195  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]196  NUM(result) = g;
197  DEN(result) = h;
198  COM(result) = COM(f);
[2c7f28]199  return (number)result;
[6ccdd3a]200}
201
[2c7f28]202number ntGetNumerator(number &a, const coeffs cf)
[6ccdd3a]203{
[2c7f28]204  ntTest(a);
[010f3b]205  definiteGcdCancellation(a, cf, FALSE);
[e5d267]206  if (IS0(a)) return NULL;
[2c7f28]207  fraction f = (fraction)a;
[e5d267]208  poly g = p_Copy(NUM(f), ntRing);
[2c7f28]209  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]210  NUM(result) = g;
211  DEN(result) = NULL;
212  COM(result) = 0;
[2c7f28]213  return (number)result;
[6ccdd3a]214}
215
[2c7f28]216number ntGetDenom(number &a, const coeffs cf)
[6ccdd3a]217{
[2c7f28]218  ntTest(a);
[010f3b]219  definiteGcdCancellation(a, cf, FALSE);
[2c7f28]220  fraction f = (fraction)a;
221  poly g;
[e5d267]222  if (IS0(f) || DENIS1(f)) g = p_One(ntRing);
223  else g = p_Copy(DEN(f), ntRing);
[2c7f28]224  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]225  NUM(result) = g;
226  DEN(result) = NULL;
227  COM(result) = 0;
[2c7f28]228  return (number)result;
[6ccdd3a]229}
230
[2c7f28]231BOOLEAN ntIsOne(number a, const coeffs cf)
[6ccdd3a]232{
[2c7f28]233  ntTest(a);
[010f3b]234  definiteGcdCancellation(a, cf, FALSE);
[2c7f28]235  fraction f = (fraction)a;
[e5d267]236  return DENIS1(f) && NUMIS1(f);
[6ccdd3a]237}
238
[2c7f28]239BOOLEAN ntIsMOne(number a, const coeffs cf)
[6ccdd3a]240{
[2c7f28]241  ntTest(a);
[010f3b]242  definiteGcdCancellation(a, cf, FALSE);
[2c7f28]243  fraction f = (fraction)a;
[e5d267]244  if (!DENIS1(f)) return FALSE;
245  poly g = NUM(f);
[2c7f28]246  if (!p_IsConstant(g, ntRing)) return FALSE;
247  return n_IsMOne(p_GetCoeff(g, ntRing), ntCoeffs);
[6ccdd3a]248}
249
250/// this is in-place, modifies a
[2c7f28]251number ntNeg(number a, const coeffs cf)
[6ccdd3a]252{
[2c7f28]253  ntTest(a);
[e5d267]254  if (!IS0(a))
[2c7f28]255  {
256    fraction f = (fraction)a;
[e5d267]257    NUM(f) = p_Neg(NUM(f), ntRing);
[2c7f28]258  }
[6ccdd3a]259  return a;
260}
261
[2c7f28]262number ntImPart(number a, const coeffs cf)
[6ccdd3a]263{
[2c7f28]264  ntTest(a);
[6ccdd3a]265  return NULL;
266}
267
[2c7f28]268number ntInit(int i, const coeffs cf)
[6ccdd3a]269{
270  if (i == 0) return NULL;
[2c7f28]271  else
272  {
273    fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]274    NUM(result) = p_ISet(i, ntRing);
275    DEN(result) = NULL;
276    COM(result) = 0;
[2c7f28]277    return (number)result;
278  }
[6ccdd3a]279}
280
[2c7f28]281int ntInt(number &a, const coeffs cf)
[6ccdd3a]282{
[2c7f28]283  ntTest(a);
[e5d267]284  if (IS0(a)) return 0;
[010f3b]285  definiteGcdCancellation(a, cf, FALSE);
[2c7f28]286  fraction f = (fraction)a;
[e5d267]287  if (!DENIS1(f)) return 0;
288  if (!p_IsConstant(NUM(f), ntRing)) return 0;
289  return n_Int(p_GetCoeff(NUM(f), ntRing), ntCoeffs);
[2c7f28]290}
291
292/* This method will only consider the numerators of a and b, without
293   cancelling gcd's before.
294   Moreover it may return TRUE only if one or both numerators
295   are zero or if their degrees are equal. Then TRUE is returned iff
296   coeff(numerator(a)) > coeff(numerator(b));
297   In all other cases, FALSE will be returned. */
298BOOLEAN ntGreater(number a, number b, const coeffs cf)
299{
300  ntTest(a); ntTest(b);
301  number aNumCoeff = NULL; int aNumDeg = 0;
302  number bNumCoeff = NULL; int bNumDeg = 0;
[e5d267]303  if (!IS0(a))
[2c7f28]304  {
305    fraction fa = (fraction)a;
[e5d267]306    aNumDeg = p_Totaldegree(NUM(fa), ntRing);
307    aNumCoeff = p_GetCoeff(NUM(fa), ntRing);
[2c7f28]308  }
[e5d267]309  if (!IS0(b))
[2c7f28]310  {
311    fraction fb = (fraction)b;
[e5d267]312    bNumDeg = p_Totaldegree(NUM(fb), ntRing);
313    bNumCoeff = p_GetCoeff(NUM(fb), ntRing);
[2c7f28]314  }
315  if (aNumDeg != bNumDeg) return FALSE;
316  else return n_Greater(aNumCoeff, bNumCoeff, ntCoeffs);
[6ccdd3a]317}
318
[2c7f28]319/* this method will only consider the numerator of a, without cancelling
320   the gcd before;
321   returns TRUE iff the leading coefficient of the numerator of a is > 0
322                    or the leading term of the numerator of a is not a
323                    constant */
324BOOLEAN ntGreaterZero(number a, const coeffs cf)
[6ccdd3a]325{
[2c7f28]326  ntTest(a);
[e5d267]327  if (IS0(a)) return FALSE;
[2c7f28]328  fraction f = (fraction)a;
[e5d267]329  poly g = NUM(f);
[2c7f28]330  return (n_GreaterZero(p_GetCoeff(g, ntRing), ntCoeffs) ||
331          (!p_LmIsConstant(g, ntRing)));
[6ccdd3a]332}
333
[2c7f28]334void ntCoeffWrite(const coeffs cf)
[6ccdd3a]335{
[2c7f28]336  PrintS("//   Coefficients live in the rational function field\n");
337  Print("//   K(");
338  for (int i = 0; i < rVar(ntRing); i++)
339  {
340    if (i > 0) PrintS(", ");
341    Print("%s", rRingVar(i, ntRing));
342  }
343  PrintS(") with\n");
344  PrintS("//   K: "); n_CoeffWrite(cf->extRing->cf);
[6ccdd3a]345}
346
[2c7f28]347/* the i-th parameter */
348number ntPar(int i, const coeffs cf)
[6ccdd3a]349{
[2c7f28]350  assume((1 <= i) && (i <= rVar(ntRing)));
351  poly p = p_ISet(1, ntRing);
352  p_SetExp(p, i, 1, ntRing);
353  p_Setm(p, ntRing);
354  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]355  NUM(result) = p;
356  DEN(result) = NULL;
357  COM(result) = 0;
[2c7f28]358  return (number)result;
[6ccdd3a]359}
360
[2c7f28]361number ntAdd(number a, number b, const coeffs cf)
[6ccdd3a]362{
[2c7f28]363  ntTest(a); ntTest(b);
[e5d267]364  if (IS0(a)) return ntCopy(b, cf);
365  if (IS0(b)) return ntCopy(a, cf);
[2c7f28]366 
367  fraction fa = (fraction)a;
368  fraction fb = (fraction)b;
[de90c01]369 
[e5d267]370  poly g = p_Copy(NUM(fa), ntRing);
371  if (!DENIS1(fb)) g = p_Mult_q(g, p_Copy(DEN(fb), ntRing), ntRing);
372  poly h = p_Copy(NUM(fb), ntRing);
373  if (!DENIS1(fa)) h = p_Mult_q(h, p_Copy(DEN(fa), ntRing), ntRing);
[de90c01]374  g = p_Add_q(g, h, ntRing);
375 
376  if (g == NULL) return NULL;
377 
[2c7f28]378  poly f;
[e5d267]379  if      (DENIS1(fa) && DENIS1(fb))  f = NULL;
380  else if (!DENIS1(fa) && DENIS1(fb)) f = p_Copy(DEN(fa), ntRing);
381  else if (DENIS1(fa) && !DENIS1(fb)) f = p_Copy(DEN(fb), ntRing);
382  else /* both denom's are != 1 */    f = p_Mult_q(p_Copy(DEN(fa), ntRing),
383                                                   p_Copy(DEN(fb), ntRing),
[2c7f28]384                                                   ntRing);
[de90c01]385 
[2c7f28]386  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]387  NUM(result) = g;
388  DEN(result) = f;
389  COM(result) = COM(fa) + COM(fb) + ADD_COMPLEXITY;
[2c7f28]390  heuristicGcdCancellation((number)result, cf);
391  return (number)result;
[6ccdd3a]392}
393
[2c7f28]394number ntSub(number a, number b, const coeffs cf)
[6ccdd3a]395{
[2c7f28]396  ntTest(a); ntTest(b);
[e5d267]397  if (IS0(a)) return ntNeg(ntCopy(b, cf), cf);
398  if (IS0(b)) return ntCopy(a, cf);
[2c7f28]399 
400  fraction fa = (fraction)a;
401  fraction fb = (fraction)b;
[de90c01]402 
[e5d267]403  poly g = p_Copy(NUM(fa), ntRing);
404  if (!DENIS1(fb)) g = p_Mult_q(g, p_Copy(DEN(fb), ntRing), ntRing);
405  poly h = p_Copy(NUM(fb), ntRing);
406  if (!DENIS1(fa)) h = p_Mult_q(h, p_Copy(DEN(fa), ntRing), ntRing);
[de90c01]407  g = p_Add_q(g, p_Neg(h, ntRing), ntRing);
408 
409  if (g == NULL) return NULL;
410 
[2c7f28]411  poly f;
[e5d267]412  if      (DENIS1(fa) && DENIS1(fb))  f = NULL;
413  else if (!DENIS1(fa) && DENIS1(fb)) f = p_Copy(DEN(fa), ntRing);
414  else if (DENIS1(fa) && !DENIS1(fb)) f = p_Copy(DEN(fb), ntRing);
415  else /* both den's are != 1 */      f = p_Mult_q(p_Copy(DEN(fa), ntRing),
416                                                   p_Copy(DEN(fb), ntRing),
[2c7f28]417                                                   ntRing);
[de90c01]418 
[2c7f28]419  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]420  NUM(result) = g;
421  DEN(result) = f;
422  COM(result) = COM(fa) + COM(fb) + ADD_COMPLEXITY;
[2c7f28]423  heuristicGcdCancellation((number)result, cf);
424  return (number)result;
[6ccdd3a]425}
426
[2c7f28]427number ntMult(number a, number b, const coeffs cf)
[6ccdd3a]428{
[2c7f28]429  ntTest(a); ntTest(b);
[e5d267]430  if (IS0(a) || IS0(b)) return NULL;
[2c7f28]431 
432  fraction fa = (fraction)a;
433  fraction fb = (fraction)b;
[de90c01]434 
[e5d267]435  poly g = p_Copy(NUM(fa), ntRing);
436  poly h = p_Copy(NUM(fb), ntRing);
[de90c01]437  g = p_Mult_q(g, h, ntRing);
438 
439  if (g == NULL) return NULL;   /* may happen due to zero divisors */
440 
[2c7f28]441  poly f;
[e5d267]442  if      (DENIS1(fa) && DENIS1(fb))  f = NULL;
443  else if (!DENIS1(fa) && DENIS1(fb)) f = p_Copy(DEN(fa), ntRing);
444  else if (DENIS1(fa) && !DENIS1(fb)) f = p_Copy(DEN(fb), ntRing);
445  else /* both den's are != 1 */      f = p_Mult_q(p_Copy(DEN(fa), ntRing),
446                                                   p_Copy(DEN(fb), ntRing),
[2c7f28]447                                                   ntRing);
[de90c01]448 
[2c7f28]449  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]450  NUM(result) = g;
451  DEN(result) = f;
452  COM(result) = COM(fa) + COM(fb) + MULT_COMPLEXITY;
[2c7f28]453  heuristicGcdCancellation((number)result, cf);
454  return (number)result;
[6ccdd3a]455}
456
[2c7f28]457number ntDiv(number a, number b, const coeffs cf)
[6ccdd3a]458{
[2c7f28]459  ntTest(a); ntTest(b);
[e5d267]460  if (IS0(a)) return NULL;
461  if (IS0(b)) WerrorS(nDivBy0);
[2c7f28]462 
463  fraction fa = (fraction)a;
464  fraction fb = (fraction)b;
[de90c01]465 
[e5d267]466  poly g = p_Copy(NUM(fa), ntRing);
467  if (!DENIS1(fb)) g = p_Mult_q(g, p_Copy(DEN(fb), ntRing), ntRing);
[de90c01]468 
469  if (g == NULL) return NULL;   /* may happen due to zero divisors */
470 
[e5d267]471  poly f = p_Copy(NUM(fb), ntRing);
472  if (!DENIS1(fa)) f = p_Mult_q(f, p_Copy(DEN(fa), ntRing), ntRing);
[de90c01]473 
[2c7f28]474  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]475  NUM(result) = g;
476  DEN(result) = f;
477  COM(result) = COM(fa) + COM(fb) + MULT_COMPLEXITY;
[2c7f28]478  heuristicGcdCancellation((number)result, cf);
479  return (number)result;
[6ccdd3a]480}
481
482/* 0^0 = 0;
483   for |exp| <= 7 compute power by a simple multiplication loop;
484   for |exp| >= 8 compute power along binary presentation of |exp|, e.g.
485      p^13 = p^1 * p^4 * p^8, where we utilise that
[2c7f28]486      p^(2^(k+1)) = p^(2^k) * p^(2^k);
487   intermediate cancellation is controlled by the in-place method
488   heuristicGcdCancellation; see there.
[6ccdd3a]489*/
[2c7f28]490void ntPower(number a, int exp, number *b, const coeffs cf)
[6ccdd3a]491{
[2c7f28]492  ntTest(a);
[6ccdd3a]493 
494  /* special cases first */
[e5d267]495  if (IS0(a))
[6ccdd3a]496  {
497    if (exp >= 0) *b = NULL;
498    else          WerrorS(nDivBy0);
499  }
[2c7f28]500  else if (exp ==  0) *b = ntInit(1, cf);
501  else if (exp ==  1) *b = ntCopy(a, cf);
502  else if (exp == -1) *b = ntInvers(a, cf);
[6ccdd3a]503 
504  int expAbs = exp; if (expAbs < 0) expAbs = -expAbs;
505 
[2c7f28]506  /* now compute a^expAbs */
507  number pow; number t;
[6ccdd3a]508  if (expAbs <= 7)
509  {
[2c7f28]510    pow = ntCopy(a, cf);
[6ccdd3a]511    for (int i = 2; i <= expAbs; i++)
512    {
[2c7f28]513      t = ntMult(pow, a, cf);
514      ntDelete(&pow, cf);
515      pow = t;
516      heuristicGcdCancellation(pow, cf);
[6ccdd3a]517    }
518  }
519  else
520  {
[2c7f28]521    pow = ntInit(1, cf);
522    number factor = ntCopy(a, cf);
[6ccdd3a]523    while (expAbs != 0)
524    {
525      if (expAbs & 1)
526      {
[2c7f28]527        t = ntMult(pow, factor, cf);
528        ntDelete(&pow, cf);
529        pow = t;
530        heuristicGcdCancellation(pow, cf);
[6ccdd3a]531      }
532      expAbs = expAbs / 2;
533      if (expAbs != 0)
534      {
[2c7f28]535        t = ntMult(factor, factor, cf);
536        ntDelete(&factor, cf);
537        factor = t;
538        heuristicGcdCancellation(factor, cf);
[6ccdd3a]539      }
540    }
[2c7f28]541    ntDelete(&factor, cf);
[6ccdd3a]542  }
543 
544  /* invert if original exponent was negative */
545  if (exp < 0)
546  {
[2c7f28]547    t = ntInvers(pow, cf);
548    ntDelete(&pow, cf);
549    pow = t;
[6ccdd3a]550  }
[2c7f28]551  *b = pow;
[6ccdd3a]552}
553
[06df101]554/* assumes that cf represents the rationals, i.e. Q, and will only
555   be called in that case;
556   assumes furthermore that f != NULL and that the denominator of f != 1;
557   generally speaking, this method removes denominators in the rational
558   coefficients of the numerator and denominator of 'a';
559   more concretely, the following normalizations will be performed,
560   where t^alpha denotes a monomial in the transcendental variables t_k
561   (1) if 'a' is of the form
562          (sum_alpha a_alpha/b_alpha * t^alpha)
563          -------------------------------------
564            (sum_beta c_beta/d_beta * t^beta)
565       with integers a_alpha, b_alpha, c_beta, d_beta, then both the
566       numerator and the denominator will be multiplied by the LCM of
567       the b_alpha's and the d_beta's (if this LCM is != 1),
568   (2) if 'a' is - e.g. after having performed step (1) - of the form
569          (sum_alpha a_alpha * t^alpha)
570          -----------------------------
571            (sum_beta c_beta * t^beta)
572       with integers a_alpha, c_beta, and with a non-constant denominator,
573       then both the numerator and the denominator will be divided by the
574       GCD of the a_alpha's and the c_beta's (if this GCD is != 1),
575   (3) if 'a' is - e.g. after having performed steps (1) and (2) - of the
576       form
577          (sum_alpha a_alpha * t^alpha)
578          -----------------------------
579                        c
580       with integers a_alpha, and c != 1, then 'a' will be replaced by
581       (sum_alpha a_alpha/c * t^alpha);
582   this procedure does not alter COM(f) (this has to be done by the
583   calling procedure);
584   modifies f */
585void handleNestedFractionsOverQ(fraction f, const coeffs cf)
586{
587  assume(nCoeff_is_Q(ntCoeffs));
588  assume(!IS0(f));
589  assume(!DENIS1(f));
590 
591  if (!p_IsConstant(DEN(f), ntRing))
592  { /* step (1); see documentation of this procedure above */
593    number lcmOfDenominators = n_Init(1, ntCoeffs);
594    number c; number tmp;
595    poly p = NUM(f);
596    /* careful when using n_Lcm!!! It computes the lcm of the numerator
597       of the 1st argument and the denominator of the 2nd!!! */
598    while (p != NULL)
599    {
600      c = p_GetCoeff(p, ntRing);
601      tmp = n_Lcm(lcmOfDenominators, c, ntCoeffs);
602      n_Delete(&lcmOfDenominators, ntCoeffs);
603      lcmOfDenominators = tmp;
604      pIter(p);
605    }
606    p = DEN(f);
607    while (p != NULL)
608    {
609      c = p_GetCoeff(p, ntRing);
610      tmp = n_Lcm(lcmOfDenominators, c, ntCoeffs);
611      n_Delete(&lcmOfDenominators, ntCoeffs);
612      lcmOfDenominators = tmp;
613      pIter(p);
614    }
615    if (!n_IsOne(lcmOfDenominators, ntCoeffs))
616    { /* multiply NUM(f) and DEN(f) with lcmOfDenominators */
617      NUM(f) = p_Mult_nn(NUM(f), lcmOfDenominators, ntRing);
618      DEN(f) = p_Mult_nn(DEN(f), lcmOfDenominators, ntRing);
619    }
620    n_Delete(&lcmOfDenominators, ntCoeffs);
621    if (!p_IsConstant(DEN(f), ntRing))
622    { /* step (2); see documentation of this procedure above */
623      p = NUM(f);
624      number gcdOfCoefficients = n_Copy(p_GetCoeff(p, ntRing), ntCoeffs);
625      pIter(p);
626      while ((p != NULL) && (!n_IsOne(gcdOfCoefficients, ntCoeffs)))
627      {
628        c = p_GetCoeff(p, ntRing);
629        tmp = n_Gcd(c, gcdOfCoefficients, ntCoeffs);
630        n_Delete(&gcdOfCoefficients, ntCoeffs);
631        gcdOfCoefficients = tmp;
632        pIter(p);
633      }
634      p = DEN(f);
635      while ((p != NULL) && (!n_IsOne(gcdOfCoefficients, ntCoeffs)))
636      {
637        c = p_GetCoeff(p, ntRing);
638        tmp = n_Gcd(c, gcdOfCoefficients, ntCoeffs);
639        n_Delete(&gcdOfCoefficients, ntCoeffs);
640        gcdOfCoefficients = tmp;
641        pIter(p);
642      }
643      if (!n_IsOne(gcdOfCoefficients, ntCoeffs))
644      { /* divide NUM(f) and DEN(f) by gcdOfCoefficients */
645        number inverseOfGcdOfCoefficients = n_Invers(gcdOfCoefficients,
646                                                     ntCoeffs);
647        NUM(f) = p_Mult_nn(NUM(f), inverseOfGcdOfCoefficients, ntRing);
648        DEN(f) = p_Mult_nn(DEN(f), inverseOfGcdOfCoefficients, ntRing);
649        n_Delete(&inverseOfGcdOfCoefficients, ntCoeffs);
650      }
651      n_Delete(&gcdOfCoefficients, ntCoeffs);
652    }
653  }
654  if (p_IsConstant(DEN(f), ntRing) &&
655      (!n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs)))
656  { /* step (3); see documentation of this procedure above */
657    number inverseOfDen = n_Invers(p_GetCoeff(DEN(f), ntRing), ntCoeffs);
658    NUM(f) = p_Mult_nn(NUM(f), inverseOfDen, ntRing);
659    n_Delete(&inverseOfDen, ntCoeffs);
660    p_Delete(&DEN(f), ntRing);
661    DEN(f) = NULL;
662  }
663 
664  /* Now, due to the above computations, DEN(f) may have become the
665     1-polynomial which needs to be represented by NULL: */
666  if ((DEN(f) != NULL) &&
667      p_IsConstant(DEN(f), ntRing) &&
668      n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs))
669  {
670    p_Delete(&DEN(f), ntRing); DEN(f) = NULL;
671  }
672}
673
[2c7f28]674/* modifies a */
675void heuristicGcdCancellation(number a, const coeffs cf)
[6ccdd3a]676{
[2c7f28]677  ntTest(a);
[e5d267]678  if (IS0(a)) return;
[010f3b]679 
[2c7f28]680  fraction f = (fraction)a;
[e5d267]681  if (DENIS1(f) || NUMIS1(f)) { COM(f) = 0; return; }
682 
683  /* check whether NUM(f) = DEN(f), and - if so - replace 'a' by 1 */
684  if (p_EqualPolys(NUM(f), DEN(f), ntRing))
685  { /* numerator and denominator are both != 1 */
686    p_Delete(&NUM(f), ntRing); NUM(f) = p_ISet(1, ntRing);
687    p_Delete(&DEN(f), ntRing); DEN(f) = NULL;
688    COM(f) = 0;
[010f3b]689    return;
690  }
691 
[e5d267]692  if (COM(f) <= BOUND_COMPLEXITY) return;
[010f3b]693  else definiteGcdCancellation(a, cf, TRUE);
[6ccdd3a]694}
695
[2c7f28]696/* modifies a */
[010f3b]697void definiteGcdCancellation(number a, const coeffs cf,
[06df101]698                             BOOLEAN simpleTestsHaveAlreadyBeenPerformed)
[6ccdd3a]699{
[2c7f28]700  ntTest(a);
[010f3b]701 
[2c7f28]702  fraction f = (fraction)a;
[010f3b]703 
[06df101]704  if (!simpleTestsHaveAlreadyBeenPerformed)
[2c7f28]705  {
[e5d267]706    if (IS0(a)) return;
707    if (DENIS1(f) || NUMIS1(f)) { COM(f) = 0; return; }
708 
709    /* check whether NUM(f) = DEN(f), and - if so - replace 'a' by 1 */
710    if (p_EqualPolys(NUM(f), DEN(f), ntRing))
711    { /* numerator and denominator are both != 1 */
712      p_Delete(&NUM(f), ntRing); NUM(f) = p_ISet(1, ntRing);
713      p_Delete(&DEN(f), ntRing); DEN(f) = NULL;
714      COM(f) = 0;
[010f3b]715      return;
716    }
[2c7f28]717  }
[010f3b]718 
[06df101]719#ifdef HAVE_FACTORY 
720  /* singclap_gcd destroys its arguments; we hence need copies: */
[e5d267]721  poly pNum = p_Copy(NUM(f), ntRing);
722  poly pDen = p_Copy(DEN(f), ntRing);
[06df101]723 
724  /* Note that, over Q, singclap_gcd will remove the denominators in all
725     rational coefficients of pNum and pDen, before starting to compute
726     the gcd. Thus, we do not need to ensure that the coefficients of
727     pNum and pDen live in Z; they may well be elements of Q\Z. */
[e5d267]728  poly pGcd = singclap_gcd(pNum, pDen, cf->extRing);
729  if (p_IsConstant(pGcd, ntRing) &&
730      n_IsOne(p_GetCoeff(pGcd, ntRing), ntCoeffs))
[06df101]731  { /* gcd = 1; nothing to cancel;
732       Suppose the given rational function field is over Q. Although the
733       gcd is 1, we may have produced fractional coefficients in NUM(f),
734       DEN(f), or both, due to previous arithmetics. The next call will
735       remove those nested fractions, in case there are any. */
736    if (nCoeff_is_Q(ntCoeffs)) handleNestedFractionsOverQ(f, cf);
[e5d267]737  }
738  else
[06df101]739  { /* We divide both NUM(f) and DEN(f) by the gcd which is known
740       to be != 1. */
741    poly newNum = singclap_pdivide(NUM(f), pGcd, ntRing);
742    p_Delete(&NUM(f), ntRing);
743    NUM(f) = newNum;
744    poly newDen = singclap_pdivide(DEN(f), pGcd, ntRing);
745    p_Delete(&DEN(f), ntRing);
746    DEN(f) = newDen;
747    if (p_IsConstant(DEN(f), ntRing) &&
748        n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs))
749    {
750      /* DEN(f) = 1 needs to be represented by NULL! */
[e5d267]751      p_Delete(&DEN(f), ntRing);
[06df101]752      newDen = NULL;
753    }
754    else
755    { /* Note that over Q, by cancelling the gcd, we may have produced
756         fractional coefficients in NUM(f), DEN(f), or both. The next
757         call will remove those nested fractions, in case there are
758         any. */
759      if (nCoeff_is_Q(ntCoeffs)) handleNestedFractionsOverQ(f, cf);
760    }
[e5d267]761  }
762  COM(f) = 0;
763  p_Delete(&pGcd, ntRing);
764#endif /* HAVE_FACTORY */
[2c7f28]765}
766
[e5d267]767/* modifies a */
[2c7f28]768void ntWrite(number &a, const coeffs cf)
769{
770  ntTest(a);
[010f3b]771  definiteGcdCancellation(a, cf, FALSE);
[e5d267]772  if (IS0(a))
[6ccdd3a]773    StringAppendS("0");
774  else
775  {
[2c7f28]776    fraction f = (fraction)a;
[2d3091c]777    BOOLEAN useBrackets = (!p_IsConstant(NUM(f), ntRing)) ||
778                          (!n_GreaterZero(p_GetCoeff(NUM(f), ntRing),
779                                          ntCoeffs));
[6ccdd3a]780    if (useBrackets) StringAppendS("(");
[e5d267]781    p_String0(NUM(f), ntRing, ntRing);
[6ccdd3a]782    if (useBrackets) StringAppendS(")");
[e5d267]783    if (!DENIS1(f))
[2c7f28]784    {
785      StringAppendS("/");
[2d3091c]786      useBrackets = (!p_IsConstant(DEN(f), ntRing)) ||
787                    (!n_GreaterZero(p_GetCoeff(DEN(f), ntRing), ntCoeffs));
[2c7f28]788      if (useBrackets) StringAppendS("(");
[e5d267]789      p_String0(DEN(f), ntRing, ntRing);
[2c7f28]790      if (useBrackets) StringAppendS(")");
791    }
[6ccdd3a]792  }
793}
794
[2c7f28]795const char * ntRead(const char *s, number *a, const coeffs cf)
[6ccdd3a]796{
[2c7f28]797  poly p;
798  const char * result = p_Read(s, p, ntRing);
799  if (p == NULL) { *a = NULL; return result; }
800  else
801  {
802    fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]803    NUM(f) = p;
804    DEN(f) = NULL;
805    COM(f) = 0;
[2c7f28]806    *a = (number)f;
807    return result;
808  }
[6ccdd3a]809}
810
[2c7f28]811/* expects *param to be castable to TransExtInfo */
812static BOOLEAN ntCoeffIsEqual(const coeffs cf, n_coeffType n, void * param)
[6ccdd3a]813{
[2c7f28]814  if (ntID != n) return FALSE;
815  TransExtInfo *e = (TransExtInfo *)param;
816  /* for rational function fields we expect the underlying
817     polynomial rings to be IDENTICAL, i.e. the SAME OBJECT;
[6ccdd3a]818     this expectation is based on the assumption that we have properly
819     registered cf and perform reference counting rather than creating
820     multiple copies of the same coefficient field/domain/ring */
[2c7f28]821  return (ntRing == e->r);
[6ccdd3a]822}
823
[2c7f28]824number ntLcm(number a, number b, const coeffs cf)
[6ccdd3a]825{
[2c7f28]826  ntTest(a); ntTest(b);
827  /* TO BE IMPLEMENTED!
828     for the time, we simply return NULL, representing the number zero */
829  Print("// TO BE IMPLEMENTED: transext.cc:ntLcm\n");
830  return NULL;
[6ccdd3a]831}
832
[2c7f28]833number ntGcd(number a, number b, const coeffs cf)
[6ccdd3a]834{
[2c7f28]835  ntTest(a); ntTest(b);
836  /* TO BE IMPLEMENTED!
837     for the time, we simply return NULL, representing the number zero */
838  Print("// TO BE IMPLEMENTED: transext.cc:ntGcd\n");
839  return NULL;
[6ccdd3a]840}
841
[2c7f28]842int ntSize(number a, const coeffs cf)
[6ccdd3a]843{
[2c7f28]844  ntTest(a);
[e5d267]845  if (IS0(a)) return -1;
[2c7f28]846  /* this has been taken from the old implementation of field extensions,
847     where we computed the sum of the degrees and the numbers of terms in
848     the numerator and denominator of a; so we leave it at that, for the
849     time being */
850  fraction f = (fraction)a;
[e5d267]851  poly p = NUM(f);
[2c7f28]852  int noOfTerms = 0;
853  int numDegree = 0;
854  while (p != NULL)
855  {
856    noOfTerms++;
857    int d = 0;
858    for (int i = 1; i <= rVar(ntRing); i++)
859      d += p_GetExp(p, i, ntRing);
860    if (d > numDegree) numDegree = d;
861    pIter(p);
862  }
863  int denDegree = 0;
[e5d267]864  if (!DENIS1(f))
[2c7f28]865  {
[e5d267]866    p = DEN(f);
[2c7f28]867    while (p != NULL)
868    {
869      noOfTerms++;
870      int d = 0;
871      for (int i = 1; i <= rVar(ntRing); i++)
872        d += p_GetExp(p, i, ntRing);
873      if (d > denDegree) denDegree = d;
874      pIter(p);
875    }
876  }
877  return numDegree + denDegree + noOfTerms;
[6ccdd3a]878}
879
[2c7f28]880number ntInvers(number a, const coeffs cf)
[6ccdd3a]881{
[2c7f28]882  ntTest(a);
[e5d267]883  if (IS0(a)) WerrorS(nDivBy0);
[2c7f28]884  fraction f = (fraction)a;
885  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
886  poly g;
[e5d267]887  if (DENIS1(f)) g = p_One(ntRing);
888  else           g = p_Copy(DEN(f), ntRing);
889  NUM(result) = g;
890  DEN(result) = p_Copy(NUM(f), ntRing);
891  COM(result) = COM(f);
[2c7f28]892  return (number)result;
[6ccdd3a]893}
894
[2c7f28]895/* assumes that src = Q, dst = Q(t_1, ..., t_s) */
896number ntMap00(number a, const coeffs src, const coeffs dst)
[6ccdd3a]897{
[2c7f28]898  if (n_IsZero(a, src)) return NULL;
[6ccdd3a]899  assume(src == dst->extRing->cf);
[2c7f28]900  poly p = p_One(dst->extRing);
901  p_SetCoeff(p, ntCopy(a, src), dst->extRing);
902  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]903  NUM(f) = p; DEN(f) = NULL; COM(f) = 0;
[2c7f28]904  return (number)f;
[6ccdd3a]905}
906
[2c7f28]907/* assumes that src = Z/p, dst = Q(t_1, ..., t_s) */
908number ntMapP0(number a, const coeffs src, const coeffs dst)
[6ccdd3a]909{
[2c7f28]910  if (n_IsZero(a, src)) return NULL;
[6ccdd3a]911  /* mapping via intermediate int: */
912  int n = n_Int(a, src);
913  number q = n_Init(n, dst->extRing->cf);
[2c7f28]914  poly p;
915  if (n_IsZero(q, dst->extRing->cf))
916  {
917    n_Delete(&q, dst->extRing->cf);
918    return NULL;
919  }
920  p = p_One(dst->extRing);
921  p_SetCoeff(p, q, dst->extRing);
922  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]923  NUM(f) = p; DEN(f) = NULL; COM(f) = 0;
[2c7f28]924  return (number)f;
[6ccdd3a]925}
926
[2c7f28]927/* assumes that either src = Q(t_1, ..., t_s), dst = Q(t_1, ..., t_s), or
928                       src = Z/p(t_1, ..., t_s), dst = Z/p(t_1, ..., t_s) */
929number ntCopyMap(number a, const coeffs src, const coeffs dst)
[6ccdd3a]930{
[2c7f28]931  return ntCopy(a, dst);
[6ccdd3a]932}
933
[2c7f28]934/* assumes that src = Q, dst = Z/p(t_1, ..., t_s) */
935number ntMap0P(number a, const coeffs src, const coeffs dst)
[6ccdd3a]936{
[2c7f28]937  if (n_IsZero(a, src)) return NULL;
[6ccdd3a]938  int p = rChar(dst->extRing);
939  int n = nlModP(a, p, src);
940  number q = n_Init(n, dst->extRing->cf);
[2c7f28]941  poly g;
942  if (n_IsZero(q, dst->extRing->cf))
943  {
944    n_Delete(&q, dst->extRing->cf);
945    return NULL;
946  }
947  g = p_One(dst->extRing);
948  p_SetCoeff(g, q, dst->extRing);
949  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]950  NUM(f) = g; DEN(f) = NULL; COM(f) = 0;
[2c7f28]951  return (number)f;
[6ccdd3a]952}
953
[2c7f28]954/* assumes that src = Z/p, dst = Z/p(t_1, ..., t_s) */
955number ntMapPP(number a, const coeffs src, const coeffs dst)
[6ccdd3a]956{
[2c7f28]957  if (n_IsZero(a, src)) return NULL;
[6ccdd3a]958  assume(src == dst->extRing->cf);
[2c7f28]959  poly p = p_One(dst->extRing);
960  p_SetCoeff(p, ntCopy(a, src), dst->extRing);
961  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]962  NUM(f) = p; DEN(f) = NULL; COM(f) = 0;
[2c7f28]963  return (number)f;
[6ccdd3a]964}
965
[2c7f28]966/* assumes that src = Z/u, dst = Z/p(t_1, ..., t_s), where u != p */
967number ntMapUP(number a, const coeffs src, const coeffs dst)
[6ccdd3a]968{
[2c7f28]969  if (n_IsZero(a, src)) return NULL;
[6ccdd3a]970  /* mapping via intermediate int: */
971  int n = n_Int(a, src);
972  number q = n_Init(n, dst->extRing->cf);
[2c7f28]973  poly p;
974  if (n_IsZero(q, dst->extRing->cf))
975  {
976    n_Delete(&q, dst->extRing->cf);
977    return NULL;
978  }
979  p = p_One(dst->extRing);
980  p_SetCoeff(p, q, dst->extRing);
981  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
[e5d267]982  NUM(f) = p; DEN(f) = NULL; COM(f) = 0;
[2c7f28]983  return (number)f;
[6ccdd3a]984}
985
[2c7f28]986nMapFunc ntSetMap(const coeffs src, const coeffs dst)
[6ccdd3a]987{
[2c7f28]988  /* dst is expected to be a rational function field */
989  assume(getCoeffType(dst) == ntID);
[6ccdd3a]990 
991  int h = 0; /* the height of the extension tower given by dst */
992  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
993 
994  /* for the time being, we only provide maps if h = 1 and if b is Q or
995     some field Z/pZ: */
996  if (h != 1) return NULL;
997  if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
998 
[2c7f28]999  /* Let T denote the sequence of transcendental extension variables, i.e.,
1000     K[t_1, ..., t_s] =: K[T];
1001     Let moreover, for any such sequence T, T' denote any subsequence of T
1002     of the form t_1, ..., t_w with w <= s. */
1003 
[6ccdd3a]1004  if (nCoeff_is_Q(src) && nCoeff_is_Q(bDst))
[2c7f28]1005    return ntMap00;                                      /// Q       -->  Q(T)
[6ccdd3a]1006 
1007  if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
[2c7f28]1008    return ntMapP0;                                      /// Z/p     -->  Q(T)
[6ccdd3a]1009 
1010  if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
[2c7f28]1011    return ntMap0P;                                      /// Q       --> Z/p(T)
[6ccdd3a]1012 
1013  if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
1014  {
[2c7f28]1015    if (src->ch == dst->ch) return ntMapPP;              /// Z/p     --> Z/p(T)
1016    else return ntMapUP;                                 /// Z/u     --> Z/p(T)
[6ccdd3a]1017  }
1018 
1019  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
1020  if (h != 1) return NULL;
1021  if ((!nCoeff_is_Zp(bSrc)) && (!nCoeff_is_Q(bSrc))) return NULL;
1022 
1023  if (nCoeff_is_Q(bSrc) && nCoeff_is_Q(bDst))
1024  {
[2c7f28]1025    if (rVar(src->extRing) > rVar(dst->extRing)) return NULL;
1026    for (int i = 0; i < rVar(src->extRing); i++)
1027      if (strcmp(rRingVar(i, src->extRing),
1028                 rRingVar(i, dst->extRing)) != 0) return NULL;
1029      return ntCopyMap;                                  /// Q(T')   --> Q(T)
[6ccdd3a]1030  }
1031 
1032  if (nCoeff_is_Zp(bSrc) && nCoeff_is_Zp(bDst))
1033  {
[2c7f28]1034    if (rVar(src->extRing) > rVar(dst->extRing)) return NULL;
1035    for (int i = 0; i < rVar(src->extRing); i++)
1036      if (strcmp(rRingVar(i, src->extRing),
1037                 rRingVar(i, dst->extRing)) != 0) return NULL;
1038      return ntCopyMap;                                  /// Z/p(T') --> Z/p(T)
[6ccdd3a]1039  }
1040 
1041  return NULL;                                           /// default
1042}
1043
[2c7f28]1044BOOLEAN ntInitChar(coeffs cf, void * infoStruct)
1045{ 
1046  TransExtInfo *e = (TransExtInfo *)infoStruct;
[6ccdd3a]1047  /// first check whether cf->extRing != NULL and delete old ring???
1048  cf->extRing           = e->r;
[2c7f28]1049  cf->extRing->minideal = NULL;
1050
1051  assume(cf->extRing                != NULL);      // extRing;
1052  assume(cf->extRing->cf            != NULL);      // extRing->cf;
1053  assume(getCoeffType(cf) == ntID);                // coeff type;
[6ccdd3a]1054 
1055  /* propagate characteristic up so that it becomes
1056     directly accessible in cf: */
1057  cf->ch = cf->extRing->cf->ch;
1058 
[2c7f28]1059  cf->cfGreaterZero  = ntGreaterZero;
1060  cf->cfGreater      = ntGreater;
1061  cf->cfEqual        = ntEqual;
1062  cf->cfIsZero       = ntIsZero;
1063  cf->cfIsOne        = ntIsOne;
1064  cf->cfIsMOne       = ntIsMOne;
1065  cf->cfInit         = ntInit;
1066  cf->cfInt          = ntInt;
1067  cf->cfNeg          = ntNeg;
1068  cf->cfPar          = ntPar;
1069  cf->cfAdd          = ntAdd;
1070  cf->cfSub          = ntSub;
1071  cf->cfMult         = ntMult;
1072  cf->cfDiv          = ntDiv;
1073  cf->cfExactDiv     = ntDiv;
1074  cf->cfPower        = ntPower;
1075  cf->cfCopy         = ntCopy;
1076  cf->cfWrite        = ntWrite;
1077  cf->cfRead         = ntRead;
1078  cf->cfDelete       = ntDelete;
1079  cf->cfSetMap       = ntSetMap;
1080  cf->cfGetDenom     = ntGetDenom;
1081  cf->cfGetNumerator = ntGetNumerator;
1082  cf->cfRePart       = ntCopy;
1083  cf->cfImPart       = ntImPart;
1084  cf->cfCoeffWrite   = ntCoeffWrite;
1085  cf->cfDBTest       = ntDBTest;
1086  cf->cfGcd          = ntGcd;
1087  cf->cfLcm          = ntLcm;
1088  cf->cfSize         = ntSize;
1089  cf->nCoeffIsEqual  = ntCoeffIsEqual;
1090  cf->cfInvers       = ntInvers;
1091  cf->cfIntDiv       = ntDiv;
[6ccdd3a]1092 
[e5d267]1093#ifndef HAVE_FACTORY
1094  PrintS("// Warning: The 'factory' module is not available.\n");
1095  PrintS("//          Hence gcd's cannot be cancelled in any\n");
1096  PrintS("//          computed fraction!\n");
1097#endif
1098 
[6ccdd3a]1099  return FALSE;
1100}
Note: See TracBrowser for help on using the repository browser.