transext.cc
Go to the documentation of this file.
1 /****************************************
2 * Computer Algebra System SINGULAR *
3 ****************************************/
4 /*
5 * ABSTRACT: numbers in a rational function field K(t_1, .., t_s) with
6 * transcendental variables t_1, ..., t_s, where s >= 1.
7 * Denoting the implemented coeffs object by cf, then these numbers
8 * are represented as quotients of polynomials living in the
9 * polynomial ring K[t_1, .., t_s] represented by cf->extring.
10 *
11 * An element of K(t_1, .., t_s) may have numerous representations,
12 * due to the possibility of common polynomial factors in the
13 * numerator and denominator. This problem is handled by a
14 * cancellation heuristic: Each number "knows" its complexity
15 * which is 0 if and only if common factors have definitely been
16 * cancelled, and some positive integer otherwise.
17 * Each arithmetic operation of two numbers with complexities c1
18 * and c2 will result in a number of complexity c1 + c2 + some
19 * penalty (specific for each arithmetic operation; see constants
20 * in the *.h file). Whenever the resulting complexity exceeds a
21 * certain threshold (see constant in the *.h file), then the
22 * cancellation heuristic will call 'factory' to compute the gcd
23 * and cancel it out in the given number. (This definite cancel-
24 * lation will also be performed at the beginning of ntWrite,
25 * ensuring that any output is free of common factors.
26 * For the special case of K = Q (i.e., when computing over the
27 * rationals), this definite cancellation procedure will also take
28 * care of nested fractions: If there are fractional coefficients
29 * in the numerator or denominator of a number, then this number
30 * is being replaced by a quotient of two polynomials over Z, or
31 * - if the denominator is a constant - by a polynomial over Q.
32 *
33 * TODO: the description above needs a major update!!!
34 */
35 #define TRANSEXT_PRIVATES
36 
37 #include <misc/auxiliary.h>
38 
39 #include <omalloc/omalloc.h>
40 #include <factory/factory.h>
41 
42 #include <reporter/reporter.h>
43 
44 #include <coeffs/coeffs.h>
45 #include <coeffs/numbers.h>
46 
47 #include <coeffs/longrat.h>
48 
49 #include <polys/monomials/ring.h>
51 #include <polys/simpleideals.h>
52 
53 #include <polys/clapsing.h>
54 #include <polys/clapconv.h>
55 
56 #include <polys/prCopy.h>
57 #include "transext.h"
58 #include "algext.h"
59 
60 #include <polys/PolyEnumerator.h>
61 
62 
63 /* constants for controlling the complexity of numbers */
64 #define ADD_COMPLEXITY 1 /**< complexity increase due to + and - */
65 #define MULT_COMPLEXITY 2 /**< complexity increase due to * and / */
66 #define DIFF_COMPLEXITY 2 /**< complexity increase due to * and / */
67 #define BOUND_COMPLEXITY 10 /**< maximum complexity of a number */
68 
69 /// TRUE iff num. represents 1
70 #define NUMIS1(f) (p_IsOne(NUM(f), cf->extRing))
71 
72 #define COM(f) f->complexity
73 
74 
75 #ifdef LDEBUG
76 #define ntTest(a) ntDBTest(a,__FILE__,__LINE__,cf)
77 BOOLEAN ntDBTest(number a, const char *f, const int l, const coeffs r);
78 #else
79 #define ntTest(a) do {} while (0)
80 #endif
81 
82 /// Our own type!
83 static const n_coeffType ID = n_transExt;
84 
85 /* polynomial ring in which the numerators and denominators of our
86  numbers live */
87 #define ntRing cf->extRing
88 
89 /* coeffs object in which the coefficients of our numbers live;
90  * methods attached to ntCoeffs may be used to compute with the
91  * coefficients of our numbers, e.g., use ntCoeffs->nAdd to add
92  * coefficients of our numbers */
93 #define ntCoeffs cf->extRing->cf
94 
95 
96 omBin fractionObjectBin = omGetSpecBin(sizeof(fractionObject));
97 
98 /// forward declarations
99 BOOLEAN ntGreaterZero(number a, const coeffs cf);
100 BOOLEAN ntGreater(number a, number b, const coeffs cf);
101 BOOLEAN ntEqual(number a, number b, const coeffs cf);
102 BOOLEAN ntIsOne(number a, const coeffs cf);
103 BOOLEAN ntIsMOne(number a, const coeffs cf);
104 BOOLEAN ntIsZero(number a, const coeffs cf);
105 number ntInit(long i, const coeffs cf);
106 long ntInt(number &a, const coeffs cf);
107 number ntNeg(number a, const coeffs cf);
108 number ntInvers(number a, const coeffs cf);
109 number ntAdd(number a, number b, const coeffs cf);
110 number ntSub(number a, number b, const coeffs cf);
111 number ntMult(number a, number b, const coeffs cf);
112 number ntDiv(number a, number b, const coeffs cf);
113 void ntPower(number a, int exp, number *b, const coeffs cf);
114 number ntCopy(number a, const coeffs cf);
115 void ntWriteLong(number &a, const coeffs cf);
116 void ntWriteShort(number &a, const coeffs cf);
117 number ntRePart(number a, const coeffs cf);
118 number ntImPart(number a, const coeffs cf);
119 number ntGetDenom(number &a, const coeffs cf);
120 number ntGetNumerator(number &a, const coeffs cf);
121 number ntGcd(number a, number b, const coeffs cf);
122 number ntNormalizeHelper(number a, number b, const coeffs cf);
123 int ntSize(number a, const coeffs cf);
124 void ntDelete(number * a, const coeffs cf);
125 void ntCoeffWrite(const coeffs cf, BOOLEAN details);
126 const char * ntRead(const char *s, number *a, const coeffs cf);
127 static BOOLEAN ntCoeffIsEqual(const coeffs cf, n_coeffType n, void * param);
128 
129 void heuristicGcdCancellation(number a, const coeffs cf);
130 void definiteGcdCancellation(number a, const coeffs cf,
131  BOOLEAN simpleTestsHaveAlreadyBeenPerformed);
132 void handleNestedFractionsOverQ(fraction f, const coeffs cf);
133 
134 /* test routine, usualy disabled *
135  * if want to activate it, activate also the calls to check_N *
136  *
137 void check_normalized(number t,const coeffs cf, const char *f, int l)
138 {
139  if (IS0(t)) return;
140  if(rField_is_Q(ntRing))
141  {
142  poly pp=NUM(t);
143  while(pp!=NULL)
144  {
145  if (((SR_HDL(pGetCoeff(pp)) & SR_INT)==0)&&(SR_HDL(pGetCoeff(pp))!=NULL))
146  {
147  if (pGetCoeff(pp)->s==0)
148  {
149  Print("NUM not normalized in %s:%d\n",f,l);
150  p_Normalize(pp,ntRing);
151  }
152  else if (pGetCoeff(pp)->s==1)
153  Print("NUM is rational in %s:%d\n",f,l);
154  }
155  pIter(pp);
156  }
157  pp=DEN(t);
158  while(pp!=NULL)
159  {
160  if (((SR_HDL(pGetCoeff(pp)) & SR_INT)==0)&&(SR_HDL(pGetCoeff(pp))!=NULL))
161  {
162  if (pGetCoeff(pp)->s==0)
163  {
164  Print("NUM not normalized in %s:%d\n",f,l);
165  p_Normalize(pp,ntRing);
166  }
167  else if (pGetCoeff(pp)->s==1)
168  Print("DEN is rational in %s:%d\n",f,l);
169  }
170  pIter(pp);
171  }
172  }
173 }
174 #define check_N(A,B) check_normalized(A,B,__FILE__,__LINE__)
175 */
176 
177 #ifdef LDEBUG
178 BOOLEAN ntDBTest(number a, const char *f, const int l, const coeffs cf)
179 {
180  assume(getCoeffType(cf) == ID);
181 
182  if (IS0(a)) return TRUE;
183 
184  const fraction t = (fraction)a;
185 
186  //check_N(a,cf);
187  const poly num = NUM(t);
188  assume(num != NULL); /**< t != 0 ==> numerator(t) != 0 */
189 
190  p_Test(num, ntRing);
191 
192  const poly den = DEN(t);
193 
194  if (den != NULL) // !DENIS1(f)
195  {
196  p_Test(den, ntRing);
197 
198  if(p_IsConstant(den, ntRing) && (n_IsOne(pGetCoeff(den), ntCoeffs)))
199  {
200  Print("?/1 in %s:%d\n",f,l);
201  return FALSE;
202  }
203 
204  if( !n_GreaterZero(pGetCoeff(den), ntCoeffs) )
205  {
206  Print("negative sign of DEN. of a fraction in %s:%d\n",f,l);
207  return FALSE;
208  }
209 
210  // test that den is over integers!?
211 
212  } else
213  { // num != NULL // den == NULL
214 
215 // if( COM(t) != 0 )
216 // {
217 // Print("?//NULL with non-zero complexity: %d in %s:%d\n", COM(t), f, l);
218 // return FALSE;
219 // }
220  // test that nume is over integers!?
221  }
222  if (getCoeffType(ntCoeffs)==n_Q)
223  {
224  poly p=num; // !=NULL
225  do
226  {
227  number n=pGetCoeff(p);
228  n_Test(n,ntCoeffs);
229  if ((!(SR_HDL(n) & SR_INT))&&(n->s==0))
230  /* not normalized, just do for the following test*/
231  {
233  n=pGetCoeff(p);
234  }
235  if (!(SR_HDL(n) & SR_INT))
236  {
237  if (n->s<2)
238  Print("rational coeff in num: %s:%d\n",f,l);
239  }
240  pIter(p);
241  } while(p!=NULL);
242  p=den;
243  while(p!=NULL)
244  {
245  number n=pGetCoeff(p);
246  if (!(SR_HDL(n) & SR_INT))
247  {
248  if (n->s!=3)
249  Print("rational coeff in den.:%s:%d\n",f,l);
250  }
251  pIter(p);
252  }
253  }
254  return TRUE;
255 }
256 #endif
257 
258 /* returns the bottom field in this field extension tower; if the tower
259  is flat, i.e., if there is no extension, then r itself is returned;
260  as a side-effect, the counter 'height' is filled with the height of
261  the extension tower (in case the tower is flat, 'height' is zero) */
262 static coeffs nCoeff_bottom(const coeffs r, int &height)
263 {
264  assume(r != NULL);
265  coeffs cf = r;
266  height = 0;
267  while (nCoeff_is_Extension(cf))
268  {
269  assume(cf->extRing != NULL); assume(cf->extRing->cf != NULL);
270  cf = cf->extRing->cf;
271  height++;
272  }
273  return cf;
274 }
275 
276 BOOLEAN ntIsZero(number a, const coeffs cf)
277 {
278  //check_N(a,cf);
279  ntTest(a); // !!!
280  return (IS0(a));
281 }
282 
283 void ntDelete(number * a, const coeffs cf)
284 {
285  //check_N(*a,cf);
286  ntTest(*a); // !!!
287  fraction f = (fraction)(*a);
288  if (IS0(f)) return;
289  p_Delete(&NUM(f), ntRing);
290  if (!DENIS1(f)) p_Delete(&DEN(f), ntRing);
292  *a = NULL;
293 }
294 
295 BOOLEAN ntEqual(number a, number b, const coeffs cf)
296 {
297  //check_N(a,cf);
298  //check_N(b,cf);
299  ntTest(a);
300  ntTest(b);
301 
302  /// simple tests
303  if (a == b) return TRUE;
304  if ((IS0(a)) && (!IS0(b))) return FALSE;
305  if ((IS0(b)) && (!IS0(a))) return FALSE;
306 
307  /// cheap test if gcd's have been cancelled in both numbers
308  fraction fa = (fraction)a;
309  fraction fb = (fraction)b;
310  if ((COM(fa) == 1) && (COM(fb) == 1))
311  {
312  poly f = p_Add_q(p_Copy(NUM(fa), ntRing),
313  p_Neg(p_Copy(NUM(fb), ntRing), ntRing),
314  ntRing);
315  if (f != NULL) { p_Delete(&f, ntRing); return FALSE; }
316  if (DENIS1(fa) && DENIS1(fb)) return TRUE;
317  if (DENIS1(fa) && !DENIS1(fb)) return FALSE;
318  if (!DENIS1(fa) && DENIS1(fb)) return FALSE;
319  f = p_Add_q(p_Copy(DEN(fa), ntRing),
320  p_Neg(p_Copy(DEN(fb), ntRing), ntRing),
321  ntRing);
322  if (f != NULL) { p_Delete(&f, ntRing); return FALSE; }
323  return TRUE;
324  }
325 
326  /* default: the more expensive multiplication test
327  a/b = c/d <==> a*d = b*c */
328  poly f = p_Copy(NUM(fa), ntRing);
329  if (!DENIS1(fb)) f = p_Mult_q(f, p_Copy(DEN(fb), ntRing), ntRing);
330  poly g = p_Copy(NUM(fb), ntRing);
331  if (!DENIS1(fa)) g = p_Mult_q(g, p_Copy(DEN(fa), ntRing), ntRing);
332  poly h = p_Add_q(f, p_Neg(g, ntRing), ntRing);
333  if (h == NULL) return TRUE;
334  else
335  {
336  p_Delete(&h, ntRing);
337  return FALSE;
338  }
339 }
340 
341 number ntCopy(number a, const coeffs cf)
342 {
343  //check_N(a,cf);
344  ntTest(a); // !!!
345  if (IS0(a)) return NULL;
346  fraction f = (fraction)a;
347  poly g = p_Copy(NUM(f), ntRing);
348  poly h = NULL; if (!DENIS1(f)) h = p_Copy(DEN(f), ntRing);
349  fraction result = (fraction)omAllocBin(fractionObjectBin);
350  NUM(result) = g;
351  DEN(result) = h;
352  COM(result) = COM(f);
353  ntTest((number)result);
354  return (number)result;
355 }
356 
357 /// TODO: normalization of a!?
358 number ntGetNumerator(number &a, const coeffs cf)
359 {
360  //check_N(a,cf);
361  ntTest(a);
362  if (IS0(a)) return NULL;
363 
365 
366  fraction f = (fraction)a;
367  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
368 
369  const BOOLEAN denis1= DENIS1 (f);
370 
371  if (getCoeffType (ntCoeffs) == n_Q && !denis1)
373 
374  if (getCoeffType (ntCoeffs) == n_Q && denis1)
375  {
376  assume( DEN (f) == NULL );
377 
378  number g;
379  // TODO/NOTE: the following should not be necessary (due to
380  // Hannes!) as NUM (f) should be over Z!!!
381  CPolyCoeffsEnumerator itr(NUM(f));
382 
383 
384  n_ClearDenominators(itr, g, ntCoeffs);
385 
386  if( !n_GreaterZero(g, ntCoeffs) )
387  {
388  NUM (f) = p_Neg(NUM (f), ntRing); // Ugly :(((
389  g = n_InpNeg(g, ntCoeffs);
390  }
391 
392  // g should be a positive integer now!
394 
395  if( !n_IsOne(g, ntCoeffs) )
396  {
397  DEN (f) = p_NSet(g, ntRing); // update COM(f)???
398  COM (f) ++;
399  assume( DEN (f) != NULL );
400  }
401  else
402  n_Delete(&g, ntCoeffs);
403 
404  ntTest(a);
405  }
406 
407  // Call ntNormalize instead of above?!?
408 
409  NUM (result) = p_Copy (NUM (f), ntRing); // ???
410  //DEN (result) = NULL; // done by ..Alloc0..
411  //COM (result) = 0; // done by ..Alloc0..
412 
413  ntTest((number)result);
414  //check_N((number)result,cf);
415  return (number)result;
416 }
417 
418 /// TODO: normalization of a!?
419 number ntGetDenom(number &a, const coeffs cf)
420 {
421  //check_N(a,cf);
422  ntTest(a);
423 
424  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
425  //DEN (result)= NULL; // done by ..Alloc0..
426  //COM (result)= 0; // done by ..Alloc0..
427 
428  if (IS0(a))
429  {
430  NUM (result) = p_One(ntRing);
431  return (number)result;
432  }
433 
435 
436  fraction f = (fraction)a;
437 
438  assume( !IS0(f) );
439 
440  const BOOLEAN denis1 = DENIS1 (f);
441 
442  if( denis1 && (getCoeffType (ntCoeffs) != n_Q) ) // */1 or 0
443  {
444  NUM (result)= p_One(ntRing);
445  ntTest((number)result);
446  return (number)result;
447  }
448 
449  if (!denis1) // */* / Q
450  {
451  assume( DEN (f) != NULL );
452 
453  if (getCoeffType (ntCoeffs) == n_Q)
455 
456  ntTest(a);
457 
458  if( DEN (f) != NULL ) // is it ?? // 1 now???
459  {
460  assume( !p_IsOne(DEN (f), ntRing) );
461 
462  NUM (result) = p_Copy (DEN (f), ntRing);
463  ntTest((number)result);
464  return (number)result;
465  }
466 // NUM (result) = p_One(ntRing); // NOTE: just in order to be sure...
467  }
468 
469  // */1 / Q
471  assume( DEN (f) == NULL );
472 
473  number g;
474 // poly num= p_Copy (NUM (f), ntRing); // ???
475 
476 
477  // TODO/NOTE: the following should not be necessary (due to
478  // Hannes!) as NUM (f) should be over Z!!!
479  CPolyCoeffsEnumerator itr(NUM(f));
480 
481  n_ClearDenominators(itr, g, ntCoeffs); // may return -1 :(((
482 
483  if( !n_GreaterZero(g, ntCoeffs) )
484  {
485 // NUM (f) = p_Neg(NUM (f), ntRing); // Ugly :(((
486 // g = n_InpNeg(g, ntCoeffs);
487  NUM (f) = p_Neg(NUM (f), ntRing); // Ugly :(((
488  g = n_InpNeg(g, ntCoeffs);
489  }
490 
491  // g should be a positive integer now!
493 
494  if( !n_IsOne(g, ntCoeffs) )
495  {
497  assume( !n_IsOne(g, ntCoeffs) );
498 
499  DEN (f) = p_NSet(g, ntRing); // update COM(f)???
500  assume( DEN (f) != NULL );
501  COM (f) ++;
502 
503  NUM (result)= p_Copy (DEN (f), ntRing);
504  }
505  else
506  { // common denom == 1?
507  NUM (result)= p_NSet(g, ntRing); // p_Copy (DEN (f), ntRing);
508 // n_Delete(&g, ntCoeffs);
509  }
510 
511 // if (!p_IsConstant (num, ntRing) && pNext(num) != NULL)
512 // else
513 // g= p_GetAllDenom (num, ntRing);
514 // result= (fraction) ntSetMap (ntCoeffs, cf) (g, ntCoeffs, cf);
515 
516  ntTest((number)result);
517  //check_N((number)result,cf);
518  return (number)result;
519 }
520 
521 BOOLEAN ntIsOne(number a, const coeffs cf)
522 {
523  //check_N(a,cf);
524  ntTest(a); // !!!
526  fraction f = (fraction)a;
527  return (f!=NULL) && DENIS1(f) && NUMIS1(f);
528 }
529 
530 BOOLEAN ntIsMOne(number a, const coeffs cf)
531 {
532  //check_N(a,cf);
533  ntTest(a);
535  fraction f = (fraction)a;
536  if ((f==NULL) || (!DENIS1(f))) return FALSE;
537  poly g = NUM(f);
538  if (!p_IsConstant(g, ntRing)) return FALSE;
539  return n_IsMOne(p_GetCoeff(g, ntRing), ntCoeffs);
540 }
541 
542 /// this is in-place, modifies a
543 number ntNeg(number a, const coeffs cf)
544 {
545  //check_N(a,cf);
546  ntTest(a);
547  if (!IS0(a))
548  {
549  fraction f = (fraction)a;
550  NUM(f) = p_Neg(NUM(f), ntRing);
551  }
552  ntTest(a);
553  return a;
554 }
555 
556 number ntImPart(number a, const coeffs cf)
557 {
558  ntTest(a);
559  return NULL;
560 }
561 
562 number ntInit(long i, const coeffs cf)
563 {
564  if (i != 0)
565  {
566  poly p=p_ISet(i, ntRing);
567  if (p!=NULL)
568  {
569  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
570  NUM(result) = p;
571  //DEN(result) = NULL; // done by omAlloc0Bin
572  //COM(result) = 0; // done by omAlloc0Bin
573  ntTest((number)result);
574  //check_N((number)result,cf);
575  return (number)result;
576  }
577  }
578  return NULL;
579 }
580 
581 
582 /// takes over p!
583 number ntInit(poly p, const coeffs cf)
584 {
585  if (p == NULL) return NULL;
586 
587  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
588 
589  if (nCoeff_is_Q(ntCoeffs))
590  {
591  number g;
592  // the following is necessary because
593  // NUM (f) should be over Z,
594  // while p may be over Q
595  CPolyCoeffsEnumerator itr(p);
596 
597  n_ClearDenominators(itr, g, ntCoeffs);
598 
599  if( !n_GreaterZero(g, ntCoeffs) )
600  {
601  p = p_Neg(p, ntRing);
602  g = n_InpNeg(g, ntCoeffs);
603  }
604 
605  // g should be a positive integer now!
607 
608  if( !n_IsOne(g, ntCoeffs) )
609  {
610  DEN (f) = p_NSet(g, ntRing);
611  p_Normalize(DEN(f), ntRing);
612  assume( DEN (f) != NULL );
613  }
614  else
615  {
616  //DEN(f) = NULL; // done by omAlloc0
617  n_Delete(&g, ntCoeffs);
618  }
619  }
620 
621  p_Normalize(p, ntRing);
622  NUM(f) = p;
623  //COM(f) = 0; // done by omAlloc0
624 
625  //check_N((number)f,cf);
626  ntTest((number)f);
627  return (number)f;
628 }
629 
630 long ntInt(number &a, const coeffs cf)
631 {
632  //check_N(a,cf);
633  ntTest(a);
634  if (IS0(a)) return 0;
636  fraction f = (fraction)a;
637  if (!DENIS1(f)) return 0;
638 
639  const poly aAsPoly = NUM(f);
640 
641  if(aAsPoly == NULL)
642  return 0;
643 
644  if (!p_IsConstant(aAsPoly, ntRing))
645  return 0;
646 
647  assume( aAsPoly != NULL );
648 
649  return n_Int(p_GetCoeff(aAsPoly, ntRing), ntCoeffs);
650 }
651 
652 /* This method will only consider the numerators of a and b, without
653  cancelling gcd's before.
654  Moreover it may return TRUE only if one or both numerators
655  are zero or if their degrees are equal. Then TRUE is returned iff
656  coeff(numerator(a)) > coeff(numerator(b));
657  In all other cases, FALSE will be returned. */
658 BOOLEAN ntGreater(number a, number b, const coeffs cf)
659 {
660  //check_N(a,cf);
661  //check_N(b,cf);
662  ntTest(a);
663  ntTest(b);
664  number aNumCoeff = NULL; int aNumDeg = 0;
665  number aDenCoeff = NULL; int aDenDeg = 0;
666  number bNumCoeff = NULL; int bNumDeg = 0;
667  number bDenCoeff = NULL; int bDenDeg = 0;
668  if (!IS0(a))
669  {
670  fraction fa = (fraction)a;
671  aNumDeg = p_Totaldegree(NUM(fa), ntRing);
672  aNumCoeff = p_GetCoeff(NUM(fa), ntRing);
673  if (DEN(fa)!=NULL)
674  {
675  aDenDeg = p_Totaldegree(DEN(fa), ntRing);
676  aDenCoeff=p_GetCoeff(DEN(fa),ntRing);
677  }
678  }
679  else return !(ntGreaterZero (b,cf));
680  if (!IS0(b))
681  {
682  fraction fb = (fraction)b;
683  bNumDeg = p_Totaldegree(NUM(fb), ntRing);
684  bNumCoeff = p_GetCoeff(NUM(fb), ntRing);
685  if (DEN(fb)!=NULL)
686  {
687  bDenDeg = p_Totaldegree(DEN(fb), ntRing);
688  bDenCoeff=p_GetCoeff(DEN(fb),ntRing);
689  }
690  }
691  else return ntGreaterZero(a,cf);
692  if (aNumDeg-aDenDeg > bNumDeg-bDenDeg) return TRUE;
693  if (aNumDeg-aDenDeg < bNumDeg-bDenDeg) return FALSE;
694  number aa;
695  number bb;
696  if (bDenCoeff==NULL) aa=n_Copy(aNumCoeff,ntCoeffs);
697  else aa=n_Mult(aNumCoeff,bDenCoeff,ntCoeffs);
698  if (aDenCoeff==NULL) bb=n_Copy(bNumCoeff,ntCoeffs);
699  else bb=n_Mult(bNumCoeff,aDenCoeff,ntCoeffs);
700  BOOLEAN rr= n_Greater(aa, bb, ntCoeffs);
701  n_Delete(&aa,ntCoeffs);
702  n_Delete(&bb,ntCoeffs);
703  return rr;
704 }
705 
706 /* this method will only consider the numerator of a, without cancelling
707  the gcd before;
708  returns TRUE iff the leading coefficient of the numerator of a is > 0
709  or the leading term of the numerator of a is not a
710  constant */
712 {
713  //check_N(a,cf);
714  ntTest(a);
715  if (IS0(a)) return FALSE;
716  fraction f = (fraction)a;
717  poly g = NUM(f);
719 }
720 
721 void ntCoeffWrite(const coeffs cf, BOOLEAN details)
722 {
723  assume( cf != NULL );
724 
725  const ring A = cf->extRing;
726 
727  assume( A != NULL );
728  assume( A->cf != NULL );
729 
730  n_CoeffWrite(A->cf, details);
731 
732 // rWrite(A);
733 
734  const int P = rVar(A);
735  assume( P > 0 );
736 
737  Print("// %d parameter : ", P);
738 
739  for (int nop=0; nop < P; nop ++)
740  Print("%s ", rRingVar(nop, A));
741 
742  assume( A->qideal == NULL );
743 
744  PrintS("\n// minpoly : 0\n");
745 
746 /*
747  PrintS("// Coefficients live in the rational function field\n");
748  Print("// K(");
749  for (int i = 0; i < rVar(ntRing); i++)
750  {
751  if (i > 0) PrintS(" ");
752  Print("%s", rRingVar(i, ntRing));
753  }
754  PrintS(") with\n");
755  PrintS("// K: "); n_CoeffWrite(cf->extRing->cf);
756 */
757 }
758 
759 number ntDiff(number a, number d, const coeffs cf)
760 {
761  //check_N(a,cf);
762  //check_N(d,cf);
763  ntTest(a);
764  ntTest(d);
765 
766  if (IS0(d))
767  {
768  WerrorS("ringvar expected");
769  return NULL;
770  }
771  fraction t = (fraction) d;
772  if (!DENIS1(t))
773  {
774  WerrorS("expected differentiation by a variable");
775  return NULL;
776  }
777  int k=p_Var(NUM(t),ntRing);
778  if (k==0)
779  {
780  WerrorS("expected differentiation by a variable");
781  return NULL;
782  }
783 
784  if (IS0(a)) return ntCopy(a, cf);
785 
786  fraction fa = (fraction)a;
787  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
788  if (DENIS1(fa))
789  {
790  NUM(result) = p_Diff(NUM(fa),k,ntRing);
791  //DEN(result) = NULL; // done by ..Alloc0..
792  if (NUM(result)==NULL)
793  {
795  return(NULL);
796  }
797  COM(result) = COM(fa);
798  //check_N((number)result,cf);
799  return (number)result;
800  }
801 
802  poly fg = p_Mult_q(p_Copy(DEN(fa),ntRing),p_Diff(NUM(fa),k,ntRing),ntRing);
803  poly gf = p_Mult_q(p_Copy(NUM(fa),ntRing),p_Diff(DEN(fa),k,ntRing),ntRing);
804  NUM(result) = p_Sub(fg,gf,ntRing);
805  if (NUM(result)==NULL) return(NULL);
806  DEN(result) = pp_Mult_qq(DEN(fa), DEN(fa), ntRing);
807  COM(result) = COM(fa) + COM(fa) + DIFF_COMPLEXITY;
808  heuristicGcdCancellation((number)result, cf);
809 
810  //check_N((number)result,cf);
811  return (number)result;
812 }
813 
814 
815 number ntAdd(number a, number b, const coeffs cf)
816 {
817  //check_N(a,cf);
818  //check_N(b,cf);
819  ntTest(a);
820  ntTest(b);
821  if (IS0(a)) return ntCopy(b, cf);
822  if (IS0(b)) return ntCopy(a, cf);
823 
824  fraction fa = (fraction)a;
825  fraction fb = (fraction)b;
826 
827  poly g = p_Copy(NUM(fa), ntRing);
828  if (!DENIS1(fb)) g = p_Mult_q(g, p_Copy(DEN(fb), ntRing), ntRing);
829  poly h = p_Copy(NUM(fb), ntRing);
830  if (!DENIS1(fa)) h = p_Mult_q(h, p_Copy(DEN(fa), ntRing), ntRing);
831  g = p_Add_q(g, h, ntRing);
832 
833  if (g == NULL) return NULL;
834 
835  poly f;
836  if (DENIS1(fa) && DENIS1(fb)) f = NULL;
837  else if (!DENIS1(fa) && DENIS1(fb)) f = p_Copy(DEN(fa), ntRing);
838  else if (DENIS1(fa) && !DENIS1(fb)) f = p_Copy(DEN(fb), ntRing);
839  else /* both denom's are != 1 */ f = p_Mult_q(p_Copy(DEN(fa), ntRing),
840  p_Copy(DEN(fb), ntRing),
841  ntRing);
842 
843  fraction result = (fraction)omAllocBin(fractionObjectBin);
844  NUM(result) = g;
845  DEN(result) = f;
846  COM(result) = COM(fa) + COM(fb) + ADD_COMPLEXITY;
847  heuristicGcdCancellation((number)result, cf);
848 
849 // ntTest((number)result);
850 
851  //check_N((number)result,cf);
852  return (number)result;
853 }
854 
855 number ntSub(number a, number b, const coeffs cf)
856 {
857  //check_N(a,cf);
858  //check_N(b,cf);
859  ntTest(a);
860  ntTest(b);
861  if (IS0(a)) return ntNeg(ntCopy(b, cf), cf);
862  if (IS0(b)) return ntCopy(a, cf);
863 
864  fraction fa = (fraction)a;
865  fraction fb = (fraction)b;
866 
867  poly g = p_Copy(NUM(fa), ntRing);
868  if (!DENIS1(fb)) g = p_Mult_q(g, p_Copy(DEN(fb), ntRing), ntRing);
869  poly h = p_Copy(NUM(fb), ntRing);
870  if (!DENIS1(fa)) h = p_Mult_q(h, p_Copy(DEN(fa), ntRing), ntRing);
871  g = p_Add_q(g, p_Neg(h, ntRing), ntRing);
872 
873  if (g == NULL) return NULL;
874 
875  poly f;
876  if (DENIS1(fa) && DENIS1(fb)) f = NULL;
877  else if (!DENIS1(fa) && DENIS1(fb)) f = p_Copy(DEN(fa), ntRing);
878  else if (DENIS1(fa) && !DENIS1(fb)) f = p_Copy(DEN(fb), ntRing);
879  else /* both den's are != 1 */ f = p_Mult_q(p_Copy(DEN(fa), ntRing),
880  p_Copy(DEN(fb), ntRing),
881  ntRing);
882 
883  fraction result = (fraction)omAllocBin(fractionObjectBin);
884  NUM(result) = g;
885  DEN(result) = f;
886  COM(result) = COM(fa) + COM(fb) + ADD_COMPLEXITY;
887  heuristicGcdCancellation((number)result, cf);
888 // ntTest((number)result);
889  //check_N((number)result,cf);
890  return (number)result;
891 }
892 
893 number ntMult(number a, number b, const coeffs cf)
894 {
895  //check_N(a,cf);
896  //check_N(b,cf);
897  ntTest(a); // !!!?
898  ntTest(b); // !!!?
899 
900  if (IS0(a) || IS0(b)) return NULL;
901 
902  fraction fa = (fraction)a;
903  fraction fb = (fraction)b;
904 
905  const poly g = pp_Mult_qq(NUM(fa), NUM(fb), ntRing);
906 
907  if (g == NULL) return NULL; // may happen due to zero divisors???
908 
909  fraction result = (fraction)omAllocBin(fractionObjectBin);
910 
911  NUM(result) = g;
912 
913  const poly da = DEN(fa);
914  const poly db = DEN(fb);
915 
916 
917  //check_N((number)result,cf);
918  if (db == NULL)
919  {
920  // b = ? // NULL
921 
922  if(da == NULL)
923  { // both fa && fb are ?? // NULL!
924  assume (da == NULL && db == NULL);
925  DEN(result) = NULL;
926  COM(result) = 0;
927  }
928  else
929  {
930  assume (da != NULL && db == NULL);
931  DEN(result) = p_Copy(da, ntRing);
932  COM(result) = COM(fa) + MULT_COMPLEXITY;
933  heuristicGcdCancellation((number)result, cf);
934  //check_N((number)result,cf);
935  }
936  }
937  else
938  { // b = ?? / ??
939  if (da == NULL)
940  { // a == ? // NULL
941  assume( db != NULL && da == NULL);
942  DEN(result) = p_Copy(db, ntRing);
943  COM(result) = COM(fb) + MULT_COMPLEXITY;
944  heuristicGcdCancellation((number)result, cf);
945  //check_N((number)result,cf);
946  }
947  else /* both den's are != 1 */
948  {
949  assume (da != NULL && db != NULL);
950  DEN(result) = pp_Mult_qq(da, db, ntRing);
951  COM(result) = COM(fa) + COM(fb) + MULT_COMPLEXITY;
952  heuristicGcdCancellation((number)result, cf);
953  //check_N((number)result,cf);
954  }
955  }
956 
957 // ntTest((number)result);
958 
959  //check_N((number)result,cf);
960  return (number)result;
961 }
962 
963 number ntDiv(number a, number b, const coeffs cf)
964 {
965  //check_N(a,cf);
966  //check_N(b,cf);
967  ntTest(a);
968  ntTest(b);
969  if (IS0(a)) return NULL;
970  if (IS0(b)) WerrorS(nDivBy0);
971 
972  fraction fa = (fraction)a;
973  fraction fb = (fraction)b;
974 
975  poly g = p_Copy(NUM(fa), ntRing);
976  if (!DENIS1(fb)) g = p_Mult_q(g, p_Copy(DEN(fb), ntRing), ntRing);
977 
978  if (g == NULL) return NULL; /* may happen due to zero divisors */
979 
980  poly f = p_Copy(NUM(fb), ntRing);
981  if (!DENIS1(fa)) f = p_Mult_q(f, p_Copy(DEN(fa), ntRing), ntRing);
982 
983  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
984  NUM(result) = g;
986  {
987  g=p_Neg(g,ntRing);
988  f=p_Neg(f,ntRing);
989  NUM(result) = g;
990  }
991  if (!p_IsConstant(f,ntRing) || !n_IsOne(pGetCoeff(f),ntCoeffs))
992  {
993  DEN(result) = f;
994  }
995  COM(result) = COM(fa) + COM(fb) + MULT_COMPLEXITY;
996  heuristicGcdCancellation((number)result, cf);
997 // ntTest((number)result);
998  //check_N((number)result,cf);
999  return (number)result;
1000 }
1001 
1002 /* 0^0 = 0;
1003  for |exp| <= 7 compute power by a simple multiplication loop;
1004  for |exp| >= 8 compute power along binary presentation of |exp|, e.g.
1005  p^13 = p^1 * p^4 * p^8, where we utilise that
1006  p^(2^(k+1)) = p^(2^k) * p^(2^k);
1007  intermediate cancellation is controlled by the in-place method
1008  heuristicGcdCancellation; see there.
1009 */
1010 void ntPower(number a, int exp, number *b, const coeffs cf)
1011 {
1012  ntTest(a);
1013 
1014  /* special cases first */
1015  if (IS0(a))
1016  {
1017  if (exp >= 0) *b = NULL;
1018  else WerrorS(nDivBy0);
1019  }
1020  else if (exp == 0) { *b = ntInit(1, cf); return;}
1021  else if (exp == 1) { *b = ntCopy(a, cf); return;}
1022  else if (exp == -1) { *b = ntInvers(a, cf); return;}
1023 
1024  int expAbs = exp; if (expAbs < 0) expAbs = -expAbs;
1025 
1026  /* now compute a^expAbs */
1027  number pow; number t;
1028  if (expAbs <= 7)
1029  {
1030  pow = ntCopy(a, cf);
1031  for (int i = 2; i <= expAbs; i++)
1032  {
1033  t = ntMult(pow, a, cf);
1034  ntDelete(&pow, cf);
1035  pow = t;
1036  heuristicGcdCancellation(pow, cf);
1037  }
1038  }
1039  else
1040  {
1041  pow = ntInit(1, cf);
1042  number factor = ntCopy(a, cf);
1043  while (expAbs != 0)
1044  {
1045  if (expAbs & 1)
1046  {
1047  t = ntMult(pow, factor, cf);
1048  ntDelete(&pow, cf);
1049  pow = t;
1050  heuristicGcdCancellation(pow, cf);
1051  }
1052  expAbs = expAbs / 2;
1053  if (expAbs != 0)
1054  {
1055  t = ntMult(factor, factor, cf);
1056  ntDelete(&factor, cf);
1057  factor = t;
1058  heuristicGcdCancellation(factor, cf);
1059  }
1060  }
1061  ntDelete(&factor, cf);
1062  }
1063 
1064  /* invert if original exponent was negative */
1065  if (exp < 0)
1066  {
1067  t = ntInvers(pow, cf);
1068  ntDelete(&pow, cf);
1069  pow = t;
1070  }
1071  *b = pow;
1072  ntTest(*b);
1073  //check_N(*b,cf);
1074 }
1075 
1076 /* assumes that cf represents the rationals, i.e. Q, and will only
1077  be called in that case;
1078  assumes furthermore that f != NULL and that the denominator of f != 1;
1079  generally speaking, this method removes denominators in the rational
1080  coefficients of the numerator and denominator of 'a';
1081  more concretely, the following normalizations will be performed,
1082  where t^alpha denotes a monomial in the transcendental variables t_k
1083  (1) if 'a' is of the form
1084  (sum_alpha a_alpha/b_alpha * t^alpha)
1085  -------------------------------------
1086  (sum_beta c_beta/d_beta * t^beta)
1087  with integers a_alpha, b_alpha, c_beta, d_beta, then both the
1088  numerator and the denominator will be multiplied by the LCM of
1089  the b_alpha's and the d_beta's (if this LCM is != 1),
1090  (2) if 'a' is - e.g. after having performed step (1) - of the form
1091  (sum_alpha a_alpha * t^alpha)
1092  -----------------------------
1093  (sum_beta c_beta * t^beta)
1094  with integers a_alpha, c_beta, and with a non-constant denominator,
1095  then both the numerator and the denominator will be divided by the
1096  GCD of the a_alpha's and the c_beta's (if this GCD is != 1),
1097  this procedure does not alter COM(f) (this has to be done by the
1098  calling procedure);
1099  modifies f */
1100 void handleNestedFractionsOverQ(fraction f, const coeffs cf)
1101 {
1103  assume(!IS0(f));
1104  assume(!DENIS1(f));
1105 
1106  { /* step (1); see documentation of this procedure above */
1107  number lcmOfDenominators = n_Init(1, ntCoeffs);
1108  number c; number tmp;
1109  poly p = NUM(f);
1110  /* careful when using n_NormalizeHelper!!! It computes the lcm of the numerator
1111  of the 1st argument and the denominator of the 2nd!!! */
1112  while (p != NULL)
1113  {
1114  c = p_GetCoeff(p, ntRing);
1115  tmp = n_NormalizeHelper(lcmOfDenominators, c, ntCoeffs);
1116  n_Delete(&lcmOfDenominators, ntCoeffs);
1117  lcmOfDenominators = tmp;
1118  pIter(p);
1119  }
1120  p = DEN(f);
1121  while (p != NULL)
1122  {
1123  c = p_GetCoeff(p, ntRing);
1124  tmp = n_NormalizeHelper(lcmOfDenominators, c, ntCoeffs);
1125  n_Delete(&lcmOfDenominators, ntCoeffs);
1126  lcmOfDenominators = tmp;
1127  pIter(p);
1128  }
1129  if (!n_IsOne(lcmOfDenominators, ntCoeffs))
1130  { /* multiply NUM(f) and DEN(f) with lcmOfDenominators */
1131  NUM(f) = p_Mult_nn(NUM(f), lcmOfDenominators, ntRing);
1132  p_Normalize(NUM(f), ntRing);
1133  DEN(f) = p_Mult_nn(DEN(f), lcmOfDenominators, ntRing);
1134  p_Normalize(DEN(f), ntRing);
1135  }
1136  n_Delete(&lcmOfDenominators, ntCoeffs);
1137  if (DEN(f)!=NULL)
1138  { /* step (2); see documentation of this procedure above */
1139  p = NUM(f);
1140  number gcdOfCoefficients = n_Copy(p_GetCoeff(p, ntRing), ntCoeffs);
1141  pIter(p);
1142  while ((p != NULL) && (!n_IsOne(gcdOfCoefficients, ntCoeffs)))
1143  {
1144  c = p_GetCoeff(p, ntRing);
1145  tmp = n_Gcd(c, gcdOfCoefficients, ntCoeffs);
1146  n_Delete(&gcdOfCoefficients, ntCoeffs);
1147  gcdOfCoefficients = tmp;
1148  pIter(p);
1149  }
1150  p = DEN(f);
1151  while ((p != NULL) && (!n_IsOne(gcdOfCoefficients, ntCoeffs)))
1152  {
1153  c = p_GetCoeff(p, ntRing);
1154  tmp = n_Gcd(c, gcdOfCoefficients, ntCoeffs);
1155  n_Delete(&gcdOfCoefficients, ntCoeffs);
1156  gcdOfCoefficients = tmp;
1157  pIter(p);
1158  }
1159  if (!n_IsOne(gcdOfCoefficients, ntCoeffs))
1160  { /* divide NUM(f) and DEN(f) by gcdOfCoefficients */
1161  number inverseOfGcdOfCoefficients = n_Invers(gcdOfCoefficients,
1162  ntCoeffs);
1163  NUM(f) = p_Mult_nn(NUM(f), inverseOfGcdOfCoefficients, ntRing);
1164  p_Normalize(NUM(f), ntRing);
1165  DEN(f) = p_Mult_nn(DEN(f), inverseOfGcdOfCoefficients, ntRing);
1166  p_Normalize(DEN(f), ntRing);
1167  n_Delete(&inverseOfGcdOfCoefficients, ntCoeffs);
1168  }
1169  n_Delete(&gcdOfCoefficients, ntCoeffs);
1170  }
1171  }
1172 
1173  /* Now, due to the above computations, DEN(f) may have become the
1174  1-polynomial which needs to be represented by NULL: */
1175  if ((DEN(f) != NULL) &&
1176  p_IsConstant(DEN(f), ntRing) &&
1177  n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs))
1178  {
1179  p_Delete(&DEN(f), ntRing); DEN(f) = NULL;
1180  }
1181 
1182  if( DEN(f) != NULL )
1183  if( !n_GreaterZero(pGetCoeff(DEN(f)), ntCoeffs) )
1184  {
1185  NUM(f) = p_Neg(NUM(f), ntRing);
1186  DEN(f) = p_Neg(DEN(f), ntRing);
1187  }
1188 
1189  ntTest((number)f); // TODO!
1190 }
1191 
1192 /* modifies a */
1194 {
1195 // ntTest(a); // !!!!????
1196  if (IS0(a)) return;
1197 
1198  fraction f = (fraction)a;
1199  p_Normalize(NUM(f),ntRing);
1200  if (DENIS1(f) || NUMIS1(f)) { COM(f) = 0; return; }
1201 
1202  assume( DEN(f) != NULL );
1203  p_Normalize(DEN(f),ntRing);
1204 
1205  /* check whether NUM(f) = DEN(f), and - if so - replace 'a' by 1 */
1206  if (p_EqualPolys(NUM(f), DEN(f), ntRing))
1207  { /* numerator and denominator are both != 1 */
1208  p_Delete(&NUM(f), ntRing); NUM(f) = p_ISet(1, ntRing);
1209  p_Delete(&DEN(f), ntRing); DEN(f) = NULL;
1210  COM(f) = 0;
1211  }
1212  else
1213  {
1214  if (COM(f) > BOUND_COMPLEXITY)
1215  definiteGcdCancellation(a, cf, TRUE);
1216 
1217  // TODO: check if it is enough to put the following into definiteGcdCancellation?!
1218  if( DEN(f) != NULL )
1219  {
1220  if( !n_GreaterZero(pGetCoeff(DEN(f)), ntCoeffs) )
1221  {
1222  NUM(f) = p_Neg(NUM(f), ntRing);
1223  DEN(f) = p_Neg(DEN(f), ntRing);
1224  }
1225  if (ntCoeffs->has_simple_Inverse)
1226  {
1227  if (!n_IsOne(pGetCoeff(DEN(f)),ntCoeffs))
1228  {
1229  number inv=n_Invers(pGetCoeff(DEN(f)),ntCoeffs);
1230  DEN(f)=p_Mult_nn(DEN(f),inv,ntRing);
1231  NUM(f)=p_Mult_nn(NUM(f),inv,ntRing);
1232  }
1233  if(p_LmIsConstant(DEN(f),ntRing))
1234  {
1235  p_Delete(&DEN(f),ntRing);
1236  COM(f)=0;
1237  }
1238  }
1239  }
1240  }
1241 
1242  ntTest(a);
1243 }
1244 
1245 /// modifies a
1246 void definiteGcdCancellation(number a, const coeffs cf,
1247  BOOLEAN simpleTestsHaveAlreadyBeenPerformed)
1248 {
1249  ntTest(a); // !!!!
1250 
1251  fraction f = (fraction)a;
1252 
1253  if (IS0(a)) return;
1254  if (!simpleTestsHaveAlreadyBeenPerformed)
1255  {
1256  if (DENIS1(f) || NUMIS1(f)) { COM(f) = 0; return; }
1257 
1258  /* check whether NUM(f) = DEN(f), and - if so - replace 'a' by 1 */
1259  if (p_EqualPolys(NUM(f), DEN(f), ntRing))
1260  { /* numerator and denominator are both != 1 */
1261  p_Delete(&NUM(f), ntRing); NUM(f) = p_ISet(1, ntRing);
1262  p_Delete(&DEN(f), ntRing); DEN(f) = NULL;
1263  COM(f) = 0;
1264  ntTest(a); // !!!!
1265  return;
1266  }
1267  }
1268  /*if (rField_is_Q(ntRing))
1269  {
1270  number c=n_Copy(pGetCoeff(NUM(f)),ntCoeffs);
1271  poly p=pNext(NUM(f));
1272  while((p!=NULL)&&(!n_IsOne(c,ntCoeffs)))
1273  {
1274  number cc=n_Gcd(c,pGetCoeff(p),ntCoeffs);
1275  n_Delete(&c,ntCoeffs);
1276  c=cc;
1277  pIter(p);
1278  };
1279  p=DEN(f);
1280  while((p!=NULL)&&(!n_IsOne(c,ntCoeffs)))
1281  {
1282  number cc=n_Gcd(c,pGetCoeff(p),ntCoeffs);
1283  n_Delete(&c,ntCoeffs);
1284  c=cc;
1285  pIter(p);
1286  };
1287  if(!n_IsOne(c,ntCoeffs))
1288  {
1289  p=NUM(f);
1290  do
1291  {
1292  number cc=n_Div(pGetCoeff(p),c,ntCoeffs);
1293  n_Normalize(cc,ntCoeffs);
1294  p_SetCoeff(p,cc,ntRing);
1295  pIter(p);
1296  } while(p!=NULL);
1297  p=DEN(f);
1298  do
1299  {
1300  number cc=n_Div(pGetCoeff(p),c,ntCoeffs);
1301  n_Normalize(cc,ntCoeffs);
1302  p_SetCoeff(p,cc,ntRing);
1303  pIter(p);
1304  } while(p!=NULL);
1305  n_Delete(&c,ntCoeffs);
1306  if(pNext(DEN(f))==NULL)
1307  {
1308  if (p_IsOne(DEN(f),ntRing))
1309  {
1310  p_LmDelete(&DEN(f),ntRing);
1311  COM(f)=0;
1312  return;
1313  }
1314  else
1315  {
1316  return;
1317  }
1318  }
1319  }
1320  }*/
1321 
1322  /* here we assume: NUM(f), DEN(f) !=NULL, in Z_a reqp. Z/p_a */
1323  poly pGcd = singclap_gcd_and_divide(NUM(f), DEN(f), ntRing);
1324  if (p_IsConstant(pGcd, ntRing)
1325  && n_IsOne(p_GetCoeff(pGcd, ntRing), ntCoeffs)
1326  )
1327  { /* gcd = 1; nothing to cancel;
1328  Suppose the given rational function field is over Q. Although the
1329  gcd is 1, we may have produced fractional coefficients in NUM(f),
1330  DEN(f), or both, due to previous arithmetics. The next call will
1331  remove those nested fractions, in case there are any. */
1332  if (nCoeff_is_Zp(ntCoeffs))
1333  {
1334  NUM (f) = p_Div_nn (NUM (f), p_GetCoeff (DEN(f),ntRing), ntRing);
1335  if (p_IsConstant (DEN (f), ntRing))
1336  {
1337  p_Delete(&DEN (f), ntRing);
1338  DEN (f) = NULL;
1339  }
1340  else
1341  {
1342  p_Norm (DEN (f),ntRing);
1343  }
1344  } else if (nCoeff_is_Q(ntCoeffs)) handleNestedFractionsOverQ(f, cf);
1345  }
1346  else
1347  { /* We divide both NUM(f) and DEN(f) by the gcd which is known
1348  to be != 1. */
1349  if (p_IsConstant(DEN(f), ntRing) &&
1350  n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs))
1351  {
1352  /* DEN(f) = 1 needs to be represented by NULL! */
1353  p_Delete(&DEN(f), ntRing);
1354  DEN(f) = NULL;
1355  }
1356  else
1357  {
1358  if (nCoeff_is_Zp(ntCoeffs))
1359  {
1360  NUM (f) = p_Div_nn (NUM (f), p_GetCoeff (DEN(f),ntRing), ntRing);
1361  if (p_IsConstant (DEN (f), ntRing))
1362  {
1363  p_Delete(&DEN (f), ntRing);
1364  DEN (f) = NULL;
1365  }
1366  else
1367  {
1368  p_Norm (DEN (f),ntRing);
1369  }
1370  }
1371  }
1372  }
1373  COM(f) = 0;
1374  p_Delete(&pGcd, ntRing);
1375 
1376  if( DEN(f) != NULL )
1377  if( !n_GreaterZero(pGetCoeff(DEN(f)), ntCoeffs) )
1378  {
1379  NUM(f) = p_Neg(NUM(f), ntRing);
1380  DEN(f) = p_Neg(DEN(f), ntRing);
1381  if (p_IsConstant(DEN(f), ntRing) &&
1382  n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs))
1383  {
1384  /* DEN(f) = 1 needs to be represented by NULL! */
1385  p_Delete(&DEN(f), ntRing);
1386  DEN (f) = NULL;
1387  }
1388  }
1389  ntTest(a); // !!!!
1390 }
1391 
1392 // NOTE: modifies a
1393 void ntWriteLong(number &a, const coeffs cf)
1394 {
1395  ntTest(a);
1397  if (IS0(a))
1398  StringAppendS("0");
1399  else
1400  {
1401  fraction f = (fraction)a;
1402  // stole logic from napWrite from kernel/longtrans.cc of legacy singular
1403  BOOLEAN omitBrackets = p_IsConstant(NUM(f), ntRing);
1404  if (!omitBrackets) StringAppendS("(");
1405  p_String0Long(NUM(f), ntRing, ntRing);
1406  if (!omitBrackets) StringAppendS(")");
1407  if (!DENIS1(f))
1408  {
1409  StringAppendS("/");
1410  omitBrackets = p_IsConstant(DEN(f), ntRing);
1411  if (!omitBrackets) StringAppendS("(");
1412  p_String0Long(DEN(f), ntRing, ntRing);
1413  if (!omitBrackets) StringAppendS(")");
1414  }
1415  }
1416  ntTest(a); // !!!!
1417 }
1418 
1419 // NOTE: modifies a
1420 void ntWriteShort(number &a, const coeffs cf)
1421 {
1422  ntTest(a);
1424  if (IS0(a))
1425  StringAppendS("0");
1426  else
1427  {
1428  fraction f = (fraction)a;
1429  // stole logic from napWrite from kernel/longtrans.cc of legacy singular
1430  BOOLEAN omitBrackets = p_IsConstant(NUM(f), ntRing);
1431  if (!omitBrackets) StringAppendS("(");
1432  p_String0Short(NUM(f), ntRing, ntRing);
1433  if (!omitBrackets) StringAppendS(")");
1434  if (!DENIS1(f))
1435  {
1436  StringAppendS("/");
1437  omitBrackets = p_IsConstant(DEN(f), ntRing);
1438  if (!omitBrackets) StringAppendS("(");
1439  p_String0Short(DEN(f), ntRing, ntRing);
1440  if (!omitBrackets) StringAppendS(")");
1441  }
1442  }
1443  ntTest(a);
1444 }
1445 
1446 const char * ntRead(const char *s, number *a, const coeffs cf)
1447 {
1448  poly p;
1449  const char * result = p_Read(s, p, ntRing);
1450  if (p == NULL) *a = NULL;
1451  else *a = ntInit(p, cf);
1452  return result;
1453 }
1454 
1455 void ntNormalize (number &a, const coeffs cf)
1456 {
1457  if ( /*(*/ a!=NULL /*)*/ )
1458  {
1460  if ((DEN(a)!=NULL)
1461  &&(!n_GreaterZero(pGetCoeff(DEN(a)),ntCoeffs)))
1462  {
1463  NUM(a)=p_Neg(NUM(a),ntRing);
1464  DEN(a)=p_Neg(DEN(a),ntRing);
1465  }
1466  }
1467  ntTest(a); // !!!!
1468 }
1469 
1470 /* expects *param to be castable to TransExtInfo */
1471 static BOOLEAN ntCoeffIsEqual(const coeffs cf, n_coeffType n, void * param)
1472 {
1473  if (ID != n) return FALSE;
1474  TransExtInfo *e = (TransExtInfo *)param;
1475  /* for rational function fields we expect the underlying
1476  polynomial rings to be IDENTICAL, i.e. the SAME OBJECT;
1477  this expectation is based on the assumption that we have properly
1478  registered cf and perform reference counting rather than creating
1479  multiple copies of the same coefficient field/domain/ring */
1480  if (ntRing == e->r)
1481  return TRUE;
1482 
1483  // NOTE: Q(a)[x] && Q(a)[y] should better share the _same_ Q(a)...
1484  if( rEqual(ntRing, e->r, TRUE) )
1485  {
1486  rDelete(e->r);
1487  return TRUE;
1488  }
1489 
1490  return FALSE;
1491 }
1492 
1493 number ntNormalizeHelper(number a, number b, const coeffs cf)
1494 {
1495  ntTest(a);
1496  ntTest(b);
1497  fraction fb = (fraction)b;
1498  if ((b==NULL)||(DEN(fb)==NULL)) return ntCopy(a,cf);
1499  fraction fa = (fraction)a;
1500  /* singclap_gcd destroys its arguments; we hence need copies: */
1501  poly pa = p_Copy(NUM(fa), ntRing);
1502  poly pb = p_Copy(DEN(fb), ntRing);
1503 
1504  poly pGcd;
1505  if (nCoeff_is_Q(ntCoeffs))
1506  {
1507  if (p_IsConstant(pa,ntRing) && p_IsConstant(pb,ntRing))
1508  {
1509  pGcd = pa;
1510  p_SetCoeff (pGcd, n_Gcd (pGetCoeff(pGcd), pGetCoeff(pb), ntCoeffs), ntRing);
1511  }
1512  else
1513  {
1514  number contentpa, contentpb, tmp;
1515 
1516  contentpb= p_GetCoeff(pb, ntRing);
1517  pIter(pb);
1518  while (pb != NULL)
1519  {
1520  tmp = n_SubringGcd(contentpb, p_GetCoeff(pb, ntRing) , ntCoeffs);
1521  n_Delete(&contentpb, ntCoeffs);
1522  contentpb = tmp;
1523  pIter(pb);
1524  }
1525 
1526  contentpa= p_GetCoeff(pa, ntRing);
1527  pIter(pa);
1528  while (pa != NULL)
1529  {
1530  tmp = n_SubringGcd(contentpa, p_GetCoeff(pa, ntRing), ntCoeffs);
1531  n_Delete(&contentpa, ntCoeffs);
1532  contentpa = tmp;
1533  pIter(pa);
1534  }
1535 
1536  tmp= n_SubringGcd (contentpb, contentpa, ntCoeffs);
1537  n_Delete(&contentpa, ntCoeffs);
1538  n_Delete(&contentpb, ntCoeffs);
1539  contentpa= tmp;
1540  p_Delete(&pb, ntRing);
1541  p_Delete(&pa, ntRing);
1542 
1543  /* singclap_gcd destroys its arguments; we hence need copies: */
1544  pGcd = singclap_gcd(p_Copy(NUM(fa),ntRing), p_Copy(DEN(fb),ntRing), ntRing);
1545  pGcd= p_Mult_nn (pGcd, contentpa, ntRing);
1546  n_Delete(&contentpa, ntCoeffs);
1547  }
1548  }
1549  else
1550  pGcd = singclap_gcd(pa, pb, cf->extRing);
1551 
1552  /* Note that, over Q, singclap_gcd will remove the denominators in all
1553  rational coefficients of pa and pb, before starting to compute
1554  the gcd. Thus, we do not need to ensure that the coefficients of
1555  pa and pb live in Z; they may well be elements of Q\Z. */
1556 
1557  if (p_IsConstant(pGcd, ntRing) &&
1558  n_IsOne(p_GetCoeff(pGcd, ntRing), ntCoeffs))
1559  { /* gcd = 1; return pa*pb*/
1560  p_Delete(&pGcd,ntRing);
1561  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
1562  NUM(result) = pp_Mult_qq(NUM(fa),DEN(fb),ntRing);
1563 
1564  ntTest((number)result); // !!!!
1565 
1566  return (number)result;
1567  }
1568 
1569 
1570  /* return pa*pb/gcd */
1571  poly newNum = singclap_pdivide(NUM(fa), pGcd, ntRing);
1572  p_Delete(&pGcd,ntRing);
1573  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
1574  NUM(result) = p_Mult_q(p_Copy(DEN(fb),ntRing),newNum,ntRing);
1575  ntTest((number)result); // !!!!
1576  return (number)result;
1577 
1578  return NULL;
1579 }
1580 
1581 number ntGcd(number a, number b, const coeffs cf)
1582 {
1583  ntTest(a);
1584  ntTest(b);
1585  if (a==NULL) return ntCopy(b,cf);
1586  if (b==NULL) return ntCopy(a,cf);
1587  fraction fa = (fraction)a;
1588  fraction fb = (fraction)b;
1589 
1590  poly pa = p_Copy(NUM(fa), ntRing);
1591  poly pb = p_Copy(NUM(fb), ntRing);
1592 
1593  poly pGcd;
1594  if (nCoeff_is_Q(ntCoeffs))
1595  {
1596  if (p_IsConstant(pa,ntRing) && p_IsConstant(pb,ntRing))
1597  {
1598  pGcd = pa;
1599  p_SetCoeff (pGcd, n_SubringGcd (pGetCoeff(pGcd), pGetCoeff(pb), ntCoeffs), ntRing);
1600  }
1601  else
1602  {
1603  number contentpa, contentpb, tmp;
1604 
1605  contentpb= p_GetCoeff(pb, ntRing);
1606  pIter(pb);
1607  while (pb != NULL)
1608  {
1609  tmp = n_SubringGcd(contentpb, p_GetCoeff(pb, ntRing) , ntCoeffs);
1610  n_Delete(&contentpb, ntCoeffs);
1611  contentpb = tmp;
1612  pIter(pb);
1613  }
1614 
1615  contentpa= p_GetCoeff(pa, ntRing);
1616  pIter(pa);
1617  while (pa != NULL)
1618  {
1619  tmp = n_SubringGcd(contentpa, p_GetCoeff(pa, ntRing), ntCoeffs);
1620  n_Delete(&contentpa, ntCoeffs);
1621  contentpa = tmp;
1622  pIter(pa);
1623  }
1624 
1625  tmp= n_SubringGcd (contentpb, contentpa, ntCoeffs);
1626  n_Delete(&contentpa, ntCoeffs);
1627  n_Delete(&contentpb, ntCoeffs);
1628  contentpa= tmp;
1629  p_Delete(&pb, ntRing);
1630  p_Delete(&pa, ntRing);
1631 
1632  /* singclap_gcd destroys its arguments; we hence need copies: */
1633  pGcd = singclap_gcd(p_Copy(NUM(fa),ntRing), p_Copy(NUM(fb),ntRing), ntRing);
1634  pGcd= p_Mult_nn (pGcd, contentpa, ntRing);
1635  n_Delete(&contentpa, ntCoeffs);
1636  }
1637  }
1638  else
1639  pGcd = singclap_gcd(pa, pb, cf->extRing);
1640  /* Note that, over Q, singclap_gcd will remove the denominators in all
1641  rational coefficients of pa and pb, before starting to compute
1642  the gcd. Thus, we do not need to ensure that the coefficients of
1643  pa and pb live in Z; they may well be elements of Q\Z. */
1644 
1645  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
1646  NUM(result) = pGcd;
1647  ntTest((number)result); // !!!!
1648  return (number)result;
1649 }
1650 //number ntGcd_dummy(number a, number b, const coeffs cf)
1651 //{
1652 // extern char my_yylinebuf[80];
1653 // Print("ntGcd in >>%s<<\n",my_yylinebuf);
1654 // return ntGcd(a,b,cf);
1655 //}
1656 
1657 int ntSize(number a, const coeffs cf)
1658 {
1659  ntTest(a);
1660  if (IS0(a)) return -1;
1661  /* this has been taken from the old implementation of field extensions,
1662  where we computed the sum of the degrees and the numbers of terms in
1663  the numerator and denominator of a; so we leave it at that, for the
1664  time being */
1665  fraction f = (fraction)a;
1666  poly p = NUM(f);
1667  int noOfTerms = 0;
1668  int numDegree = 0;
1669  while (p != NULL)
1670  {
1671  noOfTerms++;
1672  int d = 0;
1673  for (int i = 1; i <= rVar(ntRing); i++)
1674  d += p_GetExp(p, i, ntRing);
1675  if (d > numDegree) numDegree = d;
1676  pIter(p);
1677  }
1678  int denDegree = 0;
1679  if (!DENIS1(f))
1680  {
1681  p = DEN(f);
1682  while (p != NULL)
1683  {
1684  noOfTerms++;
1685  int d = 0;
1686  for (int i = 1; i <= rVar(ntRing); i++)
1687  d += p_GetExp(p, i, ntRing);
1688  if (d > denDegree) denDegree = d;
1689  pIter(p);
1690  }
1691  }
1692  ntTest(a); // !!!!
1693  return numDegree + denDegree + noOfTerms;
1694 }
1695 
1696 number ntInvers(number a, const coeffs cf)
1697 {
1698  //check_N(a,cf);
1699  ntTest(a);
1700  if (IS0(a))
1701  {
1702  WerrorS(nDivBy0);
1703  return NULL;
1704  }
1705  fraction f = (fraction)a;
1706  assume( f != NULL );
1707 
1708  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
1709 
1710  assume( NUM(f) != NULL );
1711  const poly den = DEN(f);
1712 
1713  if (den == NULL)
1714  NUM(result) = p_One(ntRing);
1715  else
1716  NUM(result) = p_Copy(den, ntRing);
1717 
1718  if( !NUMIS1(f) )
1719  {
1720  poly num_f=NUM(f);
1721  BOOLEAN neg= !n_GreaterZero(pGetCoeff(num_f),ntCoeffs);
1722  if (neg)
1723  {
1724  num_f=p_Neg(p_Copy(num_f, ntRing), ntRing);
1725  NUM(result)=p_Neg(NUM(result), ntRing);
1726  }
1727  else
1728  {
1729  num_f=p_Copy(num_f, ntRing);
1730  }
1731  DEN(result) = num_f;
1732  COM(result) = COM(f);
1733  if (neg)
1734  {
1735  if (p_IsOne(num_f, ntRing))
1736  {
1737  DEN(result)=NULL;
1738  //COM(result) = 0;
1739  p_Delete(&num_f,ntRing);
1740  }
1741  }
1742  }
1743  //else// Alloc0
1744  //{
1745  // DEN(result) = NULL;
1746  // COM(result) = 0;
1747  //}
1748  ntTest((number)result); // !!!!
1749  //check_N((number)result,cf);
1750  return (number)result;
1751 }
1752 
1753 /* assumes that src = Q or Z, dst = Q(t_1, ..., t_s) */
1754 number ntMap00(number a, const coeffs src, const coeffs dst)
1755 {
1756  if (n_IsZero(a, src)) return NULL;
1757  n_Test(a, src);
1758  assume(src->rep == dst->extRing->cf->rep);
1759  if ((SR_HDL(a) & SR_INT) || (a->s==3))
1760  {
1761  number res=ntInit(p_NSet(n_Copy(a, src), dst->extRing), dst);
1762  n_Test(res,dst);
1763  return res;
1764  }
1765  number nn=n_GetDenom(a,src);
1766  number zz=n_GetNumerator(a,src);
1767  number res=ntInit(p_NSet(zz,dst->extRing), dst);
1768  fraction ff=(fraction)res;
1769  if (n_IsOne(nn,src)) DEN(ff)=NULL;
1770  else DEN(ff)=p_NSet(nn,dst->extRing);
1771  n_Test((number)ff,dst);
1772  //check_N((number)ff,dst);
1773  return (number)ff;
1774 }
1775 
1776 number ntMapZ0(number a, const coeffs src, const coeffs dst)
1777 {
1778  if (n_IsZero(a, src)) return NULL;
1779  n_Test(a, src);
1780  nMapFunc nMap=n_SetMap(src,dst->extRing->cf);
1781  poly p=p_NSet(nMap(a, src,dst->extRing->cf), dst->extRing);
1782  if (n_IsZero(pGetCoeff(p),dst->extRing->cf))
1783  p_Delete(&p,dst->extRing);
1784  number res=ntInit(p, dst);
1785  n_Test(res,dst);
1786  return res;
1787 }
1788 
1789 /* assumes that src = Z/p, dst = Q(t_1, ..., t_s) */
1790 number ntMapP0(number a, const coeffs src, const coeffs dst)
1791 {
1792  if (n_IsZero(a, src)) return NULL;
1793  n_Test(a, src);
1794  /* mapping via intermediate int: */
1795  int n = n_Int(a, src);
1796  number q = n_Init(n, dst->extRing->cf);
1797  if (n_IsZero(q, dst->extRing->cf))
1798  {
1799  n_Delete(&q, dst->extRing->cf);
1800  return NULL;
1801  }
1802  return ntInit(p_NSet(q, dst->extRing), dst);
1803 }
1804 
1805  /* assumes that either src = K(t_1, ..., t_s), dst = K(t_1, ..., t_s) */
1806 number ntCopyMap(number a, const coeffs cf, const coeffs dst)
1807 {
1808  ntTest(a);
1809  if (IS0(a)) return NULL;
1810 
1811  const ring rSrc = cf->extRing;
1812  const ring rDst = dst->extRing;
1813 
1814  if( rSrc == rDst )
1815  return ntCopy(a, dst); // USUALLY WRONG!
1816 
1817  fraction f = (fraction)a;
1818  poly g = prCopyR(NUM(f), rSrc, rDst);
1819 
1820  poly h = NULL;
1821 
1822  if (!DENIS1(f))
1823  h = prCopyR(DEN(f), rSrc, rDst);
1824 
1825  fraction result = (fraction)omAllocBin(fractionObjectBin);
1826 
1827  NUM(result) = g;
1828  DEN(result) = h;
1829  COM(result) = COM(f);
1830  //check_N((number)result,dst);
1831  n_Test((number)result, dst);
1832  return (number)result;
1833 }
1834 
1835 number ntGenMap(number a, const coeffs cf, const coeffs dst)
1836 {
1837  ntTest(a);
1838  if (IS0(a)) return NULL;
1839 
1840  const ring rSrc = cf->extRing;
1841  const ring rDst = dst->extRing;
1842 
1843  const nMapFunc nMap=n_SetMap(rSrc->cf,rDst->cf);
1844  fraction f = (fraction)a;
1845  poly g = prMapR(NUM(f), nMap, rSrc, rDst);
1846 
1847  poly h = NULL;
1848 
1849  if (!DENIS1(f))
1850  h = prMapR(DEN(f), nMap, rSrc, rDst);
1851 
1852  fraction result = (fraction)omAllocBin(fractionObjectBin);
1853 
1854  NUM(result) = g;
1855  DEN(result) = h;
1856  COM(result) = COM(f);
1857  //check_N((number)result,dst);
1858  n_Test((number)result, dst);
1859  return (number)result;
1860 }
1861 
1862 number ntCopyAlg(number a, const coeffs cf, const coeffs dst)
1863 {
1864  n_Test(a, cf) ;
1865  if (n_IsZero(a, cf)) return NULL;
1866  return ntInit(prCopyR((poly)a, cf->extRing, dst->extRing),dst);
1867 }
1868 
1869 number ntGenAlg(number a, const coeffs cf, const coeffs dst)
1870 {
1871  n_Test(a, cf) ;
1872  if (n_IsZero(a, cf)) return NULL;
1873 
1874  const nMapFunc nMap=n_SetMap(cf->extRing->cf,dst->extRing->cf);
1875  return ntInit(prMapR((poly)a, nMap, cf->extRing, dst->extRing),dst);
1876 }
1877 
1878 /* assumes that src = Q, dst = Z/p(t_1, ..., t_s) */
1879 number ntMap0P(number a, const coeffs src, const coeffs dst)
1880 {
1881  n_Test(a, src) ;
1882  if (n_IsZero(a, src)) return NULL;
1883  // int p = rChar(dst->extRing);
1884 
1885  number q = nlModP(a, src, dst->extRing->cf); // FIXME? TODO? // extern number nlModP(number q, const coeffs Q, const coeffs Zp); // Map q \in QQ \to Zp
1886 
1887  if (n_IsZero(q, dst->extRing->cf))
1888  {
1889  n_Delete(&q, dst->extRing->cf);
1890  return NULL;
1891  }
1892 
1893  poly g = p_NSet(q, dst->extRing);
1894 
1895  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
1896  NUM(f) = g; // DEN(f) = NULL; COM(f) = 0;
1897  n_Test((number)f, dst);
1898  //check_N((number)f,dst);
1899  return (number)f;
1900 }
1901 
1902 /* assumes that src = Z/p, dst = Z/p(t_1, ..., t_s) */
1903 number ntMapPP(number a, const coeffs src, const coeffs dst)
1904 {
1905  n_Test(a, src) ;
1906  if (n_IsZero(a, src)) return NULL;
1907  assume(src == dst->extRing->cf);
1908  poly p = p_One(dst->extRing);
1909  p_SetCoeff(p, n_Copy(a, src), dst->extRing);
1910  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
1911  NUM(f) = p; // DEN(f) = NULL; COM(f) = 0;
1912  n_Test((number)f, dst);
1913  //check_N((number)f,dst);
1914  return (number)f;
1915 }
1916 
1917 /* assumes that src = Z/u, dst = Z/p(t_1, ..., t_s), where u != p */
1918 number ntMapUP(number a, const coeffs src, const coeffs dst)
1919 {
1920  n_Test(a, src) ;
1921  if (n_IsZero(a, src)) return NULL;
1922  /* mapping via intermediate int: */
1923  int n = n_Int(a, src);
1924  number q = n_Init(n, dst->extRing->cf);
1925  poly p;
1926  if (n_IsZero(q, dst->extRing->cf))
1927  {
1928  n_Delete(&q, dst->extRing->cf);
1929  return NULL;
1930  }
1931  p = p_One(dst->extRing);
1932  p_SetCoeff(p, q, dst->extRing);
1933  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
1934  NUM(f) = p; // DEN(f) = NULL; COM(f) = 0;
1935  n_Test((number)f, dst);
1936  //check_N((number)f,dst);
1937  return (number)f;
1938 }
1939 
1940 nMapFunc ntSetMap(const coeffs src, const coeffs dst)
1941 {
1942  /* dst is expected to be a rational function field */
1943  assume(getCoeffType(dst) == ID);
1944 
1945  if( src == dst ) return ndCopyMap;
1946 
1947  int h = 0; /* the height of the extension tower given by dst */
1948  coeffs bDst = nCoeff_bottom(dst, h); /* the bottom field in the tower dst */
1949  coeffs bSrc = nCoeff_bottom(src, h); /* the bottom field in the tower src */
1950 
1951  /* for the time being, we only provide maps if h = 1 and if b is Q or
1952  some field Z/pZ: */
1953  if (h==0)
1954  {
1955  if ((src->rep==n_rep_gap_rat) && nCoeff_is_Q(bDst))
1956  return ntMap00; /// Q or Z --> Q(T)
1957  if (src->rep==n_rep_gap_gmp)
1958  return ntMapZ0; /// Z --> K(T)
1959  if (nCoeff_is_Zp(src) && nCoeff_is_Q(bDst))
1960  return ntMapP0; /// Z/p --> Q(T)
1961  if (nCoeff_is_Q(src) && nCoeff_is_Zp(bDst))
1962  return ntMap0P; /// Q --> Z/p(T)
1963  if (nCoeff_is_Zp(src) && nCoeff_is_Zp(bDst))
1964  {
1965  if (src->ch == dst->ch) return ntMapPP; /// Z/p --> Z/p(T)
1966  else return ntMapUP; /// Z/u --> Z/p(T)
1967  }
1968  }
1969  if (h != 1) return NULL;
1970  //if ((!nCoeff_is_Zp(bDst)) && (!nCoeff_is_Q(bDst))) return NULL;
1971 
1972  /* Let T denote the sequence of transcendental extension variables, i.e.,
1973  K[t_1, ..., t_s] =: K[T];
1974  Let moreover, for any such sequence T, T' denote any subsequence of T
1975  of the form t_1, ..., t_w with w <= s. */
1976 
1977  if (rVar(src->extRing) > rVar(dst->extRing))
1978  return NULL;
1979 
1980  for (int i = 0; i < rVar(src->extRing); i++)
1981  if (strcmp(rRingVar(i, src->extRing), rRingVar(i, dst->extRing)) != 0)
1982  return NULL;
1983 
1984  if (src->type==n_transExt)
1985  {
1986  if (src->extRing->cf==dst->extRing->cf)
1987  return ntCopyMap; /// K(T') --> K(T)
1988  else
1989  return ntGenMap; /// K(T') --> K'(T)
1990  }
1991  else
1992  {
1993  if (src->extRing->cf==dst->extRing->cf)
1994  return ntCopyAlg; /// K(T') --> K(T)
1995  else
1996  return ntGenAlg; /// K(T') --> K'(T)
1997  }
1998 
1999  return NULL; /// default
2000 }
2001 #if 0
2002 nMapFunc ntSetMap_T(const coeffs src, const coeffs dst)
2003 {
2004  nMapFunc n=ntSetMap(src,dst);
2005  if (n==ntCopyAlg) printf("n=ntCopyAlg\n");
2006  else if (n==ntCopyMap) printf("n=ntCopyMap\n");
2007  else if (n==ntMapUP) printf("n=ntMapUP\n");
2008  else if (n==ntMap0P) printf("n=ntMap0P\n");
2009  else if (n==ntMapP0) printf("n=ntMapP0\n");
2010  else if (n==ntMap00) printf("n=ntMap00\n");
2011  else if (n==NULL) printf("n=NULL\n");
2012  else printf("n=?\n");
2013  return n;
2014 }
2015 #endif
2016 
2018 {
2019  if ((--cf->extRing->ref) == 0)
2020  rDelete(cf->extRing);
2021 }
2023 {
2024  if (n.isZero()) return NULL;
2026  p_Normalize(p,ntRing);
2027  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
2028  NUM(result) = p;
2029  //DEN(result) = NULL; // done by omAlloc0Bin
2030  //COM(result) = 0; // done by omAlloc0Bin
2031  ntTest((number)result);
2032  return (number)result;
2033 }
2034 CanonicalForm ntConvSingNFactoryN( number n, BOOLEAN /*setChar*/, const coeffs cf )
2035 {
2036  ntTest(n);
2037  if (IS0(n)) return CanonicalForm(0);
2038 
2039  fraction f = (fraction)n;
2040  return convSingPFactoryP(NUM(f),ntRing);
2041 }
2042 
2043 static int ntParDeg(number a, const coeffs cf)
2044 {
2045  ntTest(a);
2046  if (IS0(a)) return -1;
2047  fraction fa = (fraction)a;
2048  return cf->extRing->pFDeg(NUM(fa),cf->extRing);
2049 }
2050 
2051 /// return the specified parameter as a number in the given trans.ext.
2052 static number ntParameter(const int iParameter, const coeffs cf)
2053 {
2054  assume(getCoeffType(cf) == ID);
2055 
2056  const ring R = cf->extRing;
2057  assume( R != NULL );
2058  assume( 0 < iParameter && iParameter <= rVar(R) );
2059 
2060  poly p = p_One(R); p_SetExp(p, iParameter, 1, R); p_Setm(p, R);
2061  p_Test(p,R);
2062 
2063  fraction f = (fraction)omAlloc0Bin(fractionObjectBin);
2064  NUM(f) = p;
2065  //DEN(f) = NULL;
2066  //COM(f) = 0;
2067 
2068  ntTest((number)f);
2069 
2070  return (number)f;
2071 }
2072 
2073 /// if m == var(i)/1 => return i,
2074 int ntIsParam(number m, const coeffs cf)
2075 {
2076  ntTest(m);
2077  assume(getCoeffType(cf) == ID);
2078 
2079  const ring R = cf->extRing;
2080  assume( R != NULL );
2081 
2082  fraction f = (fraction)m;
2083 
2084  if( DEN(f) != NULL )
2085  return 0;
2086 
2087  return p_Var( NUM(f), R );
2088 }
2089 
2091 {
2092  static inline poly convert(const number& n)
2093  {
2094  // suitable for trans. ext. numbers that are fractions of polys
2095  return NUM((fraction)n); // return the numerator
2096  }
2097 };
2098 
2099 
2100 static void ntClearContent(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
2101 {
2102  assume(cf != NULL);
2103  assume(getCoeffType(cf) == ID);
2104  // all coeffs are given by fractions of polynomails over integers!!!
2105  // without denominators!!!
2106 
2107  const ring R = cf->extRing;
2108  assume(R != NULL);
2109  const coeffs Q = R->cf;
2110  assume(Q != NULL);
2111  assume(nCoeff_is_Q(Q));
2112 
2113 
2114  numberCollectionEnumerator.Reset();
2115 
2116  if( !numberCollectionEnumerator.MoveNext() ) // empty zero polynomial?
2117  {
2118  c = ntInit(1, cf);
2119  return;
2120  }
2121 
2122  // all coeffs are given by integers after returning from this routine
2123 
2124  // part 1, collect product of all denominators /gcds
2125  poly cand = NULL;
2126 
2127  do
2128  {
2129  number &n = numberCollectionEnumerator.Current();
2130 
2131  ntNormalize(n, cf);
2132 
2133  fraction f = (fraction)n;
2134 
2135  assume( f != NULL );
2136 
2137  const poly den = DEN(f);
2138 
2139  assume( den == NULL ); // ?? / 1 ?
2140 
2141  const poly num = NUM(f);
2142 
2143  if( cand == NULL )
2144  cand = p_Copy(num, R);
2145  else
2146  cand = singclap_gcd(cand, p_Copy(num, R), R); // gcd(cand, num)
2147 
2148  if( p_IsConstant(cand, R) )
2149  break;
2150  }
2151  while( numberCollectionEnumerator.MoveNext() ) ;
2152 
2153 
2154  // part2: all coeffs = all coeffs * cand
2155  if( cand != NULL )
2156  {
2157  if( !p_IsConstant(cand, R) )
2158  {
2159  c = ntInit(cand, cf);
2160  numberCollectionEnumerator.Reset();
2161  while (numberCollectionEnumerator.MoveNext() )
2162  {
2163  number &n = numberCollectionEnumerator.Current();
2164  const number t = ntDiv(n, c, cf); // TODO: rewrite!?
2165  ntDelete(&n, cf);
2166  n = t;
2167  }
2168  } // else NUM (result) = p_One(R);
2169  else { p_Delete(&cand, R); cand = NULL; }
2170  }
2171 
2172  // Quick and dirty fix for constant content clearing: consider numerators???
2173  CRecursivePolyCoeffsEnumerator<NTNumConverter> itr(numberCollectionEnumerator); // recursively treat the NUM(numbers) as polys!
2174  number cc;
2175 
2176  n_ClearContent(itr, cc, Q);
2177  number g = ntInit(p_NSet(cc, R), cf);
2178 
2179  if( cand != NULL )
2180  {
2181  number gg = ntMult(g, c, cf);
2182  ntDelete(&g, cf);
2183  ntDelete(&c, cf); c = gg;
2184  } else
2185  c = g;
2186  ntTest(c);
2187 }
2188 
2189 static void ntClearDenominators(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
2190 {
2191  assume(cf != NULL);
2192  assume(getCoeffType(cf) == ID); // both over Q(a) and Zp(a)!
2193  // all coeffs are given by fractions of polynomails over integers!!!
2194 
2195  numberCollectionEnumerator.Reset();
2196 
2197  if( !numberCollectionEnumerator.MoveNext() ) // empty zero polynomial?
2198  {
2199  c = ntInit(1, cf);
2200  return;
2201  }
2202 
2203  // all coeffs are given by integers after returning from this routine
2204 
2205  // part 1, collect product of all denominators /gcds
2206  poly cand = NULL;
2207 
2208  const ring R = cf->extRing;
2209  assume(R != NULL);
2210 
2211  const coeffs Q = R->cf;
2212  assume(Q != NULL);
2213 // assume(nCoeff_is_Q(Q));
2214 
2215  do
2216  {
2217  number &n = numberCollectionEnumerator.Current();
2218 
2219  ntNormalize(n, cf);
2220 
2221  fraction f = (fraction)ntGetDenom (n, cf);
2222 
2223  assume( f != NULL );
2224 
2225  const poly den = NUM(f);
2226 
2227  if( den == NULL ) // ?? / 1 ?
2228  continue;
2229 
2230  if( cand == NULL )
2231  cand = p_Copy(den, R);
2232  else
2233  {
2234  // cand === LCM( cand, den )!!!!
2235  // NOTE: maybe it's better to make the product and clearcontent afterwards!?
2236  // TODO: move the following to factory?
2237  poly gcd = singclap_gcd(p_Copy(cand, R), p_Copy(den, R), R); // gcd(cand, den) is monic no mater leading coeffs! :((((
2238  if (nCoeff_is_Q (Q))
2239  {
2240  number LcGcd= n_SubringGcd (p_GetCoeff (cand, R), p_GetCoeff(den, R), Q);
2241  gcd = p_Mult_nn(gcd, LcGcd, R);
2242  n_Delete(&LcGcd,Q);
2243  }
2244 // assume( n_IsOne(pGetCoeff(gcd), Q) ); // TODO: this may be wrong...
2245  cand = p_Mult_q(cand, p_Copy(den, R), R); // cand *= den
2246  const poly t = singclap_pdivide( cand, gcd, R ); // cand' * den / gcd(cand', den)
2247  p_Delete(&cand, R);
2248  p_Delete(&gcd, R);
2249  cand = t;
2250  }
2251  }
2252  while( numberCollectionEnumerator.MoveNext() );
2253 
2254  if( cand == NULL )
2255  {
2256  c = ntInit(1, cf);
2257  return;
2258  }
2259 
2260  c = ntInit(cand, cf);
2261 
2262  numberCollectionEnumerator.Reset();
2263 
2264  number d = NULL;
2265 
2266  while (numberCollectionEnumerator.MoveNext() )
2267  {
2268  number &n = numberCollectionEnumerator.Current();
2269  number t = ntMult(n, c, cf); // TODO: rewrite!?
2270  ntDelete(&n, cf);
2271 
2272  ntNormalize(t, cf); // TODO: needed?
2273  n = t;
2274 
2275  fraction f = (fraction)t;
2276  assume( f != NULL );
2277 
2278  const poly den = DEN(f);
2279 
2280  if( den != NULL ) // ?? / ?? ?
2281  {
2282  assume( p_IsConstant(den, R) );
2283  assume( pNext(den) == NULL );
2284 
2285  if( d == NULL )
2286  d = n_Copy(pGetCoeff(den), Q);
2287  else
2288  {
2289  number g = n_NormalizeHelper(d, pGetCoeff(den), Q);
2290  n_Delete(&d, Q); d = g;
2291  }
2292  }
2293  }
2294 
2295  if( d != NULL )
2296  {
2297  numberCollectionEnumerator.Reset();
2298  while (numberCollectionEnumerator.MoveNext() )
2299  {
2300  number &n = numberCollectionEnumerator.Current();
2301  fraction f = (fraction)n;
2302 
2303  assume( f != NULL );
2304 
2305  const poly den = DEN(f);
2306 
2307  if( den == NULL ) // ?? / 1 ?
2308  NUM(f) = p_Mult_nn(NUM(f), d, R);
2309  else
2310  {
2311  assume( p_IsConstant(den, R) );
2312  assume( pNext(den) == NULL );
2313 
2314  number ddd = n_Div(d, pGetCoeff(den), Q); // but be an integer now!!!
2315  NUM(f) = p_Mult_nn(NUM(f), ddd, R);
2316  n_Delete(&ddd, Q);
2317 
2318  p_Delete(&DEN(f), R);
2319  DEN(f) = NULL; // TODO: check if this is needed!?
2320  }
2321 
2322  assume( DEN(f) == NULL );
2323  }
2324 
2325  NUM(c) = p_Mult_nn(NUM(c), d, R);
2326  n_Delete(&d, Q);
2327  }
2328 
2329 
2330  ntTest(c);
2331 }
2332 
2333 number ntChineseRemainder(number *x, number *q,int rl, BOOLEAN sym,const coeffs cf)
2334 {
2335  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
2336  int i;
2337 
2338  poly *P=(poly*)omAlloc(rl*sizeof(poly*));
2339  number *X=(number *)omAlloc(rl*sizeof(number));
2340 
2341  for(i=0;i<rl;i++) P[i]=p_Copy(NUM((fraction)(x[i])),cf->extRing);
2342  NUM(result)=p_ChineseRemainder(P,X,q,rl,cf->extRing);
2343 
2344  for(i=0;i<rl;i++)
2345  {
2346  P[i]=p_Copy(DEN((fraction)(x[i])),cf->extRing);
2347  if (P[i]==NULL) P[i]=p_One(cf->extRing);
2348  }
2349  DEN(result)=p_ChineseRemainder(P,X,q,rl,cf->extRing);
2350 
2351  omFreeSize(X,rl*sizeof(number));
2352  omFreeSize(P,rl*sizeof(poly*));
2353  if (p_IsConstant(DEN(result), ntRing)
2354  && n_IsOne(pGetCoeff(DEN(result)), ntCoeffs))
2355  {
2356  p_Delete(&DEN(result),ntRing);
2357  }
2358  return ((number)result);
2359 }
2360 
2361 number ntFarey(number p, number n, const coeffs cf)
2362 {
2363  // n is really a bigint
2364  fraction result = (fraction)omAlloc0Bin(fractionObjectBin);
2365  NUM(result)=p_Farey(p_Copy(NUM((fraction)p),cf->extRing),n,cf->extRing);
2366  DEN(result)=p_Farey(p_Copy(DEN((fraction)p),cf->extRing),n,cf->extRing);
2367  return ((number)result);
2368 }
2369 
2370 BOOLEAN ntInitChar(coeffs cf, void * infoStruct)
2371 {
2372 
2373  assume( infoStruct != NULL );
2374 
2375  TransExtInfo *e = (TransExtInfo *)infoStruct;
2376 
2377  assume( e->r != NULL); // extRing;
2378  assume( e->r->cf != NULL); // extRing->cf;
2379  assume( e->r->qideal == NULL );
2380 
2381  assume( cf != NULL );
2382  assume(getCoeffType(cf) == ID); // coeff type;
2383 
2384  ring R = e->r;
2385  assume(R != NULL);
2386 
2387  R->ref ++; // increase the ref.counter for the ground poly. ring!
2388 
2389  cf->extRing = R;
2390  /* propagate characteristic up so that it becomes
2391  directly accessible in cf: */
2392  cf->ch = R->cf->ch;
2393 
2394  cf->is_field=TRUE;
2395  cf->is_domain=TRUE;
2396  cf->rep=n_rep_rat_fct;
2397 
2398  cf->factoryVarOffset = R->cf->factoryVarOffset + rVar(R);
2399 
2400  cf->cfCoeffString = naCoeffString; // FIXME? TODO? // extern char* naCoeffString(const coeffs r);
2401 
2402  cf->cfGreaterZero = ntGreaterZero;
2403  cf->cfGreater = ntGreater;
2404  cf->cfEqual = ntEqual;
2405  cf->cfIsZero = ntIsZero;
2406  cf->cfIsOne = ntIsOne;
2407  cf->cfIsMOne = ntIsMOne;
2408  cf->cfInit = ntInit;
2409  cf->cfFarey = ntFarey;
2410  cf->cfChineseRemainder = ntChineseRemainder;
2411  cf->cfInt = ntInt;
2412  cf->cfInpNeg = ntNeg;
2413  cf->cfAdd = ntAdd;
2414  cf->cfSub = ntSub;
2415  cf->cfMult = ntMult;
2416  cf->cfDiv = ntDiv;
2417  cf->cfExactDiv = ntDiv;
2418  cf->cfPower = ntPower;
2419  cf->cfCopy = ntCopy;
2420  cf->cfWriteLong = ntWriteLong;
2421  cf->cfRead = ntRead;
2422  cf->cfNormalize = ntNormalize;
2423  cf->cfDelete = ntDelete;
2424  cf->cfSetMap = ntSetMap;
2425  cf->cfGetDenom = ntGetDenom;
2426  cf->cfGetNumerator = ntGetNumerator;
2427  cf->cfRePart = ntCopy;
2428  cf->cfImPart = ntImPart;
2429  cf->cfCoeffWrite = ntCoeffWrite;
2430 #ifdef LDEBUG
2431  cf->cfDBTest = ntDBTest;
2432 #endif
2433  //cf->cfGcd = ntGcd_dummy;
2434  cf->cfSubringGcd = ntGcd;
2435  cf->cfNormalizeHelper = ntNormalizeHelper;
2436  cf->cfSize = ntSize;
2437  cf->nCoeffIsEqual = ntCoeffIsEqual;
2438  cf->cfInvers = ntInvers;
2439  cf->cfKillChar = ntKillChar;
2440 
2441  if( rCanShortOut(ntRing) )
2442  cf->cfWriteShort = ntWriteShort;
2443  else
2444  cf->cfWriteShort = ntWriteLong;
2445 
2446  cf->convFactoryNSingN =ntConvFactoryNSingN;
2447  cf->convSingNFactoryN =ntConvSingNFactoryN;
2448  cf->cfParDeg = ntParDeg;
2449 
2450  cf->iNumberOfParameters = rVar(R);
2451  cf->pParameterNames = (const char**)R->names;
2452  cf->cfParameter = ntParameter;
2453  cf->has_simple_Inverse= FALSE;
2454  /* cf->has_simple_Alloc= FALSE; */
2455 
2456 
2457  if( nCoeff_is_Q(R->cf) )
2458  cf->cfClearContent = ntClearContent;
2459 
2460  cf->cfClearDenominators = ntClearDenominators;
2461 
2462  return FALSE;
2463 }
2464 
2466 template class IEnumerator<snumber*>;
#define omAllocBin(bin)
Definition: omAllocDecl.h:205
static FORCE_INLINE BOOLEAN n_Greater(number a, number b, const coeffs r)
ordered fields: TRUE iff 'a' is larger than 'b'; in Z/pZ: TRUE iff la > lb, where la and lb are the l...
Definition: coeffs.h:511
static FORCE_INLINE number n_GetNumerator(number &n, const coeffs r)
return the numerator of n (if elements of r are by nature not fractional, result is n) ...
Definition: coeffs.h:607
static FORCE_INLINE number n_Gcd(number a, number b, const coeffs r)
in Z: return the gcd of 'a' and 'b' in Z/nZ, Z/2^kZ: computed as in the case Z in Z/pZ...
Definition: coeffs.h:683
long ntInt(number &a, const coeffs cf)
Definition: transext.cc:630
const CanonicalForm int s
Definition: facAbsFact.cc:55
poly p_Diff(poly a, int k, const ring r)
Definition: p_polys.cc:1809
#define BOUND_COMPLEXITY
maximum complexity of a number
Definition: transext.cc:67
poly singclap_gcd_and_divide(poly &f, poly &g, const ring r)
clears denominators of f and g, divides by gcd(f,g)
Definition: clapsing.cc:150
number ntNormalizeHelper(number a, number b, const coeffs cf)
Definition: transext.cc:1493
number ntDiff(number a, number d, const coeffs cf)
Definition: transext.cc:759
const poly a
Definition: syzextra.cc:212
omBin_t * omBin
Definition: omStructs.h:12
#define Print
Definition: emacs.cc:83
static FORCE_INLINE BOOLEAN nCoeff_is_Zp(const coeffs r)
Definition: coeffs.h:816
number ntMap00(number a, const coeffs src, const coeffs dst)
Definition: transext.cc:1754
number ntMapUP(number a, const coeffs src, const coeffs dst)
Definition: transext.cc:1918
poly prCopyR(poly p, ring src_r, ring dest_r)
Definition: prCopy.cc:36
number ntGenMap(number a, const coeffs cf, const coeffs dst)
Definition: transext.cc:1835
number ntImPart(number a, const coeffs cf)
Definition: transext.cc:556
void ntDelete(number *a, const coeffs cf)
Definition: transext.cc:283
static poly convert(const number &n)
Definition: transext.cc:2092
CanonicalForm num(const CanonicalForm &f)
used for all transcendental extensions, i.e., the top-most extension in an extension tower is transce...
Definition: coeffs.h:37
#define DIFF_COMPLEXITY
complexity increase due to * and /
Definition: transext.cc:66
void p_String0Long(const poly p, ring lmRing, ring tailRing)
print p in a long way
Definition: polys0.cc:119
#define FALSE
Definition: auxiliary.h:140
number ntDiv(number a, number b, const coeffs cf)
Definition: transext.cc:963
number ntChineseRemainder(number *x, number *q, int rl, BOOLEAN sym, const coeffs cf)
Definition: transext.cc:2333
return P p
Definition: myNF.cc:203
static FORCE_INLINE BOOLEAN n_IsOne(number n, const coeffs r)
TRUE iff 'n' represents the one element.
Definition: coeffs.h:468
f
Definition: cfModGcd.cc:4022
poly p_NSet(number n, const ring r)
returns the poly representing the number n, destroys n
Definition: p_polys.cc:1448
number ndCopyMap(number a, const coeffs aRing, const coeffs r)
Definition: numbers.cc:228
BOOLEAN ntIsMOne(number a, const coeffs cf)
Definition: transext.cc:530
number ntMult(number a, number b, const coeffs cf)
Definition: transext.cc:893
rational (GMP) numbers
Definition: coeffs.h:30
static FORCE_INLINE number n_Init(long i, const coeffs r)
a number representing i in the given coeff field/ring r
Definition: coeffs.h:537
#define omFreeSize(addr, size)
Definition: omAllocDecl.h:260
#define ntTest(a)
Definition: transext.cc:76
const CanonicalForm CFMap CFMap int &both_non_zero int n
Definition: cfEzgcd.cc:52
number ntSub(number a, number b, const coeffs cf)
Definition: transext.cc:855
static short rVar(const ring r)
#define rVar(r) (r->N)
Definition: ring.h:531
poly singclap_gcd(poly f, poly g, const ring r)
destroys f and g
Definition: clapsing.cc:287
(), see rinteger.h, new impl.
Definition: coeffs.h:110
void ntWriteLong(number &a, const coeffs cf)
Definition: transext.cc:1393
poly p_Div_nn(poly p, const number n, const ring r)
Definition: p_polys.cc:1480
void ntWriteShort(number &a, const coeffs cf)
Definition: transext.cc:1420
#define COM(f)
Definition: transext.cc:72
factory's main class
Definition: canonicalform.h:72
#define TRUE
Definition: auxiliary.h:144
int ntSize(number a, const coeffs cf)
Definition: transext.cc:1657
void handleNestedFractionsOverQ(fraction f, const coeffs cf)
Definition: transext.cc:1100
static long p_Totaldegree(poly p, const ring r)
Definition: p_polys.h:1435
BOOLEAN ntIsZero(number a, const coeffs cf)
Definition: transext.cc:276
static FORCE_INLINE void n_Normalize(number &n, const coeffs r)
inplace-normalization of n; produces some canonical representation of n;
Definition: coeffs.h:577
void * ADDRESS
Definition: auxiliary.h:161
BOOLEAN ntDBTest(number a, const char *f, const int l, const coeffs r)
Definition: transext.cc:178
g
Definition: cfModGcd.cc:4031
void WerrorS(const char *s)
Definition: feFopen.cc:23
int k
Definition: cfEzgcd.cc:93
static FORCE_INLINE number n_NormalizeHelper(number a, number b, const coeffs r)
assume that r is a quotient field (otherwise, return 1) for arguments (a1/a2,b1/b2) return (lcm(a1...
Definition: coeffs.h:714
(fraction), see transext.h
Definition: coeffs.h:112
nMapFunc ntSetMap(const coeffs src, const coeffs dst)
Get a mapping function from src into the domain of this type (n_transExt)
Definition: transext.cc:1940
void p_Norm(poly p1, const ring r)
Definition: p_polys.cc:3528
#define Q
Definition: sirandom.c:25
CF_NO_INLINE bool isZero() const
Definition: cf_inline.cc:372
static FORCE_INLINE BOOLEAN nCoeff_is_Q(const coeffs r)
Definition: coeffs.h:822
static number & pGetCoeff(poly p)
return an alias to the leading coefficient of p assumes that p != NULL NOTE: not copy ...
Definition: monomials.h:51
char * naCoeffString(const coeffs r)
Definition: algext.cc:1346
poly singclap_pdivide(poly f, poly g, const ring r)
Definition: clapsing.cc:547
#define omAlloc(size)
Definition: omAllocDecl.h:210
static number p_SetCoeff(poly p, number n, ring r)
Definition: p_polys.h:401
poly p_Sub(poly p1, poly p2, const ring r)
Definition: p_polys.cc:1901
static coeffs nCoeff_bottom(const coeffs r, int &height)
Definition: transext.cc:262
static BOOLEAN rCanShortOut(const ring r)
Definition: ring.h:525
BOOLEAN ntIsOne(number a, const coeffs cf)
Definition: transext.cc:521
static poly p_Copy(poly p, const ring r)
returns a copy of p
Definition: p_polys.h:811
void ntNormalize(number &a, const coeffs cf)
Definition: transext.cc:1455
poly prMapR(poly src, nMapFunc nMap, ring src_r, ring dest_r)
Definition: prCopy.cc:47
number ntInvers(number a, const coeffs cf)
Definition: transext.cc:1696
static BOOLEAN p_LmIsConstant(const poly p, const ring r)
Definition: p_polys.h:954
#define pIter(p)
Definition: monomials.h:44
poly res
Definition: myNF.cc:322
BOOLEAN ntGreater(number a, number b, const coeffs cf)
Definition: transext.cc:658
static int ntParDeg(number a, const coeffs cf)
Definition: transext.cc:2043
static FORCE_INLINE number n_Mult(number a, number b, const coeffs r)
return the product of 'a' and 'b', i.e., a*b
Definition: coeffs.h:633
virtual void Reset()=0
Sets the enumerator to its initial position: -1, which is before the first element in the collection...
const char * p_Read(const char *st, poly &rc, const ring r)
Definition: p_polys.cc:1353
number ntCopyMap(number a, const coeffs cf, const coeffs dst)
Definition: transext.cc:1806
const char * ntRead(const char *s, number *a, const coeffs cf)
Definition: transext.cc:1446
static FORCE_INLINE void n_ClearContent(ICoeffsEnumerator &numberCollectionEnumerator, number &c, const coeffs r)
Computes the content and (inplace) divides it out on a collection of numbers number c is the content ...
Definition: coeffs.h:927
static void ntClearDenominators(ICoeffsEnumerator &numberCollectionEnumerator, number &c, const coeffs cf)
Definition: transext.cc:2189
const ring r
Definition: syzextra.cc:208
number ntMapPP(number a, const coeffs src, const coeffs dst)
Definition: transext.cc:1903
Coefficient rings, fields and other domains suitable for Singular polynomials.
poly p_Farey(poly p, number N, const ring r)
Definition: p_polys.cc:61
CanonicalForm ntConvSingNFactoryN(number n, BOOLEAN, const coeffs cf)
Definition: transext.cc:2034
static FORCE_INLINE long n_Int(number &n, const coeffs r)
conversion of n to an int; 0 if not possible in Z/pZ: the representing int lying in (-p/2 ...
Definition: coeffs.h:546
poly p_One(const ring r)
Definition: p_polys.cc:1318
Concrete implementation of enumerators over polynomials.
static long p_GetExp(const poly p, const unsigned long iBitmask, const int VarOffset)
get a single variable exponent : the integer VarOffset encodes:
Definition: p_polys.h:465
This is a polynomial enumerator for simple iteration over coefficients of polynomials.
polyrec * poly
Definition: hilb.h:10
number ntInit(long i, const coeffs cf)
Definition: transext.cc:562
#define assume(x)
Definition: mod2.h:405
static BOOLEAN p_IsConstant(const poly p, const ring r)
Definition: p_polys.h:1781
The main handler for Singular numbers which are suitable for Singular polynomials.
Templated enumerator interface for simple iteration over a generic collection of T's.
Definition: Enumerator.h:124
number ntFarey(number p, number n, const coeffs cf)
Definition: transext.cc:2361
number ntGetDenom(number &a, const coeffs cf)
TODO: normalization of a!?
Definition: transext.cc:419
number ntGenAlg(number a, const coeffs cf, const coeffs dst)
Definition: transext.cc:1869
static poly pp_Mult_qq(poly p, poly q, const ring r)
Definition: p_polys.h:1075
void StringAppendS(const char *st)
Definition: reporter.cc:107
#define A
Definition: sirandom.c:23
poly convFactoryPSingP(const CanonicalForm &f, const ring r)
Definition: clapconv.cc:41
number(* nMapFunc)(number a, const coeffs src, const coeffs dst)
maps "a", which lives in src, into dst
Definition: coeffs.h:71
number ntMapP0(number a, const coeffs src, const coeffs dst)
Definition: transext.cc:1790
static const n_coeffType ID
Our own type!
Definition: transext.cc:83
number nlModP(number q, const coeffs Q, const coeffs Zp)
Definition: longrat.cc:1355
virtual reference Current()=0
Gets the current element in the collection (read and write).
number ntNeg(number a, const coeffs cf)
this is in-place, modifies a
Definition: transext.cc:543
#define n_Test(a, r)
BOOLEAN n_Test(number a, const coeffs r)
Definition: coeffs.h:918
All the auxiliary stuff.
static FORCE_INLINE number n_Invers(number a, const coeffs r)
return the multiplicative inverse of 'a'; raise an error if 'a' is not invertible ...
Definition: coeffs.h:563
int m
Definition: cfEzgcd.cc:119
static FORCE_INLINE number n_InpNeg(number n, const coeffs r)
in-place negation of n MUST BE USED: n = n_InpNeg(n) (no copy is returned)
Definition: coeffs.h:556
static BOOLEAN ntCoeffIsEqual(const coeffs cf, n_coeffType n, void *param)
Definition: transext.cc:1471
#define NUMIS1(f)
TRUE iff num. represents 1.
Definition: transext.cc:70
struct for passing initialization parameters to naInitChar
Definition: transext.h:92
poly p_ChineseRemainder(poly *xx, number *x, number *q, int rl, const ring R)
Definition: p_polys.cc:94
const char *const nDivBy0
Definition: numbers.h:83
static BOOLEAN p_IsOne(const poly p, const ring R)
either poly(1) or gen(k)?!
Definition: p_polys.h:1789
int i
Definition: cfEzgcd.cc:123
void PrintS(const char *s)
Definition: reporter.cc:294
static char * rRingVar(short i, const ring r)
Definition: ring.h:516
static poly p_Mult_nn(poly p, number n, const ring r)
Definition: p_polys.h:902
BOOLEAN ntGreaterZero(number a, const coeffs cf)
forward declarations
Definition: transext.cc:711
number ntRePart(number a, const coeffs cf)
CanonicalForm factor
Definition: facAbsFact.cc:101
void definiteGcdCancellation(number a, const coeffs cf, BOOLEAN simpleTestsHaveAlreadyBeenPerformed)
modifies a
Definition: transext.cc:1246
static FORCE_INLINE BOOLEAN n_IsZero(number n, const coeffs r)
TRUE iff 'n' represents the zero element.
Definition: coeffs.h:464
BOOLEAN rEqual(ring r1, ring r2, BOOLEAN qr)
returns TRUE, if r1 equals r2 FALSE, otherwise Equality is determined componentwise, if qr == 1, then qrideal equality is tested, as well
Definition: ring.cc:1594
static FORCE_INLINE nMapFunc n_SetMap(const coeffs src, const coeffs dst)
set the mapping function pointers for translating numbers from src to dst
Definition: coeffs.h:718
go into polynomials over an alg. extension recursively
static FORCE_INLINE n_coeffType getCoeffType(const coeffs r)
Returns the type of coeffs domain.
Definition: coeffs.h:421
BOOLEAN p_EqualPolys(poly p1, poly p2, const ring r)
Definition: p_polys.cc:4288
#define p_Test(p, r)
Definition: p_polys.h:160
number ntCopy(number a, const coeffs cf)
Definition: transext.cc:341
static void ntClearContent(ICoeffsEnumerator &numberCollectionEnumerator, number &c, const coeffs cf)
Definition: transext.cc:2100
void p_Normalize(poly p, const ring r)
Definition: p_polys.cc:3584
static void p_Delete(poly *p, const ring r)
Definition: p_polys.h:850
#define omAlloc0Bin(bin)
Definition: omAllocDecl.h:206
#define omGetSpecBin(size)
Definition: omBin.h:11
(number), see longrat.h
Definition: coeffs.h:109
static unsigned long p_SetExp(poly p, const unsigned long e, const unsigned long iBitmask, const int VarOffset)
set a single variable exponent : VarOffset encodes the position in p->exp
Definition: p_polys.h:484
void heuristicGcdCancellation(number a, const coeffs cf)
Definition: transext.cc:1193
n_coeffType
Definition: coeffs.h:26
CanonicalForm cf
Definition: cfModGcd.cc:4024
static FORCE_INLINE void n_CoeffWrite(const coeffs r, BOOLEAN details=TRUE)
output the coeff description
Definition: coeffs.h:735
#define NULL
Definition: omList.c:10
CanonicalForm convSingPFactoryP(poly p, const ring r)
Definition: clapconv.cc:88
number ntAdd(number a, number b, const coeffs cf)
Definition: transext.cc:815
static FORCE_INLINE number n_Copy(number n, const coeffs r)
return a copy of 'n'
Definition: coeffs.h:451
static number ntParameter(const int iParameter, const coeffs cf)
return the specified parameter as a number in the given trans.ext.
Definition: transext.cc:2052
CanonicalForm den(const CanonicalForm &f)
void rDelete(ring r)
unconditionally deletes fields in r
Definition: ring.cc:448
BOOLEAN ntEqual(number a, number b, const coeffs cf)
Definition: transext.cc:295
static FORCE_INLINE number n_Div(number a, number b, const coeffs r)
return the quotient of 'a' and 'b', i.e., a/b; raises an error if 'b' is not invertible in r exceptio...
Definition: coeffs.h:613
virtual bool MoveNext()=0
Advances the enumerator to the next element of the collection. returns true if the enumerator was suc...
int gcd(int a, int b)
Definition: walkSupport.cc:839
#define R
Definition: sirandom.c:26
number ntMapZ0(number a, const coeffs src, const coeffs dst)
Definition: transext.cc:1776
#define SR_INT
Definition: longrat.h:65
void ntPower(number a, int exp, number *b, const coeffs cf)
Definition: transext.cc:1010
void ntKillChar(coeffs cf)
Definition: transext.cc:2017
Variable x
Definition: cfModGcd.cc:4023
number ntConvFactoryNSingN(const CanonicalForm n, const coeffs cf)
Definition: transext.cc:2022
static FORCE_INLINE number n_GetDenom(number &n, const coeffs r)
return the denominator of n (if elements of r are by nature not fractional, result is 1) ...
Definition: coeffs.h:602
#define pNext(p)
Definition: monomials.h:43
#define ntCoeffs
Definition: transext.cc:93
static void p_Setm(poly p, const ring r)
Definition: p_polys.h:436
#define p_GetCoeff(p, r)
Definition: monomials.h:57
static FORCE_INLINE number n_SubringGcd(number a, number b, const coeffs r)
Definition: coeffs.h:685
number ntGetNumerator(number &a, const coeffs cf)
TODO: normalization of a!?
Definition: transext.cc:358
static FORCE_INLINE BOOLEAN nCoeff_is_Extension(const coeffs r)
Definition: coeffs.h:839
int ntIsParam(number m, const coeffs cf)
if m == var(i)/1 => return i,
Definition: transext.cc:2074
p exp[i]
Definition: DebugPrint.cc:39
static poly p_Neg(poly p, const ring r)
Definition: p_polys.h:1018
number ntMap0P(number a, const coeffs src, const coeffs dst)
Definition: transext.cc:1879
#define SR_HDL(A)
Definition: tgb.cc:35
static FORCE_INLINE void n_Delete(number *p, const coeffs r)
delete 'p'
Definition: coeffs.h:455
#define ntRing
Definition: transext.cc:87
static FORCE_INLINE BOOLEAN n_IsMOne(number n, const coeffs r)
TRUE iff 'n' represents the additive inverse of the one element, i.e. -1.
Definition: coeffs.h:472
static FORCE_INLINE BOOLEAN n_GreaterZero(number n, const coeffs r)
ordered fields: TRUE iff 'n' is positive; in Z/pZ: TRUE iff 0 < m <= roundedBelow(p/2), where m is the long representing n in C: TRUE iff (Im(n) != 0 and Im(n) >= 0) or (Im(n) == 0 and Re(n) >= 0) in K(a)/: TRUE iff (n != 0 and (LC(n) > 0 or deg(n) > 0)) in K(t_1, ..., t_n): TRUE iff (LC(numerator(n) is a constant and > 0) or (LC(numerator(n) is not a constant) in Z/2^kZ: TRUE iff 0 < n <= 2^(k-1) in Z/mZ: TRUE iff the internal mpz is greater than zero in Z: TRUE iff n > 0
Definition: coeffs.h:494
#define ADD_COMPLEXITY
complexity increase due to + and -
Definition: transext.cc:64
kBucketDestroy & P
Definition: myNF.cc:191
static poly p_Add_q(poly p, poly q, const ring r)
Definition: p_polys.h:884
#define omFreeBin(addr, bin)
Definition: omAllocDecl.h:259
Rational pow(const Rational &a, int e)
Definition: GMPrat.cc:418
static Poly * h
Definition: janet.cc:978
number ntCopyAlg(number a, const coeffs cf, const coeffs dst)
Definition: transext.cc:1862
int BOOLEAN
Definition: auxiliary.h:131
const poly b
Definition: syzextra.cc:213
number ntGcd(number a, number b, const coeffs cf)
Definition: transext.cc:1581
int p_Var(poly m, const ring r)
Definition: p_polys.cc:4432
#define MULT_COMPLEXITY
complexity increase due to * and /
Definition: transext.cc:65
poly p_ISet(long i, const ring r)
returns the poly representing the integer i
Definition: p_polys.cc:1302
static poly p_Mult_q(poly p, poly q, const ring r)
Definition: p_polys.h:1025
void ntCoeffWrite(const coeffs cf, BOOLEAN details)
Definition: transext.cc:721
void p_String0Short(const poly p, ring lmRing, ring tailRing)
print p in a short way, if possible
Definition: polys0.cc:100
return result
Definition: facAbsBiFact.cc:76
int l
Definition: cfEzgcd.cc:94
const CanonicalForm const CanonicalForm const CanonicalForm const CanonicalForm & cand
Definition: cfModGcd.cc:69
static FORCE_INLINE void n_ClearDenominators(ICoeffsEnumerator &numberCollectionEnumerator, number &d, const coeffs r)
(inplace) Clears denominators on a collection of numbers number d is the LCM of all the coefficient d...
Definition: coeffs.h:934
BOOLEAN ntInitChar(coeffs cf, void *infoStruct)
Initialize the coeffs object.
Definition: transext.cc:2370
omBin fractionObjectBin
Definition: transext.cc:96