source: git/libpolys/polys/ext_fields/transext.cc @ 31c731

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