source: git/libpolys/polys/ext_fields/longtrans.cc @ 32d07a5

spielwiese
Last change on this file since 32d07a5 was 32d07a5, checked in by Oleksandr Motsak <motsak@…>, 13 years ago
Adding/Fixing currRing for non-commutative stuff
  • Property mode set to 100644
File size: 52.3 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: longtrans.cc 12469 2011-02-25 13:38:49Z seelisch $ */
5/*
6* ABSTRACT:   numbers in transcendental field extensions, i.e.,
7              in rational function fields
8*/
9
10#if 0
11#include <stdio.h>
12#include <string.h>
13#include <omalloc/omalloc.h>
14#include <resources/feFopen.h>
15#include <coeffs/longrat.h>
16#include <coeffs/modulop.h>
17#include <coeffs/numbers.h>
18// #include <polys/polys.h>
19#include <polys/simpleideals.h>
20#include <polys/monomials/ring.h>
21#ifdef HAVE_FACTORY
22#define SI_DONT_HAVE_GLOBAL_VARS
23#include <factory/factory.h>
24//#include <kernel/clapsing.h>
25//#include <kernel/clapconv.h>
26#endif
27#include <polys/ext_fields/longtrans.h>
28#include <polys/ext_fields/longalg.h>
29
30ring nacRing;
31int  ntIsChar0;
32ring ntMapRing;
33int  ntParsToCopy;
34int  ntNumbOfPar;
35
36
37  #if 0 /*vertagt*/
38  if (nField_is_Extension(r))
39  {
40    //ntInitChar(c,TRUE,r);
41    n->cfDelete       = ntDelete;
42    n->nNormalize     = ntNormalize;
43    n->cfInit         = ntInit;
44    n->nPar           = ntPar;
45    n->nParDeg        = ntParDeg;
46    n->n_Int          = ntInt;
47    n->nAdd           = ntAdd;
48    n->nSub           = ntSub;
49    n->nMult          = ntMult;
50    n->nDiv           = ntDiv;
51    n->nExactDiv      = ntDiv;
52    n->nIntDiv        = ntIntDiv;
53    n->nNeg           = ntNeg;
54    n->nInvers        = ntInvers;
55    //n->nCopy          = ntCopy;
56    n->cfCopy         = nt_Copy;
57    n->nGreater       = ntGreater;
58    n->nEqual         = ntEqual;
59    n->nIsZero        = ntIsZero;
60    n->nIsOne         = ntIsOne;
61    n->nIsMOne        = ntIsMOne;
62    n->nGreaterZero   = ntGreaterZero;
63    n->cfWrite        = ntWrite;
64    n->nRead          = ntRead;
65    n->nPower         = ntPower;
66    n->nGcd           = ntGcd;
67    n->nLcm           = ntLcm;
68    n->cfSetMap       = ntSetMap;
69    n->nName          = ntName;
70    n->nSize          = ntSize;
71    n->cfGetDenom     = napGetDenom;
72    n->cfGetNumerator = napGetNumerator;
73#ifdef LDEBUG
74    n->nDBTest        = ntDBTest;
75#endif
76  }
77  #endif
78
79
80numberfunc  nacMult, nacSub, nacAdd, nacDiv, nacIntDiv;
81number      (*ntMap)(number from);
82number      (*nacGcd)(number a, number b, const ring r);
83number      (*nacLcm)(number a, number b, const ring r);
84number      (*nacInit)(int i, const ring r);
85int         (*nacInt)(number &n, const ring r);
86void        (*nacNormalize)(number &a);
87number      (*nacNeg)(number a);
88number      (*nacCopy)(number a);
89number      (*nacInvers)(number a);
90BOOLEAN     (*nacIsZero)(number a);
91BOOLEAN     (*nacIsOne)(number a);
92BOOLEAN     (*nacGreaterZero)(number a);
93BOOLEAN     (*nacGreater)(number a, number b);
94number      (*nacMap)(number);
95
96#ifdef LDEBUG
97#define ntTest(a) ntDBTest(a,__FILE__,__LINE__)
98BOOLEAN ntDBTest(number a, const char *f,const int l);
99#else
100#define ntTest(a)
101#endif
102
103//static number ntdGcd( number a, number b, const ring r) { return nacInit(1,r); }
104/*2
105*  sets the appropriate operators
106*/
107void ntSetChar(int i, ring r)
108{
109  assume((r->minpoly  == NULL) &&
110         (r->minideal == NULL)    );
111 
112  if (naI!=NULL)
113  {
114    int j;
115    for (j=naI->anz-1; j>=0; j--)
116       p_Delete (&naI->liste[j],nacRing);
117    omFreeSize((ADDRESS)naI->liste,naI->anz*sizeof(poly));
118    omFreeBin((ADDRESS)naI, snaIdeal_bin);
119    naI=NULL;
120  }
121  ntMap = ntCopy;
122  naMinimalPoly = NULL;
123
124  ntNumbOfPar=rPar(r);
125  if (i == 1)
126    ntIsChar0 = 1;
127  else if (i < 0)
128  {
129    ntIsChar0 = 0;
130    npSetChar(-i, r->algring); // to be changed HS
131  }
132#ifdef TEST
133  else
134  {
135    Print("ntSetChar:c=%d param=%d\n",i,rPar(r));
136  }
137#endif
138  nacRing        = r->algring;
139  nacInit        = nacRing->cf->cfInit;
140  nacInt         = nacRing->cf->n_Int;
141  nacCopy        = nacRing->cf->nCopy;
142  nacAdd         = nacRing->cf->nAdd;
143  nacSub         = nacRing->cf->nSub;
144  nacNormalize   = nacRing->cf->nNormalize;
145  nacNeg         = nacRing->cf->nNeg;
146  nacIsZero      = nacRing->cf->nIsZero;
147  nacGreaterZero = nacRing->cf->nGreaterZero;
148  nacGreater     = nacRing->cf->nGreater;
149  nacIsOne       = nacRing->cf->nIsOne;
150  nacGcd         = nacRing->cf->nGcd;
151  nacLcm         = nacRing->cf->nLcm;
152  nacMult        = nacRing->cf->nMult;
153  nacDiv         = nacRing->cf->nDiv;
154  nacIntDiv      = nacRing->cf->nIntDiv;
155  nacInvers      = nacRing->cf->nInvers;
156}
157
158/*============= procedure for polynomials: napXXXX =======================*/
159
160#ifdef LDEBUG
161void napTest(poly p)
162{
163  if (ntIsChar0)
164  {
165    while (p != NULL)
166    {
167      nlDBTest(pGetCoeff(p), "", 0);
168      pIter(p);
169    }
170  }
171}
172#else
173#define napTest(p) ((void) 0)
174#endif
175
176/* creates a new poly that consists of a
177   single coefficient (provided as a number);
178   the provided number is NOT const */
179poly napInitz(number z)
180{
181  poly a = (poly)p_Init(nacRing);
182  pGetCoeff(a) = z;
183  return a;
184}
185
186/* creates a new poly which is the
187   negative inverse of the argument;
188   keeps p */
189poly napCopyNeg(const poly p)
190{
191  poly r = napCopy(p);
192  r = (poly)p_Neg((poly)r, nacRing);
193  return r;
194}
195
196/* modifies the poly p to p*z, i.e.
197   in-place multiplication of p with the number z;
198   keeps z */
199void napMultN(poly p, const number z)
200{
201  number t;
202  while (p != NULL)
203  {
204    t = nacMult(pGetCoeff(p), z);
205    nacNormalize(t);
206    n_Delete(&pGetCoeff(p),nacRing);
207    pGetCoeff(p) = t;
208    pIter(p);
209  }
210}
211
212/* division of f by g with remainder
213   (with respect to the first variable),
214   f = g * q + r,
215   assumes that the exponent of the first variable
216   in f is greater than or equal to that in g
217   sets q, r; destroys f; keeps g */
218void napDivMod(poly f, const poly  g, poly *q, poly *r)
219{
220  poly a, h, b, qq;
221
222  qq = (poly)p_Init(nacRing);
223  pNext(qq) = b = NULL;
224  p_Normalize(g, nacRing);
225  p_Normalize(f, nacRing);
226  a = f;
227  assume(p_GetExp(a, 1, nacRing) >= p_GetExp(g, 1, nacRing));
228  do
229  {
230    napSetExp(qq, 1, p_GetExp(a, 1, nacRing) - p_GetExp(g, 1, nacRing));
231    p_Setm(qq, nacRing);
232    pGetCoeff(qq) = nacDiv(pGetCoeff(a), pGetCoeff(g));
233    nacNormalize(pGetCoeff(qq));
234    b = napAdd(b, napCopy(qq));
235    pGetCoeff(qq) = nacNeg(pGetCoeff(qq));
236    h = napCopy(g);
237    napMultT(h, qq);
238    p_Normalize(h, nacRing);
239    n_Delete(&pGetCoeff(qq), nacRing);
240    a = napAdd(a, h);
241  }
242  while ((a != NULL) &&
243         (p_GetExp(a, 1, nacRing) >= p_GetExp(g, 1, nacRing)));
244  omFreeBinAddr(qq);
245  *q = b;
246  *r = a;
247}
248
249/* remainder of division of f by g
250   (with respect to the first variable),
251   f = g * q + r,
252   assumes that the exponent of the first variable
253   in f is greater than or equal to that in g
254   destroys f; keeps g; returns r */
255poly napRemainder(poly f, const poly g)
256{
257  poly a, h, qq;
258
259  qq = (poly)p_Init(nacRing);
260  pNext(qq) = NULL;
261  p_Normalize(g, nacRing);
262  p_Normalize(f, nacRing);
263  a = f;
264  assume(p_GetExp(a, 1, nacRing) >= p_GetExp(g, 1, nacRing));
265  do
266  {
267    napSetExp(qq, 1, p_GetExp(a, 1, nacRing) - p_GetExp(g, 1, nacRing));
268    napSetm(qq);
269    pGetCoeff(qq) = nacDiv(pGetCoeff(a), pGetCoeff(g));
270    pGetCoeff(qq) = nacNeg(pGetCoeff(qq));
271    nacNormalize(pGetCoeff(qq));
272    h = napCopy(g);
273    napMultT(h, qq);
274    p_Normalize(h, nacRing);
275    n_Delete(&pGetCoeff(qq), nacRing);
276    a = napAdd(a, h);
277  }
278  while ((a != NULL) &&
279         (p_GetExp(a,1,nacRing) >= p_GetExp(g,1,nacRing)));
280  omFreeBinAddr(qq);
281  return a;
282}
283
284/* returns z such that z * x mod c = 1;
285   if there is no solution, an error is reported and
286   some intermediate version of x is returned;
287   modifies x; keeps c */
288poly napInvers(poly x, const poly c)
289{
290  poly y, r, qa, qn, q;
291  number t;
292
293  if (p_GetExp(x, 1, nacRing) >= p_GetExp(c, 1, nacRing))
294    x = napRemainder(x, c);
295  if (x == NULL)
296  {
297    WerrorS("zero divisor found - your minpoly is not irreducible");
298    return NULL;
299  }
300  if (p_GetExp(x, 1, nacRing) == 0)
301  {
302    if (!nacIsOne(pGetCoeff(x)))
303    {
304      nacNormalize(pGetCoeff(x));
305      t = nacInvers(pGetCoeff(x));
306      nacNormalize(t);
307      n_Delete(&pGetCoeff(x), nacRing);
308      pGetCoeff(x) = t;
309    }
310    return x;
311  }
312  y = napCopy(c);
313  napDivMod(y, x, &qa, &r);
314  if (r == NULL)
315  {
316    WerrorS("x is not invertible modulo c(1)");
317    return x;
318  }
319  if (p_GetExp(r, 1, nacRing) == 0)
320  {
321    nacNormalize(pGetCoeff(r));
322    t = nacInvers(pGetCoeff(r));
323    nacNormalize(t);
324    t = nacNeg(t);
325    napMultN(qa, t);
326    n_Delete(&t, nacRing);
327    p_Normalize(qa, nacRing);
328    p_Delete(&x, nacRing);
329    p_Delete(&r, nacRing);
330    return qa;
331  }
332  y = x;
333  x = r;
334  napDivMod(y, x, &q, &r);
335  if (r == NULL)
336  {
337    WerrorS("x is not invertible modulo c(2)");
338    return x;
339  }
340  if (p_GetExp(r, 1, nacRing) == 0)
341  {
342    q = p_Mult_q(q, qa,nacRing);
343    q = napAdd(q, p_ISet(1, nacRing));
344    nacNormalize(pGetCoeff(r));
345    t = nacInvers(pGetCoeff(r));
346    napMultN(q, t);
347    p_Normalize(q, nacRing);
348    n_Delete(&t, nacRing);
349    p_Delete(&x, nacRing);
350    p_Delete(&r, nacRing);
351    if (p_GetExp(q, 1, nacRing) >= p_GetExp(c, 1, nacRing))
352      q = napRemainder(q, c);
353    return q;
354  }
355  q = p_Mult_q(q, napCopy(qa), nacRing);
356  q = napAdd(q, p_ISet(1, nacRing));
357  qa = napNeg(qa);
358  loop
359  {
360    y = x;
361    x = r;
362    napDivMod(y, x, &qn, &r);
363    if (r == NULL)
364    {
365      WerrorS("zero divisor found - your minpoly is not irreducible");
366      return x;
367    }
368    if (p_GetExp(r, 1, nacRing) == 0)
369    {
370      q = p_Mult_q(q, qn, nacRing);
371      q = napNeg(q);
372      q = napAdd(q, qa);
373      nacNormalize(pGetCoeff(r));
374      t = nacInvers(pGetCoeff(r));
375      //nacNormalize(t);
376      napMultN(q, t);
377      p_Normalize(q, nacRing);
378      n_Delete(&t, nacRing);
379      p_Delete(&x, nacRing);
380      p_Delete(&r, nacRing);
381      if (p_GetExp(q, 1, nacRing) >= p_GetExp(c, 1, nacRing))
382        q = napRemainder(q, c);
383      return q;
384    }
385    y = q;
386    q = p_Mult_q(napCopy(q), qn, nacRing);
387    q = napNeg(q);
388    q = napAdd(q, qa);
389    qa = y;
390  }
391}
392
393/* the degree of a poly, i.e. the
394   maximum of all terms' degrees;
395   keeps p */
396int napMaxDeg(poly p)
397{
398  int  d = 0;
399  while (p != NULL)
400  {
401    d=si_max(d, napDeg(p));
402    pIter(p);
403  }
404  return d;
405}
406
407/* the degree of a poly, i.e. the
408   maximum of all terms' degrees;
409   fills l with the number of terms;
410   keeps p */
411int napMaxDegLen(poly p, int &l)
412{
413  int d = 0;
414  l = 0;
415  while (p != NULL)
416  {
417    d = si_max(d, napDeg(p));
418    pIter(p);
419    l++;
420  }
421  return d;
422}
423
424
425/* writes a poly, i.e. a number in the ground field;
426   if has_denom is TRUE, the output is ready to be
427   followed by a non-trivial denominator;
428   r is assumed to be a polynomial ring over an algebraic
429   or transcendental field extension;
430   keeps all arguments */
431void napWrite(poly p, const BOOLEAN has_denom, const ring r)
432{
433  ring nacring = r->algring;
434  if (p == NULL) StringAppendS("0");
435  else if (p_LmIsConstant(p, nacring))
436  {
437    BOOLEAN kl = FALSE;
438    if (has_denom)
439    {
440      number den = nacring->cf->cfGetDenom(pGetCoeff(p), nacring);
441      kl = !n_IsOne(den, nacring);
442      n_Delete(&den, nacring);
443    }
444    if (kl) StringAppendS("(");
445    n_Write(pGetCoeff(p), nacring);
446    if (kl) StringAppendS(")");
447  }
448  else
449  {
450    StringAppendS("(");
451    loop
452    {
453      BOOLEAN wroteCoeff = FALSE;
454      if ((p_LmIsConstant(p, nacring)) ||
455           ((!n_IsOne(pGetCoeff(p), nacring)) &&
456            (!n_IsMOne(pGetCoeff(p),nacring))))
457      {
458        n_Write(pGetCoeff(p), nacring);
459        wroteCoeff = (r->ShortOut == 0);
460      }
461      else if (n_IsMOne(pGetCoeff(p), nacring)) StringAppendS("-");
462      for (int i = 0; i < r->P; i++)
463      {
464        int e = p_GetExp(p, i+1, nacring);
465        if (e > 0)
466        {
467          if (wroteCoeff) StringAppendS("*");
468          else            wroteCoeff=(r->ShortOut==0);
469          StringAppendS(r->parameter[i]);
470          if (e > 1)
471          {
472            if (r->ShortOut == 0) StringAppendS("^");
473            StringAppend("%d", e);
474          }
475        }
476      }
477      pIter(p);
478      if (p == NULL) break;
479      if (n_GreaterZero(pGetCoeff(p),nacring)) StringAppendS("+");
480    }
481    StringAppendS(")");
482  }
483}
484
485/* helper for napRead */
486const char* napHandleMons(const char* s, int i, poly ex)
487{
488  int j;
489  if (strncmp(s, ntParNames[i], strlen(ntParNames[i])) == 0)
490  {
491    s += strlen(ntParNames[i]);
492    if ((*s >= '0') && (*s <= '9'))
493    {
494      s = eati(s, &j);
495      napAddExp(ex, i+1, j);
496    }
497    else
498      napAddExp(ex, i+1, 1);
499  }
500  return s;
501}
502
503/* helper for napRead */
504const char* napHandlePars(const char *s, int i, poly ex)
505{
506  if (strcmp(s, ntParNames[i]) == 0)
507  {
508    s += strlen(ntParNames[i]);
509    napSetExp(ex, i+1, 1);
510  }
511  return s;
512}
513
514/* reads a monomial into the poly b;
515   returns the latter portion of s which
516   comes "after" the monomial that has
517   just been read;
518   modifies b */
519const char* napRead(const char *s, poly *b)
520{
521  poly a;
522  int i;
523  a = (poly)p_Init(nacRing);
524  if ((*s >= '0') && (*s <= '9'))
525  {
526    s = nacRing->cf->nRead(s, &pGetCoeff(a));
527    if (nacIsZero(pGetCoeff(a)))
528    {
529      p_LmDelete(&a, nacRing);
530      *b = NULL;
531      return s;
532    }
533  }
534  else pGetCoeff(a) = nacInit(1,nacRing);
535  i = 0;
536  const char* olds = s;
537  loop
538  {
539    s = napHandlePars(s, i, a);
540    if (olds == s) i++;
541    else if (*s == '\0')
542    {
543      *b = a;
544      return s;
545    }
546    if (i >= ntNumbOfPar) break;
547  }
548  i = 0;
549  loop
550  {
551    olds = s;
552    s = napHandleMons(s, i, a);
553    if (olds == s) i++;
554    else i = 0;
555    if ((*s == '\0') || (i >= ntNumbOfPar)) break;
556  }
557  *b = a;
558  return s;
559}
560
561/* considers the lowest terms la of a and lb of b;
562   returns the minimum of the two exponents of the
563   first variable in la and lb;
564   assumes a != NULL, b != NULL;
565   keeps a and b */
566int napExp(poly a, poly b)
567{
568  assume(a != NULL);
569  assume(b != NULL);
570  while (pNext(a) != NULL) pIter(a);
571  int m = p_GetExp(a, 1, nacRing);
572  if (m == 0) return 0;
573  while (pNext(b) != NULL) pIter(b);
574  int mm = p_GetExp(b, 1, nacRing);
575  if (m > mm) m = mm;
576  return m;
577}
578
579/* returns the smallest i-th exponent in a and b;
580   used to find it in a fraction;
581   keeps a and b */
582int napExpi(int i, poly a, poly b)
583{
584  if (a == NULL || b == NULL) return 0;
585  int m = p_GetExp(a, i+1, nacRing);
586  if (m == 0) return 0;
587  while (pNext(a) != NULL)
588  {
589    pIter(a);
590    if (m > p_GetExp(a, i+1, nacRing))
591    {
592      m = p_GetExp(a, i+1, nacRing);
593      if (m == 0) return 0;
594    }
595  }
596  do
597  {
598    if (m > p_GetExp(b, i+1, nacRing))
599    {
600      m = p_GetExp(b, i+1, nacRing);
601      if (m == 0) return 0;
602    }
603    pIter(b);
604  }
605  while (b != NULL);
606  return m;
607}
608
609/* divides out the content of the given napoly;
610   assumes that ph != NULL;
611   modifies ph */
612void napContent(poly ph)
613{
614  number h, d;
615  poly p;
616
617  assume(ph != NULL);
618  p = ph;
619  if (nacIsOne(pGetCoeff(p))) return;
620  h = nacCopy(pGetCoeff(p));
621  pIter(p);
622  while (p != NULL)
623  {
624    d = nacGcd(pGetCoeff(p), h, nacRing);
625    if (nacIsOne(d))
626    {
627      n_Delete(&h,nacRing);
628      n_Delete(&d,nacRing);
629      return;
630    }
631    n_Delete(&h, nacRing);
632    h = d;
633    pIter(p);
634  }
635  h = nacInvers(d);
636  n_Delete(&d, nacRing);
637  p = ph;
638  while (p != NULL)
639  {
640    d = nacMult(pGetCoeff(p), h);
641    n_Delete(&pGetCoeff(p), nacRing);
642    pGetCoeff(p) = d;
643    pIter(p);
644  }
645  n_Delete(&h, nacRing);
646}
647
648/* removes denominators of coefficients in ph
649   by multiplication with lcm of those;
650   if char != 0, then nothing is done;
651   modifies ph */
652void napCleardenom(poly ph)
653{
654  number d, h;
655  poly p;
656
657  if (!ntIsChar0) return;
658  p = ph;
659  h = nacInit(1,nacRing);
660  while (p!=NULL)
661  {
662    d = nacLcm(h, pGetCoeff(p), nacRing); // uses denominator of pGetCoeff(p)
663    n_Delete(&h,nacRing);
664    h = d;
665    pIter(p);
666  }
667  if(!nacIsOne(h))
668  {
669    p = ph;
670    while (p!=NULL)
671    {
672      d=nacMult(h, pGetCoeff(p));
673      n_Delete(&pGetCoeff(p),nacRing);
674      nacNormalize(d);
675      pGetCoeff(p) = d;
676      pIter(p);
677    }
678  }
679  n_Delete(&h,nacRing);
680  napContent(ph);
681}
682
683/* returns the gcd of all coefficients in a and b;
684   assumes a != NULL, b != NULL;
685   keeps a, keeps b */
686poly napGcd0(poly a, poly b)
687{
688  number x, y;
689  assume(a != NULL);
690  assume(b != NULL);
691  if (!ntIsChar0) return p_ISet(1, nacRing);
692  x = nacCopy(pGetCoeff(a));
693  if (nacIsOne(x)) return napInitz(x);
694  pIter(a);
695  while (a!=NULL)
696  {
697    y = nacGcd(x, pGetCoeff(a), nacRing);
698    n_Delete(&x,nacRing);
699    x = y;
700    if (nacIsOne(x)) return napInitz(x);
701    pIter(a);
702  }
703  do
704  {
705    y = nacGcd(x, pGetCoeff(b), nacRing);
706    n_Delete(&x,nacRing);
707    x = y;
708    if (nacIsOne(x)) return napInitz(x);
709    pIter(b);
710  }
711  while (b!=NULL);
712  return napInitz(x);
713}
714
715/* returns the gcd of a and b;
716   if char != 0, then the constant poly 1 is returned;
717   if a = b = 0, then the constant poly 1 is returned;
718   if a = 0 != b, then b is returned;
719   if a != 0 = b, then a is returned;
720   keeps a, keeps b */
721poly napGcd(poly a, poly b)
722{
723  int i;
724  poly g, x, y, h;
725  if ((a==NULL)
726  || ((pNext(a)==NULL)&&(nacIsZero(pGetCoeff(a)))))
727  {
728    if ((b==NULL)
729    || ((pNext(b)==NULL)&&(nacIsZero(pGetCoeff(b)))))
730    {
731      return p_ISet(1,nacRing);
732    }
733    return napCopy(b);
734  }
735  else
736  if ((b==NULL)
737  || ((pNext(b)==NULL)&&(nacIsZero(pGetCoeff(b)))))
738    return napCopy(a);
739 
740  if (naMinimalPoly != NULL)
741  { // we have an algebraic extension
742    if (p_GetExp(a,1,nacRing) >= p_GetExp(b,1,nacRing))
743    {
744      x = a;
745      y = b;
746    }
747    else
748    {
749      x = b;
750      y = a;
751    }
752    if (!ntIsChar0) g = p_ISet(1,nacRing);
753    else            g = napGcd0(x, y);
754    if (pNext(y)==NULL)
755    {
756      napSetExp(g,1, napExp(x, y));
757      p_Setm(g,nacRing);
758      return g;
759    }
760    x = napCopy(x);
761    y = napCopy(y);
762    loop
763    {
764      h = napRemainder(x, y);
765      if (h==NULL)
766      {
767        napCleardenom(y);
768        if (!nacIsOne(pGetCoeff(g)))
769          napMultN(y, pGetCoeff(g));
770        p_LmDelete(&g,nacRing);
771        return y;
772      }
773      else if (pNext(h)==NULL)
774        break;
775      x = y;
776      y = h;
777    }
778    p_Delete(&y,nacRing);
779    p_LmDelete(&h,nacRing);
780    napSetExp(g,1, napExp(a, b));
781    p_Setm(g,nacRing);
782    return g;
783  }
784  else
785  { // we have ntNumbOfPar transcendental variables
786    if (!ntIsChar0) x = p_ISet(1,nacRing);
787    else            x = napGcd0(a,b);
788    for (i=(ntNumbOfPar-1); i>=0; i--)
789    {
790      napSetExp(x,i+1, napExpi(i,a,b));
791      p_Setm(x,nacRing);
792    }
793    return x;
794  }
795}
796
797/* returns the lcm of all denominators in the coefficients of a;
798   if char != 0, then the constant poly 1 is returned;
799   if a = 0, then the constant poly 1 is returned;
800   keeps a */
801number napLcm(poly a)
802{
803  number h = nacInit(1,nacRing);
804  if (ntIsChar0)
805  {
806    number d;
807    poly b = a;
808
809    while (b!=NULL)
810    {
811      d = nacLcm(h, pGetCoeff(b), nacRing); // uses denominator of pGetCoeff(b)
812      n_Delete(&h,nacRing);
813      h = d;
814      pIter(b);
815    }
816  }
817  return h;
818}
819
820/*2
821* meins  (for reduction in algebraic extension)
822* checks if head of p divides head of q
823* doesn't delete p and q
824*/
825BOOLEAN napDivPoly (poly p, poly q)
826{
827  int j=1;   /* evtl. von naNumber.. -1 abwaerts zaehlen */
828
829  while (p_GetExp(p,j,nacRing) <= p_GetExp(q,j,nacRing))
830  {
831    j++;
832    if (j > ntNumbOfPar)
833      return 1;
834  }
835  return 0;
836}
837
838
839/*
840 * only used for reduction in algebraic extensions when naI != NULL;
841 * reduces the tail of poly q which is required to be != NULL;
842 * modifies q and returns it
843 */
844poly napRedp (poly q)
845{
846  poly h = (poly)p_Init(nacRing);
847  int i=0,j;
848
849  loop
850  {
851    if (napDivPoly (naI->liste[i], q))
852    {
853      /* h = lt(q)/lt(naI->liste[i])*/
854      pGetCoeff(h) = nacCopy(pGetCoeff(q));
855      for (j=ntNumbOfPar; j>0; j--)
856        napSetExp(h,j, p_GetExp(q,j,nacRing) - p_GetExp(naI->liste[i],
857                                                        j,nacRing));
858      p_Setm(h,nacRing);
859      h = p_Mult_q(h, napCopy(naI->liste[i]),nacRing);
860      h = napNeg (h);
861      q = napAdd (q, napCopy(h));
862      p_Delete (&pNext(h),nacRing);
863      if (q == NULL)
864      {
865        p_Delete(&h,nacRing);
866        return q;
867      }
868      /* try to reduce further */
869      i = 0;
870    }
871    else
872    {
873      i++;
874      if (i >= naI->anz)
875      {
876        p_Delete(&h,nacRing);
877        return q;
878      }
879    }
880  }
881}
882
883
884/*
885 * only used for reduction in algebraic extensions when naI != NULL;
886 * reduces the tail of poly q which is required to be != NULL;
887 * modifies q and returns it
888 */
889poly napTailred (poly q)
890{
891  poly h;
892
893  h = pNext(q);
894  while (h != NULL)
895  {
896     h = napRedp (h);
897     if (h == NULL)
898        return q;
899     pIter(h);
900  }
901  return q;
902}
903
904poly napMap(poly p)
905{
906  poly w, a;
907
908  if (p==NULL) return NULL;
909  a = w = (poly)p_Init(nacRing);
910  int i;
911  for(i=1;i<=ntParsToCopy;i++)
912    napSetExp(a,i,napGetExpFrom(p,i,ntMapRing));
913  p_Setm(a,nacRing);
914  pGetCoeff(w) = nacMap(pGetCoeff(p));
915  loop
916  {
917    pIter(p);
918    if (p==NULL) break;
919    pNext(a) = (poly)p_Init(nacRing);
920    pIter(a);
921    for(i=1;i<=ntParsToCopy;i++)
922      napSetExp(a,i,napGetExpFrom(p,i,ntMapRing));
923    p_Setm(a,nacRing);
924    pGetCoeff(a) = nacMap(pGetCoeff(p));
925  }
926  pNext(a) = NULL;
927  return w;
928}
929
930poly napPerm(poly p,const int *par_perm,const ring src_ring,const nMapFunc nMap)
931{
932  poly w;
933
934  if (p==NULL) return NULL;
935  w = (poly)p_Init(nacRing);
936  int i;
937  BOOLEAN not_null=TRUE;
938  loop
939  {
940    for(i=1;i<=rPar(src_ring);i++)
941    {
942      int e;
943      if (par_perm!=NULL) e=par_perm[i-1];
944      else                e=-i;
945      int ee=napGetExpFrom(p,i,src_ring);
946      if (e<0)
947        napSetExp(w,-e,ee);
948      else if (ee>0)
949        not_null=FALSE;
950    }
951    pGetCoeff(w) = nMap(pGetCoeff(p));
952    p_Setm(w,nacRing);
953    pIter(p);
954    if (!not_null)
955    {
956      if (p==NULL)
957      {
958        p_Delete(&w,nacRing);
959        return NULL;
960      }
961      /* else continue*/
962      n_Delete(&(pGetCoeff(w)),nacRing);
963    }
964    else
965    {
966      if (p==NULL) return w;
967      else
968      {
969        pNext(w)=napPerm(p,par_perm,src_ring,nMap);
970        return w;
971      }
972    }
973  }
974}
975
976/*2
977* convert a poly number into a poly
978*/
979poly napPermNumber(number z, int * par_perm, int P, ring oldRing)
980{
981  if (z==NULL) return NULL;
982  poly res=NULL;
983  poly p;
984  poly za=((lnumber)z)->z;
985  poly zb=((lnumber)z)->n;
986  nMapFunc nMap=naSetMap(oldRing,currRing); /* todo: check naSetMap
987                                                     vs. ntSetMap */
988  if (currRing->parameter!=NULL)
989    nMap=currRing->algring->cf->cfSetMap(oldRing->algring, nacRing);
990  else
991    nMap=currRing->cf->cfSetMap(oldRing->algring, currRing);
992  if (nMap==NULL) return NULL; /* emergency exit only */
993  while(za!=NULL)
994  {
995    p = pInit();
996    pNext(p)=NULL;
997    //nNew(&pGetCoeff(p));
998    int i;
999    //for(i=pVariables;i;i--) pSetExp(p,i, 0); // done by pInit
1000    //if (rRing_has_Comp(currRing)) pSetComp(p, 0); // done by pInit
1001    poly pa=NULL;
1002    lnumber pan;
1003    if (currRing->parameter!=NULL)
1004    {
1005      assume(oldRing->algring!=NULL);
1006      pGetCoeff(p)=(number)ALLOC0_LNUMBER();
1007      pan=(lnumber)pGetCoeff(p);
1008      pan->s=2;
1009      pan->z=napInitz(nMap(pGetCoeff(za)));
1010      pa=pan->z;
1011    }
1012    else
1013    {
1014      pGetCoeff(p)=nMap(pGetCoeff(za));
1015    }
1016    for(i=0;i<P;i++)
1017    {
1018      if(napGetExpFrom(za,i+1,oldRing)!=0)
1019      {
1020        if(par_perm==NULL)
1021        {
1022          if ((rPar(currRing)>=i) && (pa!=NULL))
1023          {
1024            napSetExp(pa,i+1,napGetExpFrom(za,i+1,oldRing));
1025            p_Setm(pa,nacRing);
1026          }
1027          else
1028          {
1029            pDelete(&p);
1030            break;
1031          }
1032        }
1033        else if(par_perm[i]>0)
1034          pSetExp(p,par_perm[i],napGetExpFrom(za,i+1,oldRing));
1035        else if((par_perm[i]<0)&&(pa!=NULL))
1036        {
1037          napSetExp(pa,-par_perm[i], napGetExpFrom(za,i+1,oldRing));
1038          p_Setm(pa,nacRing);
1039        }
1040        else
1041        {
1042          pDelete(&p);
1043          break;
1044        }
1045      }
1046    }
1047    if (p!=NULL)
1048    {
1049      pSetm(p);
1050      if (zb!=NULL)
1051      {
1052        if  (currRing->P>0)
1053        {
1054          pan->n=napPerm(zb,par_perm,oldRing,nMap);
1055          if(pan->n==NULL) /* error in mapping or mapping to variable */
1056            pDelete(&p);
1057        }
1058        else
1059          pDelete(&p);
1060      }
1061      nNormalize(pGetCoeff(p));
1062      if (nIsZero(pGetCoeff(p)))
1063        pDelete(&p);
1064      else
1065      {
1066        pTest(p);
1067        res=pAdd(res,p);
1068      }
1069    }
1070    pIter(za);
1071  }
1072  pTest(res);
1073  return res;
1074}
1075
1076number   napGetDenom(number &n, const ring r)
1077{
1078  lnumber x=(lnumber)n;
1079  if (x->n!=NULL)
1080  {
1081    lnumber rr=ALLOC0_LNUMBER();
1082    rr->z=p_Copy(x->n,r->algring);
1083    rr->s = 2;
1084    return (number)rr;
1085  }
1086  return n_Init(1,r);
1087}
1088
1089number   napGetNumerator(number &n, const ring r)
1090{
1091  lnumber x=(lnumber)n;
1092  lnumber rr=ALLOC0_LNUMBER();
1093  rr->z=p_Copy(x->z,r->algring);
1094  rr->s = 2;
1095  return (number)rr;
1096}
1097
1098/*================ procedure for rational functions: ntXXXX =================*/
1099
1100/*2
1101*  z:= i
1102*/
1103number ntInit(int i, const ring r)
1104{
1105  if (i!=0)
1106  {
1107    number c=n_Init(i,r->algring);
1108    if (!n_IsZero(c,r->algring))
1109    {
1110      poly z=p_Init(r->algring);
1111      pSetCoeff0(z,c);
1112      lnumber l = (lnumber)ALLOC_LNUMBER();
1113      l->z = z;
1114      l->s = 2;
1115      l->n = NULL;
1116      return (number)l;
1117    }
1118  }
1119  /*else*/
1120  return NULL;
1121}
1122
1123/*3
1124*  division with remainder: f = g*q + r,
1125*  returns r and destroys f
1126*/
1127poly ntRemainder(poly f, const poly g)
1128{
1129  poly a, h, qq;
1130
1131  qq = (poly)p_Init(nacRing);
1132  pNext(qq) = NULL;
1133  p_Normalize(g, nacRing);
1134  p_Normalize(f, nacRing);
1135  a = f;
1136  do
1137  {
1138    napSetExp(qq,1, p_GetExp(a,1,nacRing) - p_GetExp(g,1,nacRing));
1139    napSetm(qq);
1140    pGetCoeff(qq) = nacDiv(pGetCoeff(a), pGetCoeff(g));
1141    pGetCoeff(qq) = nacNeg(pGetCoeff(qq));
1142    nacNormalize(pGetCoeff(qq));
1143    h = napCopy(g);
1144    napMultT(h, qq);
1145    p_Normalize(h,nacRing);
1146    n_Delete(&pGetCoeff(qq),nacRing);
1147    a = napAdd(a, h);
1148  }
1149  while ((a!=NULL) && (p_GetExp(a,1,nacRing) >= p_GetExp(g,1,nacRing)));
1150  omFreeBinAddr(qq);
1151  return a;
1152}
1153
1154number  ntPar(int i)
1155{
1156  lnumber l = ALLOC_LNUMBER();
1157  l->s = 2;
1158  l->z = p_ISet(1,nacRing);
1159  napSetExp(l->z,i,1);
1160  p_Setm(l->z,nacRing);
1161  l->n = NULL;
1162  return (number)l;
1163}
1164
1165int     ntParDeg(number n)     /* i := deg(n) */
1166{
1167  lnumber l = (lnumber)n;
1168  if (l==NULL) return -1;
1169  return napDeg(l->z);
1170}
1171
1172//int     ntParDeg(number n)     /* i := deg(n) */
1173//{
1174//  lnumber l = (lnumber)n;
1175//  if (l==NULL) return -1;
1176//  return napMaxDeg(l->z)+napMaxDeg(l->n);
1177//}
1178
1179int     ntSize(number n)     /* size desc. */
1180{
1181  lnumber l = (lnumber)n;
1182  if (l==NULL) return -1;
1183  int len_z;
1184  int len_n;
1185  int o=napMaxDegLen(l->z,len_z)+napMaxDegLen(l->n,len_n);
1186  return (len_z+len_n)+o;
1187}
1188
1189/*2
1190* convert a number to int (if possible)
1191*/
1192int ntInt(number &n, const ring r)
1193{
1194  lnumber l=(lnumber)n;
1195  if ((l!=NULL)&&(l->n==NULL)&&(p_IsConstant(l->z,r->algring)))
1196  {
1197    return nacInt(pGetCoeff(l->z),r->algring);
1198  }
1199  return 0;
1200}
1201
1202/*2
1203*  deletes p
1204*/
1205void ntDelete(number *p, const ring r)
1206{
1207  if ((*p)!=NULL)
1208  {
1209    lnumber l = (lnumber) * p;
1210    if (l==NULL) return;
1211    p_Delete(&(l->z),r->algring);
1212    p_Delete(&(l->n),r->algring);
1213    FREE_LNUMBER(l);
1214  }
1215  *p = NULL;
1216}
1217
1218/*2
1219* copy p to erg
1220*/
1221number ntCopy(number p)
1222{
1223  if (p==NULL) return NULL;
1224  ntTest(p);
1225  lnumber erg;
1226  lnumber src = (lnumber)p;
1227  erg = ALLOC_LNUMBER();
1228  erg->z = p_Copy(src->z, nacRing);
1229  erg->n = p_Copy(src->n, nacRing);
1230  erg->s = src->s;
1231  return (number)erg;
1232}
1233number nt_Copy(number p, const ring r)
1234{
1235  if (p==NULL) return NULL;
1236  lnumber erg;
1237  lnumber src = (lnumber)p;
1238  erg = ALLOC_LNUMBER();
1239  erg->z = p_Copy(src->z,r->algring);
1240  erg->n = p_Copy(src->n,r->algring);
1241  erg->s = src->s;
1242  return (number)erg;
1243}
1244
1245/*2
1246*  addition; lu:= la + lb
1247*/
1248number ntAdd(number la, number lb)
1249{
1250  if (la==NULL) return ntCopy(lb);
1251  if (lb==NULL) return ntCopy(la);
1252
1253  poly x, y;
1254  lnumber lu;
1255  lnumber a = (lnumber)la;
1256  lnumber b = (lnumber)lb;
1257  #ifdef LDEBUG
1258  omCheckAddrSize(a,sizeof(slnumber));
1259  omCheckAddrSize(b,sizeof(slnumber));
1260  #endif
1261  if (b->n!=NULL) x = pp_Mult_qq(a->z, b->n,nacRing);
1262  else            x = napCopy(a->z);
1263  if (a->n!=NULL) y = pp_Mult_qq(b->z, a->n,nacRing);
1264  else            y = napCopy(b->z);
1265  poly res = napAdd(x, y);
1266  if (res==NULL)
1267  {
1268    return (number)NULL;
1269  }
1270  lu = ALLOC_LNUMBER();
1271  lu->z=res;
1272  if (a->n!=NULL)
1273  {
1274    if (b->n!=NULL) x = pp_Mult_qq(a->n, b->n,nacRing);
1275    else            x = napCopy(a->n);
1276  }
1277  else
1278  {
1279    if (b->n!=NULL) x = napCopy(b->n);
1280    else            x = NULL;
1281  }
1282  //if (x!=NULL)
1283  //{
1284  //  if (p_LmIsConstant(x,nacRing))
1285  //  {
1286  //    number inv=nacInvers(pGetCoeff(x));
1287  //    napMultN(lu->z,inv);
1288  //    n_Delete(&inv,nacRing);
1289  //    napDelete(&x);
1290  //  }
1291  //}
1292  lu->n = x;
1293  lu->s = FALSE;
1294  if (/*lu->n*/ x!=NULL)
1295  {
1296     number luu=(number)lu;
1297     //if (p_IsConstant(lu->n,nacRing)) ntCoefNormalize(luu);
1298     //else
1299                ntNormalize(luu);
1300     lu=(lnumber)luu;
1301  }
1302  //else lu->s=2;
1303  ntTest((number)lu);
1304  return (number)lu;
1305}
1306
1307/*2
1308*  subtraction; r:= la - lb
1309*/
1310number ntSub(number la, number lb)
1311{
1312  lnumber lu;
1313
1314  if (lb==NULL) return ntCopy(la);
1315  if (la==NULL)
1316  {
1317    lu = (lnumber)ntCopy(lb);
1318    lu->z = napNeg(lu->z);
1319    return (number)lu;
1320  }
1321
1322  lnumber a = (lnumber)la;
1323  lnumber b = (lnumber)lb;
1324
1325  #ifdef LDEBUG
1326  omCheckAddrSize(a,sizeof(slnumber));
1327  omCheckAddrSize(b,sizeof(slnumber));
1328  #endif
1329
1330  poly x, y;
1331  if (b->n!=NULL) x = pp_Mult_qq(a->z, b->n,nacRing);
1332  else            x = napCopy(a->z);
1333  if (a->n!=NULL) y = p_Mult_q(napCopy(b->z), napCopyNeg(a->n),nacRing);
1334  else            y = napCopyNeg(b->z);
1335  poly res = napAdd(x, y);
1336  if (res==NULL)
1337  {
1338    return (number)NULL;
1339  }
1340  lu = ALLOC_LNUMBER();
1341  lu->z=res;
1342  if (a->n!=NULL)
1343  {
1344    if (b->n!=NULL) x = pp_Mult_qq(a->n, b->n,nacRing);
1345    else            x = napCopy(a->n);
1346  }
1347  else
1348  {
1349    if (b->n!=NULL) x = napCopy(b->n);
1350    else            x = NULL;
1351  }
1352  lu->n = x;
1353  lu->s = FALSE;
1354  if (/*lu->n*/ x!=NULL)
1355  {
1356     number luu=(number)lu;
1357     //if (p_IsConstant(lu->n,nacRing)) ntCoefNormalize(luu);
1358     //else
1359                         ntNormalize(luu);
1360     lu=(lnumber)luu;
1361  }
1362  //else lu->s=2;
1363  ntTest((number)lu);
1364  return (number)lu;
1365}
1366
1367/*2
1368*  multiplication; r:= la * lb
1369*/
1370number ntMult(number la, number lb)
1371{
1372  if ((la==NULL) || (lb==NULL))
1373    return NULL;
1374
1375  lnumber a = (lnumber)la;
1376  lnumber b = (lnumber)lb;
1377  lnumber lo;
1378  poly x;
1379
1380  #ifdef LDEBUG
1381  omCheckAddrSize(a,sizeof(slnumber));
1382  omCheckAddrSize(b,sizeof(slnumber));
1383  #endif
1384  ntTest(la);
1385  ntTest(lb);
1386
1387  lo = ALLOC_LNUMBER();
1388  lo->z = pp_Mult_qq(a->z, b->z,nacRing);
1389
1390  if (a->n==NULL)
1391  {
1392    if (b->n==NULL)
1393      x = NULL;
1394    else
1395      x = napCopy(b->n);
1396  }
1397  else
1398  {
1399    if (b->n==NULL)
1400    {
1401      x = napCopy(a->n);
1402    }
1403    else
1404    {
1405      x = pp_Mult_qq(b->n, a->n, nacRing);
1406    }
1407  }
1408  if ((x!=NULL) && (p_LmIsConstant(x,nacRing)) && nacIsOne(pGetCoeff(x)))
1409    p_Delete(&x,nacRing);
1410  lo->n = x;
1411  lo->s = 0;
1412  number luu=(number)lo;
1413  if(lo->z==NULL)
1414  {
1415    FREE_LNUMBER(lo);
1416    lo=NULL;
1417  }
1418  else if (lo->n!=NULL)
1419  {
1420    // if (p_IsConstant(lo->n,nacRing)) ntCoefNormalize(luu);
1421    // else
1422                      ntNormalize(luu);
1423    lo=(lnumber)luu;
1424  }
1425  luu=(number)lo;
1426  if ((lo!=NULL) 
1427  && (naMinimalPoly!=NULL)
1428  &&(p_GetExp(lo->z,1,nacRing)>=p_GetExp(naMinimalPoly,1,nacRing)))
1429    lo->z=napRemainder(lo->z,naMinimalPoly);
1430  //if (naMinimalPoly==NULL) lo->s=2;
1431  ntTest((number)lo);
1432  return (number)lo;
1433}
1434
1435number ntIntDiv(number la, number lb)
1436{
1437  ntTest(la);
1438  ntTest(lb);
1439  lnumber res;
1440  lnumber a = (lnumber)la;
1441  lnumber b = (lnumber)lb;
1442  if (a==NULL)
1443  {
1444    return NULL;
1445  }
1446  if (b==NULL)
1447  {
1448    WerrorS(nDivBy0);
1449    return NULL;
1450  }
1451#ifdef LDEBUG
1452  omCheckAddrSize(a,sizeof(slnumber));
1453  omCheckAddrSize(b,sizeof(slnumber));
1454#endif
1455  assume(a->z!=NULL && b->z!=NULL);
1456  assume(a->n==NULL && b->n==NULL);
1457  res = ALLOC_LNUMBER();
1458  res->z = napCopy(a->z);
1459  res->n = napCopy(b->z);
1460  res->s = 0;
1461  number nres=(number)res;
1462  ntNormalize(nres);
1463
1464  //napDelete(&res->n);
1465  ntTest(nres);
1466  return nres;
1467}
1468
1469/*2
1470*  division; lo:= la / lb
1471*/
1472number ntDiv(number la, number lb)
1473{
1474  lnumber lo;
1475  lnumber a = (lnumber)la;
1476  lnumber b = (lnumber)lb;
1477  poly x;
1478
1479  if (a==NULL)
1480    return NULL;
1481
1482  if (b==NULL)
1483  {
1484    WerrorS(nDivBy0);
1485    return NULL;
1486  }
1487  #ifdef LDEBUG
1488  omCheckAddrSize(a,sizeof(slnumber));
1489  omCheckAddrSize(b,sizeof(slnumber));
1490  #endif
1491  lo = ALLOC_LNUMBER();
1492  if (b->n!=NULL)
1493    lo->z = pp_Mult_qq(a->z, b->n,nacRing);
1494  else
1495    lo->z = napCopy(a->z);
1496  if (a->n!=NULL)
1497    x = pp_Mult_qq(b->z, a->n, nacRing);
1498  else
1499    x = napCopy(b->z);
1500  if ((p_LmIsConstant(x,nacRing)) && nacIsOne(pGetCoeff(x)))
1501    p_Delete(&x,nacRing);
1502  lo->n = x;
1503  lo->s = 0;
1504  if (lo->n!=NULL)
1505  {
1506    number luu=(number)lo;
1507     //if (p_IsConstant(lo->n,nacRing)) ntCoefNormalize(luu);
1508     //else
1509                         ntNormalize(luu);
1510    lo=(lnumber)luu;
1511  }
1512  //else lo->s=2;
1513  ntTest((number)lo);
1514  return (number)lo;
1515}
1516
1517/*2
1518*  za:= - za, inplace
1519*/
1520number ntNeg(number za)
1521{
1522  if (za!=NULL)
1523  {
1524    lnumber e = (lnumber)za;
1525    ntTest(za);
1526    e->z = napNeg(e->z);
1527  }
1528  return za;
1529}
1530
1531/*2
1532* 1/a
1533*/
1534number ntInvers(number a)
1535{
1536  lnumber lo;
1537  lnumber b = (lnumber)a;
1538  poly x;
1539
1540  if (b==NULL)
1541  {
1542    WerrorS(nDivBy0);
1543    return NULL;
1544  }
1545  #ifdef LDEBUG
1546  omCheckAddrSize(b,sizeof(slnumber));
1547  #endif
1548  lo = ALLOC0_LNUMBER();
1549  lo->s = b->s;
1550  if (b->n!=NULL)
1551    lo->z = napCopy(b->n);
1552  else
1553    lo->z = p_ISet(1,nacRing);
1554  x = b->z;
1555  if ((!p_LmIsConstant(x,nacRing)) || !nacIsOne(pGetCoeff(x)))
1556    x = napCopy(x);
1557  else
1558  {
1559    lo->n = NULL;
1560    ntTest((number)lo);
1561    return (number)lo;
1562  }
1563  lo->n = x;
1564  if (lo->n!=NULL)
1565  {
1566     number luu=(number)lo;
1567     //if (p_IsConstant(lo->n,nacRing)) ntCoefNormalize(luu);
1568     //else
1569                           ntNormalize(luu);
1570     lo=(lnumber)luu;
1571  }
1572  ntTest((number)lo);
1573  return (number)lo;
1574}
1575
1576
1577BOOLEAN ntIsZero(number za)
1578{
1579  lnumber zb = (lnumber)za;
1580  ntTest(za);
1581#ifdef LDEBUG
1582  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(2)");
1583#endif
1584  return (zb==NULL);
1585}
1586
1587
1588BOOLEAN ntGreaterZero(number za)
1589{
1590  lnumber zb = (lnumber)za;
1591#ifdef LDEBUG
1592  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(3)");
1593#endif
1594  ntTest(za);
1595  if (zb!=NULL)
1596  {
1597    return (nacGreaterZero(pGetCoeff(zb->z))||(!p_LmIsConstant(zb->z,nacRing)));
1598  }
1599  /* else */ return FALSE;
1600}
1601
1602
1603/*2
1604* a = b ?
1605*/
1606BOOLEAN ntEqual (number a, number b)
1607{
1608  if(a==b) return TRUE;
1609  if((a==NULL)&&(b!=NULL)) return FALSE;
1610  if((b==NULL)&&(a!=NULL)) return FALSE;
1611
1612  lnumber aa=(lnumber)a;
1613  lnumber bb=(lnumber)b;
1614
1615  int an_deg=0;
1616  if(aa->n!=NULL)
1617    an_deg=napDeg(aa->n);
1618  int bn_deg=0;
1619  if(bb->n!=NULL)
1620    bn_deg=napDeg(bb->n);
1621  if(an_deg+napDeg(bb->z)!=bn_deg+napDeg(aa->z))
1622    return FALSE;
1623#if 0
1624  ntNormalize(a);
1625  aa=(lnumber)a;
1626  ntNormalize(b);
1627  bb=(lnumber)b;
1628  if((aa->n==NULL)&&(bb->n!=NULL)) return FALSE;
1629  if((bb->n==NULL)&&(aa->n!=NULL)) return FALSE;
1630  if(napComp(aa->z,bb->z)!=0) return FALSE;
1631  if((aa->n!=NULL) && (napComp(aa->n,bb->n))) return FALSE;
1632#endif
1633  number h = ntSub(a, b);
1634  BOOLEAN bo = ntIsZero(h);
1635  ntDelete(&h,currRing);
1636  return bo;
1637}
1638
1639/* This method will only consider the numerators of a and b.
1640   Moreover it may return TRUE only if one or both numerators
1641   are zero or if their degrees are equal. Then TRUE is returned iff
1642   coeff(numerator(a)) > coeff(numerator(b));
1643   In all other cases, FALSE will be returned. */
1644BOOLEAN ntGreater (number a, number b)
1645{
1646  int az = 0; int ad = 0;
1647  if (ntIsZero(a)) az = 1;
1648  else ad = napDeg(((lnumber)a)->z);
1649  int bz = 0; int bd = 0;
1650  if (ntIsZero(b)) bz = 1;
1651  else bd = napDeg(((lnumber)b)->z);
1652 
1653  if ((az == 1) && (bz == 1)) /* a = b = 0 */ return FALSE;
1654  if (az == 1) /* a = 0, b != 0 */
1655  {
1656    return (!nacGreaterZero(pGetCoeff(((lnumber)b)->z)));
1657  }
1658  if (bz == 1) /* a != 0, b = 0 */
1659  {
1660    return (nacGreaterZero(pGetCoeff(((lnumber)a)->z)));
1661  }
1662  if (ad == bd) 
1663    return nacGreater(pGetCoeff(((lnumber)a)->z),
1664                      pGetCoeff(((lnumber)b)->z));
1665  return FALSE;
1666}
1667
1668/*2
1669* reads a number
1670*/
1671const char  *ntRead(const char *s, number *p)
1672{
1673  poly x;
1674  lnumber a;
1675  s = napRead(s, &x);
1676  if (x==NULL)
1677  {
1678    *p = NULL;
1679    return s;
1680  }
1681  *p = (number)ALLOC0_LNUMBER();
1682  a = (lnumber)*p;
1683  a->z = x;
1684  if(a->z==NULL)
1685  {
1686    FREE_LNUMBER(a);
1687    *p=NULL;
1688  }
1689  else
1690  {
1691    a->n = NULL;
1692    a->s = 0;
1693    ntTest(*p);
1694  }
1695  return s;
1696}
1697
1698/*2
1699* tries to convert a number to a name
1700*/
1701char * ntName(number n)
1702{
1703  lnumber ph = (lnumber)n;
1704  if (ph==NULL)
1705    return NULL;
1706  int i;
1707  char *s=(char *)omAlloc(4* ntNumbOfPar);
1708  char *t=(char *)omAlloc(8);
1709  s[0]='\0';
1710  for (i = 0; i <= ntNumbOfPar - 1; i++)
1711  {
1712    int e=p_GetExp(ph->z,i+1,nacRing);
1713    if (e > 0)
1714    {
1715      if (e >1)
1716      {
1717        sprintf(t,"%s%d",ntParNames[i],e);
1718        strcat(s,t);
1719      }
1720      else
1721      {
1722        strcat(s,ntParNames[i]);
1723      }
1724    }
1725  }
1726  omFreeSize((ADDRESS)t,8);
1727  if (s[0]=='\0')
1728  {
1729    omFree((ADDRESS)s);
1730    return NULL;
1731  }
1732  return s;
1733}
1734
1735/*2
1736*  writes a number
1737*/
1738void ntWrite(number &phn, const ring r)
1739{
1740  lnumber ph = (lnumber)phn;
1741  if (ph==NULL)
1742    StringAppendS("0");
1743  else
1744  {
1745    phn->s = 0;
1746    BOOLEAN has_denom=(ph->n!=NULL);
1747    napWrite(ph->z,has_denom/*(ph->n!=NULL)*/,r);
1748    if (has_denom/*(ph->n!=NULL)*/)
1749    {
1750      StringAppendS("/");
1751      napWrite(ph->n,TRUE,r);
1752    }
1753  }
1754}
1755
1756/*2
1757* za == 1 ?
1758*/
1759BOOLEAN ntIsOne(number za)
1760{
1761  lnumber a = (lnumber)za;
1762  if (a==NULL) return FALSE;
1763#ifdef LDEBUG
1764  omCheckAddrSize(a,sizeof(slnumber));
1765  if (a->z==NULL)
1766  {
1767    WerrorS("internal zero error(4)");
1768    return FALSE;
1769  }
1770#endif
1771  if (a->n==NULL)
1772  {
1773    if (p_LmIsConstant(a->z,nacRing))
1774    {
1775      return nacIsOne(pGetCoeff(a->z));
1776    }
1777    else                 return FALSE;
1778  }
1779#if 0
1780  number t;
1781  x = a->z;
1782  y = a->n;
1783  do
1784  {
1785    if (napComp(x, y))
1786      return FALSE;
1787    else
1788    {
1789      t = nacSub(pGetCoeff(x), pGetCoeff(y));
1790      if (!nacIsZero(t))
1791      {
1792        n_Delete(&t,nacRing);
1793        return FALSE;
1794      }
1795      else
1796        n_Delete(&t,nacRing);
1797    }
1798    pIter(x);
1799    pIter(y);
1800  }
1801  while ((x!=NULL) && (y!=NULL));
1802  if ((x!=NULL) || (y!=NULL)) return FALSE;
1803  p_Delete(&a->z,nacRing);
1804  p_Delete(&a->n,nacRing);
1805  a->z = p_ISet(1,nacRing);
1806  a->n = NULL;
1807  return TRUE;
1808#else
1809  return FALSE;
1810#endif
1811}
1812
1813/*2
1814* za == -1 ?
1815*/
1816BOOLEAN ntIsMOne(number za)
1817{
1818  lnumber a = (lnumber)za;
1819  if (a==NULL) return FALSE;
1820#ifdef LDEBUG
1821  omCheckAddrSize(a,sizeof(slnumber));
1822  if (a->z==NULL)
1823  {
1824    WerrorS("internal zero error(5)");
1825    return FALSE;
1826  }
1827#endif
1828  if (a->n==NULL)
1829  {
1830    if (p_LmIsConstant(a->z,nacRing)) return n_IsMOne(pGetCoeff(a->z),nacRing);
1831    /*else                   return FALSE;*/
1832  }
1833  return FALSE;
1834}
1835
1836/*2
1837* returns the i-th power of p (i>=0)
1838*/
1839void ntPower(number p, int i, number *rc)
1840{
1841  number x;
1842  *rc = ntInit(1,currRing);
1843  for (; i > 0; i--)
1844  {
1845    x = ntMult(*rc, p);
1846    ntDelete(rc,currRing);
1847    *rc = x;
1848  }
1849}
1850
1851/*2
1852* result =gcd(a,b)
1853*/
1854number ntGcd(number a, number b, const ring r)
1855{
1856  if (a==NULL)  return ntCopy(b);
1857  if (b==NULL)  return ntCopy(a);
1858
1859  lnumber x, y;
1860  lnumber result = ALLOC0_LNUMBER();
1861
1862  x = (lnumber)a;
1863  y = (lnumber)b;
1864#ifndef HAVE_FACTORY
1865  result->z = napGcd(x->z, y->z); // change from napGcd0
1866#else
1867  int c=ABS(nGetChar());
1868  if (c==1) c=0;
1869  setCharacteristic( c );
1870
1871  poly rz=napGcd(x->z, y->z);
1872  CanonicalForm F, G, R;
1873  R=convSingPFactoryP(rz,r->algring);
1874  p_Normalize(x->z,nacRing);
1875  F=convSingPFactoryP(x->z,r->algring)/R;
1876  p_Normalize(y->z,nacRing);
1877  G=convSingPFactoryP(y->z,r->algring)/R;
1878  F = gcd( F, G );
1879  if (F.isOne())
1880    result->z= rz;
1881  else
1882  {
1883    p_Delete(&rz,r->algring);
1884    result->z=convFactoryPSingP( F*R,r->algring );
1885    p_Normalize(result->z,nacRing);
1886  }
1887#endif
1888  ntTest((number)result);
1889  return (number)result;
1890}
1891
1892
1893/*2
1894* ntNumbOfPar = 1:
1895* clears denominator         algebraic case;
1896* tries to simplify ratio    transcendental case;
1897*
1898* cancels monomials
1899* occuring in denominator
1900* and enumerator  ?          ntNumbOfPar != 1;
1901*
1902* #defines for Factory:
1903* FACTORY_GCD_TEST: do not apply built in gcd for
1904*   univariate polynomials, always use Factory
1905*/
1906//#define FACTORY_GCD_TEST
1907void ntCoefNormalize(number pp)
1908{
1909  if (pp==NULL) return;
1910  lnumber p = (lnumber)pp;
1911  number nz; // all denom. of the numerator
1912  nz=p_GetAllDenom(p->z,nacRing);
1913  BOOLEAN norm=FALSE;
1914  if (!n_IsOne(nz,nacRing))
1915  {
1916    norm=TRUE;
1917    p->z=p_Mult_nn(p->z,nz,nacRing);
1918    if (p->n==NULL)
1919    {
1920      p->n=p_NSet(nz,nacRing);
1921    }
1922    else
1923    {
1924      p->n=p_Mult_nn(p->n,nz,nacRing);
1925      n_Delete(&nz, nacRing);
1926    }
1927  }
1928  else
1929  {
1930    n_Delete(&nz, nacRing);
1931  }
1932  if (norm)
1933  {
1934    norm=FALSE;
1935    p_Normalize(p->z,nacRing);
1936    p_Normalize(p->n,nacRing);
1937  }
1938  number nn;
1939  nn=p_GetAllDenom(p->n,nacRing);
1940  if (!n_IsOne(nn,nacRing))
1941  {
1942    norm=TRUE;
1943    p->n=p_Mult_nn(p->n,nn,nacRing);
1944    p->z=p_Mult_nn(p->z,nn,nacRing);
1945    n_Delete(&nn, nacRing);
1946  }
1947  else
1948  {
1949    n_Delete(&nn, nacRing);
1950  }
1951  if (norm)
1952  {
1953    p_Normalize(p->z,nacRing);
1954    p_Normalize(p->n,nacRing);
1955  }
1956  // remove common factors in n, z:
1957  if (p->n!=NULL)
1958  {
1959    poly pp=p->z;
1960    nz=n_Copy(pGetCoeff(pp),nacRing);
1961    pIter(pp);
1962    while(pp!=NULL)
1963    {
1964      if (n_IsOne(nz,nacRing)) break;
1965      number d=n_Gcd(nz,pGetCoeff(pp),nacRing);
1966      n_Delete(&nz,nacRing); nz=d;
1967      pIter(pp);
1968    }
1969    if (!n_IsOne(nz,nacRing))
1970    {
1971      pp=p->n;
1972      nn=n_Copy(pGetCoeff(pp),nacRing);
1973      pIter(pp);
1974      while(pp!=NULL)
1975      {
1976        if (n_IsOne(nn,nacRing)) break;
1977        number d=n_Gcd(nn,pGetCoeff(pp),nacRing);
1978        n_Delete(&nn,nacRing); nn=d;
1979        pIter(pp);
1980      }
1981      number ng=n_Gcd(nz,nn,nacRing);
1982      n_Delete(&nn,nacRing);
1983      if (!n_IsOne(ng,nacRing))
1984      {
1985        number ni=n_Invers(ng,nacRing);
1986        p->z=p_Mult_nn(p->z,ni,nacRing);
1987        p->n=p_Mult_nn(p->n,ni,nacRing);
1988        p_Normalize(p->z,nacRing);
1989        p_Normalize(p->n,nacRing);
1990        n_Delete(&ni,nacRing);
1991      }
1992      n_Delete(&ng,nacRing);
1993    }
1994    n_Delete(&nz,nacRing);
1995  }
1996  if (p->n!=NULL)
1997  {
1998    if(!nacGreaterZero(pGetCoeff(p->n)))
1999    {
2000      p->z=napNeg(p->z);
2001      p->n=napNeg(p->n);
2002    }
2003
2004    if (/*(p->n!=NULL) && */
2005    (p_IsConstant(p->n,nacRing))
2006    && (n_IsOne(pGetCoeff(p->n),nacRing)))
2007    {
2008      p_Delete(&(p->n), nacRing);
2009      p->n = NULL;
2010    }
2011  }
2012}
2013
2014void ntNormalize(number &pp)
2015{
2016
2017  //ntTest(pp); // input may not be "normal"
2018  lnumber p = (lnumber)pp;
2019
2020  if (p==NULL)
2021    return;
2022  ntCoefNormalize(pp);
2023  p->s = 2;
2024  poly x = p->z;
2025  poly y = p->n;
2026
2027  if (y==NULL) return;
2028
2029  if ((x!=NULL) && (y!=NULL))
2030  {
2031    int i;
2032    for (i=ntNumbOfPar-1; i>=0; i--)
2033    {
2034      poly xx=x;
2035      poly yy=y;
2036      int m = napExpi(i, yy, xx);
2037      if (m != 0)          // in this case xx!=NULL!=yy
2038      {
2039        while (xx != NULL)
2040        {
2041          napAddExp(xx,i+1, -m);
2042          pIter(xx);
2043        }
2044        while (yy != NULL)
2045        {
2046          napAddExp(yy,i+1, -m);
2047          pIter(yy);
2048        }
2049      }
2050    }
2051  }
2052  if (p_LmIsConstant(y,nacRing)) /* i.e. => simplify to (1/c)*z / monom */
2053  {
2054    if (nacIsOne(pGetCoeff(y)))
2055    {
2056      p_LmDelete(&y,nacRing);
2057      p->n = NULL;
2058      ntTest(pp);
2059      return;
2060    }
2061    number h1 = nacInvers(pGetCoeff(y));
2062    nacNormalize(h1);
2063    napMultN(x, h1);
2064    n_Delete(&h1,nacRing);
2065    p_LmDelete(&y,nacRing);
2066    p->n = NULL;
2067    ntTest(pp);
2068    return;
2069  }
2070#ifndef FACTORY_GCD_TEST
2071  if (ntNumbOfPar == 1) /* apply built-in gcd */
2072  {
2073    poly x1,y1;
2074    if (p_GetExp(x,1,nacRing) >= p_GetExp(y,1,nacRing))
2075    {
2076      x1 = napCopy(x);
2077      y1 = napCopy(y);
2078    }
2079    else
2080    {
2081      x1 = napCopy(y);
2082      y1 = napCopy(x);
2083    }
2084    poly r;
2085    loop
2086    {
2087      r = ntRemainder(x1, y1);
2088      if ((r==NULL) || (pNext(r)==NULL)) break;
2089      x1 = y1;
2090      y1 = r;
2091    }
2092    if (r!=NULL)
2093    {
2094      p_Delete(&r,nacRing);
2095      p_Delete(&y1,nacRing);
2096    }
2097    else
2098    {
2099      napDivMod(x, y1, &(p->z), &r);
2100      napDivMod(y, y1, &(p->n), &r);
2101      p_Delete(&y1,nacRing);
2102    }
2103    x = p->z;
2104    y = p->n;
2105    /* collect all denoms from y and multiply x and y by it */
2106    if (ntIsChar0)
2107    {
2108      number n=napLcm(y);
2109      napMultN(x,n);
2110      napMultN(y,n);
2111      n_Delete(&n,nacRing);
2112      while(x!=NULL)
2113      {
2114        nacNormalize(pGetCoeff(x));
2115        pIter(x);
2116      }
2117      x = p->z;
2118      while(y!=NULL)
2119      {
2120        nacNormalize(pGetCoeff(y));
2121        pIter(y);
2122      }
2123      y = p->n;
2124    }
2125    if (pNext(y)==NULL)
2126    {
2127      if (nacIsOne(pGetCoeff(y)))
2128      {
2129        if (p_GetExp(y,1,nacRing)==0)
2130        {
2131          p_LmDelete(&y,nacRing);
2132          p->n = NULL;
2133        }
2134        ntTest(pp);
2135        return;
2136      }
2137    }
2138  }
2139#endif /* FACTORY_GCD_TEST */
2140#ifdef HAVE_FACTORY
2141#ifndef FACTORY_GCD_TEST
2142  else
2143#endif
2144  {
2145    poly xx,yy;
2146    singclap_algdividecontent(x,y,xx,yy);
2147    if (xx!=NULL)
2148    {
2149      p->z=xx;
2150      p->n=yy;
2151      p_Delete(&x,nacRing);
2152      p_Delete(&y,nacRing);
2153    }
2154  }
2155#endif
2156  /* remove common factors from z and n */
2157  x=p->z;
2158  y=p->n;
2159  if(!nacGreaterZero(pGetCoeff(y)))
2160  {
2161    x=napNeg(x);
2162    y=napNeg(y);
2163  }
2164  number g=nacCopy(pGetCoeff(x));
2165  pIter(x);
2166  while (x!=NULL)
2167  {
2168    number d=nacGcd(g,pGetCoeff(x), nacRing);
2169    if(nacIsOne(d))
2170    {
2171      n_Delete(&g,nacRing);
2172      n_Delete(&d,nacRing);
2173      ntTest(pp);
2174      return;
2175    }
2176    n_Delete(&g,nacRing);
2177    g = d;
2178    pIter(x);
2179  }
2180  while (y!=NULL)
2181  {
2182    number d=nacGcd(g,pGetCoeff(y), nacRing);
2183    if(nacIsOne(d))
2184    {
2185      n_Delete(&g,nacRing);
2186      n_Delete(&d,nacRing);
2187      ntTest(pp);
2188      return;
2189    }
2190    n_Delete(&g,nacRing);
2191    g = d;
2192    pIter(y);
2193  }
2194  x=p->z;
2195  y=p->n;
2196  while (x!=NULL)
2197  {
2198    number d = nacIntDiv(pGetCoeff(x),g);
2199    napSetCoeff(x,d);
2200    pIter(x);
2201  }
2202  while (y!=NULL)
2203  {
2204    number d = nacIntDiv(pGetCoeff(y),g);
2205    napSetCoeff(y,d);
2206    pIter(y);
2207  }
2208  n_Delete(&g,nacRing);
2209  ntTest(pp);
2210}
2211
2212/*2
2213* returns in result->n 1
2214* and in     result->z the lcm(a->z,b->n)
2215*/
2216number ntLcm(number la, number lb, const ring r)
2217{
2218  lnumber result;
2219  lnumber a = (lnumber)la;
2220  lnumber b = (lnumber)lb;
2221  result = ALLOC0_LNUMBER();
2222  ntTest(la);
2223  ntTest(lb);
2224  poly x = p_Copy(a->z, r->algring);
2225  number t = napLcm(b->z); // get all denom of b->z
2226  if (!nacIsOne(t))
2227  {
2228    number bt, rr;
2229    poly xx=x;
2230    while (xx!=NULL)
2231    {
2232      bt = nacGcd(t, pGetCoeff(xx), r->algring);
2233      rr = nacMult(t, pGetCoeff(xx));
2234      n_Delete(&pGetCoeff(xx),r->algring);
2235      pGetCoeff(xx) = nacDiv(rr, bt);
2236      nacNormalize(pGetCoeff(xx));
2237      n_Delete(&bt,r->algring);
2238      n_Delete(&rr,r->algring);
2239      pIter(xx);
2240    }
2241  }
2242  n_Delete(&t,r->algring);
2243  result->z = x;
2244#ifdef HAVE_FACTORY
2245  if (b->n!=NULL)
2246  {
2247    result->z=singclap_alglcm(result->z,b->n);
2248    p_Delete(&x,r->algring);
2249  }
2250#endif
2251  ntTest(la);
2252  ntTest(lb);
2253  ntTest((number)result);
2254  return ((number)result);
2255}
2256
2257/*2
2258* map Z/p -> Q(a)
2259*/
2260number ntMapP0(number c)
2261{
2262  if (npIsZero(c)) return NULL;
2263  lnumber l=ALLOC_LNUMBER();
2264  l->s=2;
2265  l->z=(poly)p_Init(nacRing);
2266  int i=(int)((long)c);
2267  if (i>((long)ntMapRing->ch>>2)) i-=(long)ntMapRing->ch;
2268  pGetCoeff(l->z)=nlInit(i, nacRing);
2269  l->n=NULL;
2270  return (number)l;
2271}
2272
2273/*2
2274* map Q -> Q(a)
2275*/
2276number ntMap00(number c)
2277{
2278  if (nlIsZero(c)) return NULL;
2279  lnumber l=ALLOC_LNUMBER();
2280  l->s=0;
2281  l->z=(poly)p_Init(nacRing);
2282  pGetCoeff(l->z)=nlCopy(c);
2283  l->n=NULL;
2284  return (number)l;
2285}
2286
2287/*2
2288* map Z/p -> Z/p(a)
2289*/
2290number ntMapPP(number c)
2291{
2292  if (npIsZero(c)) return NULL;
2293  lnumber l=ALLOC_LNUMBER();
2294  l->s=2;
2295  l->z=(poly)p_Init(nacRing);
2296  pGetCoeff(l->z)=c; /* omit npCopy, because npCopy is a no-op */
2297  l->n=NULL;
2298  return (number)l;
2299}
2300
2301/*2
2302* map Z/p' -> Z/p(a)
2303*/
2304number ntMapPP1(number c)
2305{
2306  if (npIsZero(c)) return NULL;
2307  int i=(int)((long)c);
2308  if (i>(long)ntMapRing->ch) i-=(long)ntMapRing->ch;
2309  number n=npInit(i,ntMapRing);
2310  if (npIsZero(n)) return NULL;
2311  lnumber l=ALLOC_LNUMBER();
2312  l->s=2;
2313  l->z=(poly)p_Init(nacRing);
2314  pGetCoeff(l->z)=n;
2315  l->n=NULL;
2316  return (number)l;
2317}
2318
2319/*2
2320* map Q -> Z/p(a)
2321*/
2322number ntMap0P(number c)
2323{
2324  if (nlIsZero(c)) return NULL;
2325  number n=npInit(nlModP(c,npPrimeM),nacRing);
2326  if (npIsZero(n)) return NULL;
2327  npTest(n);
2328  lnumber l=ALLOC_LNUMBER();
2329  l->s=2;
2330  l->z=(poly)p_Init(nacRing);
2331  pGetCoeff(l->z)=n;
2332  l->n=NULL;
2333  return (number)l;
2334}
2335
2336/*2
2337* map _(a) -> _(b)
2338*/
2339number ntMapQaQb(number c)
2340{
2341  if (c==NULL) return NULL;
2342  lnumber erg= ALLOC0_LNUMBER();
2343  lnumber src =(lnumber)c;
2344  erg->s=src->s;
2345  erg->z=napMap(src->z);
2346  erg->n=napMap(src->n);
2347  return (number)erg;
2348}
2349
2350nMapFunc ntSetMap(const ring src, const ring dst)
2351{
2352  ntMapRing=src;
2353  if (rField_is_Q_a(dst)) /* -> Q(a) */
2354  {
2355    if (rField_is_Q(src))
2356    {
2357      return ntMap00;   /*Q -> Q(a)*/
2358    }
2359    if (rField_is_Zp(src))
2360    {
2361      return ntMapP0;  /* Z/p -> Q(a)*/
2362    }
2363    if (rField_is_Q_a(src))
2364    {
2365      int i;
2366      ntParsToCopy=0;
2367      for(i=0;i<rPar(src);i++)
2368      {
2369        if ((i>=rPar(dst))
2370        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2371           return NULL;
2372        ntParsToCopy++;
2373      }
2374      nacMap=nacCopy;
2375      if ((ntParsToCopy==rPar(dst))&&(ntParsToCopy==rPar(src)))
2376        return ntCopy;    /* Q(a) -> Q(a) */
2377      return ntMapQaQb;   /* Q(a..) -> Q(a..) */
2378    }
2379  }
2380  /*-----------------------------------------------------*/
2381  if (rField_is_Zp_a(dst)) /* -> Z/p(a) */
2382  {
2383    if (rField_is_Q(src))
2384    {
2385      return ntMap0P;   /*Q -> Z/p(a)*/
2386    }
2387    if (rField_is_Zp(src))
2388    {
2389      if (src->ch==dst->ch)
2390      {
2391        return ntMapPP;  /* Z/p -> Z/p(a)*/
2392      }
2393      else
2394      {
2395        return ntMapPP1;  /* Z/p' -> Z/p(a)*/
2396      }
2397    }
2398    if (rField_is_Zp_a(src))
2399    {
2400      if (rChar(src)==rChar(dst))
2401      {
2402        nacMap=nacCopy;
2403      }
2404      else
2405      {
2406        nacMap = npMapP;
2407      }
2408      int i;
2409      ntParsToCopy=0;
2410      for(i=0;i<rPar(src);i++)
2411      {
2412        if ((i>=rPar(dst))
2413        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2414           return NULL;
2415        ntParsToCopy++;
2416      }
2417      if ((ntParsToCopy==rPar(dst))&&(ntParsToCopy==rPar(src))
2418      && (nacMap==nacCopy))
2419        return ntCopy;    /* Z/p(a) -> Z/p(a) */
2420      return ntMapQaQb;   /* Z/p(a),Z/p'(a) -> Z/p(b)*/
2421    }
2422  }
2423  return NULL;      /* default */
2424}
2425
2426/*2
2427* convert a poly number into a poly
2428*/
2429poly ntPermNumber(number z, int * par_perm, int P, ring oldRing)
2430{
2431  if (z==NULL) return NULL;
2432  poly res=NULL;
2433  poly p;
2434  poly za=((lnumber)z)->z;
2435  poly zb=((lnumber)z)->n;
2436  nMapFunc nMap=ntSetMap(oldRing,currRing);
2437  if (currRing->parameter!=NULL)
2438    nMap=currRing->algring->cf->cfSetMap(oldRing->algring, nacRing);
2439  else
2440    nMap=currRing->cf->cfSetMap(oldRing->algring, currRing);
2441  if (nMap==NULL) return NULL; /* emergency exit only */
2442  do
2443  {
2444    p = pInit();
2445    pNext(p)=NULL;
2446    nNew(&pGetCoeff(p));
2447    int i;
2448    for(i=pVariables;i;i--)
2449       pSetExp(p,i, 0);
2450    if (rRing_has_Comp(currRing)) pSetComp(p, 0);
2451    poly pa=NULL;
2452    lnumber pan;
2453    if (currRing->parameter!=NULL)
2454    {
2455      assume(oldRing->algring!=NULL);
2456      pGetCoeff(p)=(number)ALLOC0_LNUMBER();
2457      pan=(lnumber)pGetCoeff(p);
2458      pan->s=2;
2459      pan->z=napInitz(nMap(pGetCoeff(za)));
2460      pa=pan->z;
2461    }
2462    else
2463    {
2464      pGetCoeff(p)=nMap(pGetCoeff(za));
2465    }
2466    for(i=0;i<P;i++)
2467    {
2468      if(napGetExpFrom(za,i+1,oldRing)!=0)
2469      {
2470        if(par_perm==NULL)
2471        {
2472          if ((rPar(currRing)>=i) && (pa!=NULL))
2473          {
2474            napSetExp(pa,i+1,napGetExpFrom(za,i+1,oldRing));
2475            p_Setm(pa,nacRing);
2476          }
2477          else
2478          {
2479            pDelete(&p);
2480            break;
2481          }
2482        }
2483        else if(par_perm[i]>0)
2484          pSetExp(p,par_perm[i],napGetExpFrom(za,i+1,oldRing));
2485        else if((par_perm[i]<0)&&(pa!=NULL))
2486        {
2487          napSetExp(pa,-par_perm[i], napGetExpFrom(za,i+1,oldRing));
2488          p_Setm(pa,nacRing);
2489        }
2490        else
2491        {
2492          pDelete(&p);
2493          break;
2494        }
2495      }
2496    }
2497    if (p!=NULL)
2498    {
2499      pSetm(p);
2500      if (zb!=NULL)
2501      {
2502        if  (currRing->P>0)
2503        {
2504          pan->n=napPerm(zb,par_perm,oldRing,nMap);
2505          if(pan->n==NULL) /* error in mapping or mapping to variable */
2506            pDelete(&p);
2507        }
2508        else
2509          pDelete(&p);
2510      }
2511      pTest(p);
2512      res=pAdd(res,p);
2513    }
2514    pIter(za);
2515  }
2516  while (za!=NULL);
2517  pTest(res);
2518  return res;
2519}
2520
2521number   ntGetDenom(number &n, const ring r)
2522{
2523  lnumber x=(lnumber)n;
2524  if (x->n!=NULL)
2525  {
2526    lnumber rr=ALLOC0_LNUMBER();
2527    rr->z=p_Copy(x->n,r->algring);
2528    rr->s = 2;
2529    return (number)rr;
2530  }
2531  return n_Init(1,r);
2532}
2533
2534number   ntGetNumerator(number &n, const ring r)
2535{
2536  lnumber x=(lnumber)n;
2537  lnumber rr=ALLOC0_LNUMBER();
2538  rr->z=p_Copy(x->z,r->algring);
2539  rr->s = 2;
2540  return (number)rr;
2541}
2542
2543#ifdef LDEBUG
2544BOOLEAN ntDBTest(number a, const char *f,const int l)
2545{
2546  lnumber x=(lnumber)a;
2547  if (x == NULL)
2548    return TRUE;
2549  #ifdef LDEBUG
2550  omCheckAddrSize(a, sizeof(slnumber));
2551  #endif
2552  poly p = x->z;
2553  if (p==NULL)
2554  {
2555    Print("0/* in %s:%d\n",f,l);
2556    return FALSE;
2557  }
2558  while(p!=NULL)
2559  {
2560    if (( ntIsChar0  && nlIsZero(pGetCoeff(p)))
2561    || ((!ntIsChar0) && npIsZero(pGetCoeff(p))))
2562    {
2563      Print("coeff 0 in %s:%d\n",f,l);
2564      return FALSE;
2565    }
2566    if (ntIsChar0 && !(nlDBTest(pGetCoeff(p),f,l)))
2567      return FALSE;
2568    pIter(p);
2569  }
2570  p = x->n;
2571  while(p!=NULL)
2572  {
2573    if (ntIsChar0 && !(nlDBTest(pGetCoeff(p),f,l)))
2574      return FALSE;
2575    pIter(p);
2576  }
2577  return TRUE;
2578}
2579#endif
2580#endif
Note: See TracBrowser for help on using the repository browser.