source: git/libpolys/polys/ext_fields/longtrans.cc @ a50dd10

fieker-DuValspielwiese
Last change on this file since a50dd10 was 16f8f1, checked in by Oleksandr Motsak <motsak@…>, 13 years ago
ADD: minor changes to coeffs, numbers and tests
  • Property mode set to 100644
File size: 52.4 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(napoly));
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(napoly 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 napoly that consists of a
177   single coefficient (provided as a number);
178   the provided number is NOT const */
179napoly napInitz(number z)
180{
181  napoly a = (napoly)p_Init(nacRing);
182  pGetCoeff(a) = z;
183  return a;
184}
185
186/* creates a new napoly which is the
187   negative inverse of the argument;
188   keeps p */
189napoly napCopyNeg(const napoly p)
190{
191  napoly r = napCopy(p);
192  r = (napoly)p_Neg((poly)r, nacRing);
193  return r;
194}
195
196/* modifies the napoly p to p*z, i.e.
197   in-place multiplication of p with the number z;
198   keeps z */
199void napMultN(napoly 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(napoly f, const napoly  g, napoly *q, napoly *r)
219{
220  napoly a, h, b, qq;
221
222  qq = (napoly)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 */
255napoly napRemainder(napoly f, const napoly g)
256{
257  napoly a, h, qq;
258
259  qq = (napoly)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 */
288napoly napInvers(napoly x, const napoly c)
289{
290  napoly 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 napoly, i.e. the
394   maximum of all terms' degrees;
395   keeps p */
396int napMaxDeg(napoly 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 napoly, i.e. the
408   maximum of all terms' degrees;
409   fills l with the number of terms;
410   keeps p */
411int napMaxDegLen(napoly 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 napoly, 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(napoly 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, napoly 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, napoly 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 napoly 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, napoly *b)
520{
521  napoly a;
522  int i;
523  a = (napoly)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(napoly a, napoly 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, napoly a, napoly 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(napoly ph)
613{
614  number h, d;
615  napoly 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(napoly ph)
653{
654  number d, h;
655  napoly 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 */
686napoly napGcd0(napoly a, napoly 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 */
721napoly napGcd(napoly a, napoly b)
722{
723  int i;
724  napoly g, x, y, h;
725  if (a == NULL)
726  {
727    if (b == NULL)    return p_ISet(1,nacRing);
728    else              return napCopy(b);
729  }
730  else if (b == NULL) return napCopy(a);
731 
732  if (naMinimalPoly != NULL)
733  { // we have an algebraic extension
734    if (p_GetExp(a,1,nacRing) >= p_GetExp(b,1,nacRing))
735    {
736      x = a;
737      y = b;
738    }
739    else
740    {
741      x = b;
742      y = a;
743    }
744    if (!ntIsChar0) g = p_ISet(1,nacRing);
745    else            g = napGcd0(x, y);
746    if (pNext(y)==NULL)
747    {
748      napSetExp(g,1, napExp(x, y));
749      p_Setm(g,nacRing);
750      return g;
751    }
752    x = napCopy(x);
753    y = napCopy(y);
754    loop
755    {
756      h = napRemainder(x, y);
757      if (h==NULL)
758      {
759        napCleardenom(y);
760        if (!nacIsOne(pGetCoeff(g)))
761          napMultN(y, pGetCoeff(g));
762        p_LmDelete(&g,nacRing);
763        return y;
764      }
765      else if (pNext(h)==NULL)
766        break;
767      x = y;
768      y = h;
769    }
770    p_Delete(&y,nacRing);
771    p_LmDelete(&h,nacRing);
772    napSetExp(g,1, napExp(a, b));
773    p_Setm(g,nacRing);
774    return g;
775  }
776  else
777  { // we have ntNumbOfPar transcendental variables
778    if (!ntIsChar0) x = p_ISet(1,nacRing);
779    else            x = napGcd0(a,b);
780    for (i=(ntNumbOfPar-1); i>=0; i--)
781    {
782      napSetExp(x,i+1, napExpi(i,a,b));
783      p_Setm(x,nacRing);
784    }
785    return x;
786  }
787}
788
789/* returns the lcm of all denominators in the coefficients of a;
790   if char != 0, then the constant poly 1 is returned;
791   if a = 0, then the constant poly 1 is returned;
792   keeps a */
793number napLcm(napoly a)
794{
795  number h = nacInit(1,nacRing);
796  if (ntIsChar0)
797  {
798    number d;
799    napoly b = a;
800    while (b!=NULL)
801    {
802      d = nacLcm(h, pGetCoeff(b), nacRing); // uses denominator of pGetCoeff(b)
803      n_Delete(&h,nacRing);
804      h = d;
805      pIter(b);
806    }
807  }
808  return h;
809}
810
811/*2
812* meins  (for reduction in algebraic extension)
813* checks if head of p divides head of q
814* doesn't delete p and q
815*/
816BOOLEAN napDivPoly (napoly p, napoly q)
817{
818  int j=1;   /* evtl. von naNumber.. -1 abwaerts zaehlen */
819
820  while (p_GetExp(p,j,nacRing) <= p_GetExp(q,j,nacRing))
821  {
822    j++;
823    if (j > ntNumbOfPar)
824      return 1;
825  }
826  return 0;
827}
828
829
830/*
831 * only used for reduction in algebraic extensions when naI != NULL;
832 * reduces the tail of poly q which is required to be != NULL;
833 * modifies q and returns it
834 */
835napoly napRedp (napoly q)
836{
837  napoly h = (napoly)p_Init(nacRing);
838  int i=0,j;
839
840  loop
841  {
842    if (napDivPoly (naI->liste[i], q))
843    {
844      /* h = lt(q)/lt(naI->liste[i])*/
845      pGetCoeff(h) = nacCopy(pGetCoeff(q));
846      for (j=ntNumbOfPar; j>0; j--)
847        napSetExp(h,j, p_GetExp(q,j,nacRing) - p_GetExp(naI->liste[i],
848                                                        j,nacRing));
849      p_Setm(h,nacRing);
850      h = p_Mult_q(h, napCopy(naI->liste[i]),nacRing);
851      h = napNeg (h);
852      q = napAdd (q, napCopy(h));
853      p_Delete (&pNext(h),nacRing);
854      if (q == NULL)
855      {
856        p_Delete(&h,nacRing);
857        return q;
858      }
859      /* try to reduce further */
860      i = 0;
861    }
862    else
863    {
864      i++;
865      if (i >= naI->anz)
866      {
867        p_Delete(&h,nacRing);
868        return q;
869      }
870    }
871  }
872}
873
874
875/*
876 * only used for reduction in algebraic extensions when naI != NULL;
877 * reduces the tail of poly q which is required to be != NULL;
878 * modifies q and returns it
879 */
880napoly napTailred (napoly q)
881{
882  napoly h;
883
884  h = pNext(q);
885  while (h != NULL)
886  {
887     h = napRedp (h);
888     if (h == NULL)
889        return q;
890     pIter(h);
891  }
892  return q;
893}
894
895napoly napMap(napoly p)
896{
897  napoly w, a;
898
899  if (p==NULL) return NULL;
900  a = w = (napoly)p_Init(nacRing);
901  int i;
902  for(i=1;i<=ntParsToCopy;i++)
903    napSetExp(a,i,napGetExpFrom(p,i,ntMapRing));
904  p_Setm(a,nacRing);
905  pGetCoeff(w) = nacMap(pGetCoeff(p));
906  loop
907  {
908    pIter(p);
909    if (p==NULL) break;
910    pNext(a) = (napoly)p_Init(nacRing);
911    pIter(a);
912    for(i=1;i<=ntParsToCopy;i++)
913      napSetExp(a,i,napGetExpFrom(p,i,ntMapRing));
914    p_Setm(a,nacRing);
915    pGetCoeff(a) = nacMap(pGetCoeff(p));
916  }
917  pNext(a) = NULL;
918  return w;
919}
920
921napoly napPerm(napoly p,const int *par_perm,const ring src_ring,const nMapFunc nMap)
922{
923  napoly w;
924
925  if (p==NULL) return NULL;
926  w = (napoly)p_Init(nacRing);
927  int i;
928  BOOLEAN not_null=TRUE;
929  loop
930  {
931    for(i=1;i<=rPar(src_ring);i++)
932    {
933      int e;
934      if (par_perm!=NULL) e=par_perm[i-1];
935      else                e=-i;
936      int ee=napGetExpFrom(p,i,src_ring);
937      if (e<0)
938        napSetExp(w,-e,ee);
939      else if (ee>0)
940        not_null=FALSE;
941    }
942    pGetCoeff(w) = nMap(pGetCoeff(p));
943    p_Setm(w,nacRing);
944    pIter(p);
945    if (!not_null)
946    {
947      if (p==NULL)
948      {
949        p_Delete(&w,nacRing);
950        return NULL;
951      }
952      /* else continue*/
953      n_Delete(&(pGetCoeff(w)),nacRing);
954    }
955    else
956    {
957      if (p==NULL) return w;
958      else
959      {
960        pNext(w)=napPerm(p,par_perm,src_ring,nMap);
961        return w;
962      }
963    }
964  }
965}
966
967/*2
968* convert a napoly number into a poly
969*/
970poly napPermNumber(number z, int * par_perm, int P, ring oldRing)
971{
972  if (z==NULL) return NULL;
973  poly res=NULL;
974  poly p;
975  napoly za=((lnumber)z)->z;
976  napoly zb=((lnumber)z)->n;
977  nMapFunc nMap=naSetMap(oldRing,currRing); /* todo: check naSetMap
978                                                     vs. ntSetMap */
979  if (currRing->parameter!=NULL)
980    nMap=currRing->algring->cf->cfSetMap(oldRing->algring, nacRing);
981  else
982    nMap=currRing->cf->cfSetMap(oldRing->algring, currRing);
983  if (nMap==NULL) return NULL; /* emergency exit only */
984  while(za!=NULL)
985  {
986    p = pInit();
987    pNext(p)=NULL;
988    //nNew(&pGetCoeff(p));
989    int i;
990    //for(i=pVariables;i;i--) pSetExp(p,i, 0); // done by pInit
991    //if (rRing_has_Comp(currRing)) pSetComp(p, 0); // done by pInit
992    napoly pa=NULL;
993    lnumber pan;
994    if (currRing->parameter!=NULL)
995    {
996      assume(oldRing->algring!=NULL);
997      pGetCoeff(p)=(number)ALLOC0_LNUMBER();
998      pan=(lnumber)pGetCoeff(p);
999      pan->s=2;
1000      pan->z=napInitz(nMap(pGetCoeff(za)));
1001      pa=pan->z;
1002    }
1003    else
1004    {
1005      pGetCoeff(p)=nMap(pGetCoeff(za));
1006    }
1007    for(i=0;i<P;i++)
1008    {
1009      if(napGetExpFrom(za,i+1,oldRing)!=0)
1010      {
1011        if(par_perm==NULL)
1012        {
1013          if ((rPar(currRing)>=i) && (pa!=NULL))
1014          {
1015            napSetExp(pa,i+1,napGetExpFrom(za,i+1,oldRing));
1016            p_Setm(pa,nacRing);
1017          }
1018          else
1019          {
1020            pDelete(&p);
1021            break;
1022          }
1023        }
1024        else if(par_perm[i]>0)
1025          pSetExp(p,par_perm[i],napGetExpFrom(za,i+1,oldRing));
1026        else if((par_perm[i]<0)&&(pa!=NULL))
1027        {
1028          napSetExp(pa,-par_perm[i], napGetExpFrom(za,i+1,oldRing));
1029          p_Setm(pa,nacRing);
1030        }
1031        else
1032        {
1033          pDelete(&p);
1034          break;
1035        }
1036      }
1037    }
1038    if (p!=NULL)
1039    {
1040      pSetm(p);
1041      if (zb!=NULL)
1042      {
1043        if  (currRing->P>0)
1044        {
1045          pan->n=napPerm(zb,par_perm,oldRing,nMap);
1046          if(pan->n==NULL) /* error in mapping or mapping to variable */
1047            pDelete(&p);
1048        }
1049        else
1050          pDelete(&p);
1051      }
1052      nNormalize(pGetCoeff(p));
1053      if (nIsZero(pGetCoeff(p)))
1054        pDelete(&p);
1055      else
1056      {
1057        pTest(p);
1058        res=pAdd(res,p);
1059      }
1060    }
1061    pIter(za);
1062  }
1063  pTest(res);
1064  return res;
1065}
1066
1067number   napGetDenom(number &n, const ring r)
1068{
1069  lnumber x=(lnumber)n;
1070  if (x->n!=NULL)
1071  {
1072    lnumber rr=ALLOC0_LNUMBER();
1073    rr->z=p_Copy(x->n,r->algring);
1074    rr->s = 2;
1075    return (number)rr;
1076  }
1077  return n_Init(1,r);
1078}
1079
1080number   napGetNumerator(number &n, const ring r)
1081{
1082  lnumber x=(lnumber)n;
1083  lnumber rr=ALLOC0_LNUMBER();
1084  rr->z=p_Copy(x->z,r->algring);
1085  rr->s = 2;
1086  return (number)rr;
1087}
1088
1089/*================ procedure for rational functions: ntXXXX =================*/
1090
1091/*2
1092*  z:= i
1093*/
1094number ntInit(int i, const ring r)
1095{
1096  if (i!=0)
1097  {
1098    number c=n_Init(i,r->algring);
1099    if (!n_IsZero(c,r->algring))
1100    {
1101      poly z=p_Init(r->algring);
1102      pSetCoeff0(z,c);
1103      lnumber l = (lnumber)ALLOC_LNUMBER();
1104      l->z = z;
1105      l->s = 2;
1106      l->n = NULL;
1107      return (number)l;
1108    }
1109  }
1110  /*else*/
1111  return NULL;
1112}
1113
1114/*3
1115*  division with remainder: f = g*q + r,
1116*  returns r and destroys f
1117*/
1118napoly ntRemainder(napoly f, const napoly g)
1119{
1120  napoly a, h, qq;
1121
1122  qq = (napoly)p_Init(nacRing);
1123  pNext(qq) = NULL;
1124  p_Normalize(g, nacRing);
1125  p_Normalize(f, nacRing);
1126  a = f;
1127  do
1128  {
1129    napSetExp(qq,1, p_GetExp(a,1,nacRing) - p_GetExp(g,1,nacRing));
1130    napSetm(qq);
1131    pGetCoeff(qq) = nacDiv(pGetCoeff(a), pGetCoeff(g));
1132    pGetCoeff(qq) = nacNeg(pGetCoeff(qq));
1133    nacNormalize(pGetCoeff(qq));
1134    h = napCopy(g);
1135    napMultT(h, qq);
1136    p_Normalize(h,nacRing);
1137    n_Delete(&pGetCoeff(qq),nacRing);
1138    a = napAdd(a, h);
1139  }
1140  while ((a!=NULL) && (p_GetExp(a,1,nacRing) >= p_GetExp(g,1,nacRing)));
1141  omFreeBinAddr(qq);
1142  return a;
1143}
1144
1145number  ntPar(int i)
1146{
1147  lnumber l = ALLOC_LNUMBER();
1148  l->s = 2;
1149  l->z = p_ISet(1,nacRing);
1150  napSetExp(l->z,i,1);
1151  p_Setm(l->z,nacRing);
1152  l->n = NULL;
1153  return (number)l;
1154}
1155
1156int     ntParDeg(number n)     /* i := deg(n) */
1157{
1158  lnumber l = (lnumber)n;
1159  if (l==NULL) return -1;
1160  return napDeg(l->z);
1161}
1162
1163//int     ntParDeg(number n)     /* i := deg(n) */
1164//{
1165//  lnumber l = (lnumber)n;
1166//  if (l==NULL) return -1;
1167//  return napMaxDeg(l->z)+napMaxDeg(l->n);
1168//}
1169
1170int     ntSize(number n)     /* size desc. */
1171{
1172  lnumber l = (lnumber)n;
1173  if (l==NULL) return -1;
1174  int len_z;
1175  int len_n;
1176  int o=napMaxDegLen(l->z,len_z)+napMaxDegLen(l->n,len_n);
1177  return (len_z+len_n)+o;
1178}
1179
1180/*2
1181* convert a number to int (if possible)
1182*/
1183int ntInt(number &n, const ring r)
1184{
1185  lnumber l=(lnumber)n;
1186  if ((l!=NULL)&&(l->n==NULL)&&(p_IsConstant(l->z,r->algring)))
1187  {
1188    return nacInt(pGetCoeff(l->z),r->algring);
1189  }
1190  return 0;
1191}
1192
1193/*2
1194*  deletes p
1195*/
1196void ntDelete(number *p, const ring r)
1197{
1198  if ((*p)!=NULL)
1199  {
1200    lnumber l = (lnumber) * p;
1201    if (l==NULL) return;
1202    p_Delete(&(l->z),r->algring);
1203    p_Delete(&(l->n),r->algring);
1204    FREE_LNUMBER(l);
1205  }
1206  *p = NULL;
1207}
1208
1209/*2
1210* copy p to erg
1211*/
1212number ntCopy(number p)
1213{
1214  if (p==NULL) return NULL;
1215  ntTest(p);
1216  lnumber erg;
1217  lnumber src = (lnumber)p;
1218  erg = ALLOC_LNUMBER();
1219  erg->z = p_Copy(src->z, nacRing);
1220  erg->n = p_Copy(src->n, nacRing);
1221  erg->s = src->s;
1222  return (number)erg;
1223}
1224number nt_Copy(number p, const ring r)
1225{
1226  if (p==NULL) return NULL;
1227  lnumber erg;
1228  lnumber src = (lnumber)p;
1229  erg = ALLOC_LNUMBER();
1230  erg->z = p_Copy(src->z,r->algring);
1231  erg->n = p_Copy(src->n,r->algring);
1232  erg->s = src->s;
1233  return (number)erg;
1234}
1235
1236/*2
1237*  addition; lu:= la + lb
1238*/
1239number ntAdd(number la, number lb)
1240{
1241  if (la==NULL) return ntCopy(lb);
1242  if (lb==NULL) return ntCopy(la);
1243
1244  napoly x, y;
1245  lnumber lu;
1246  lnumber a = (lnumber)la;
1247  lnumber b = (lnumber)lb;
1248  #ifdef LDEBUG
1249  omCheckAddrSize(a,sizeof(slnumber));
1250  omCheckAddrSize(b,sizeof(slnumber));
1251  #endif
1252  if (b->n!=NULL) x = pp_Mult_qq(a->z, b->n,nacRing);
1253  else            x = napCopy(a->z);
1254  if (a->n!=NULL) y = pp_Mult_qq(b->z, a->n,nacRing);
1255  else            y = napCopy(b->z);
1256  napoly res = napAdd(x, y);
1257  if (res==NULL)
1258  {
1259    return (number)NULL;
1260  }
1261  lu = ALLOC_LNUMBER();
1262  lu->z=res;
1263  if (a->n!=NULL)
1264  {
1265    if (b->n!=NULL) x = pp_Mult_qq(a->n, b->n,nacRing);
1266    else            x = napCopy(a->n);
1267  }
1268  else
1269  {
1270    if (b->n!=NULL) x = napCopy(b->n);
1271    else            x = NULL;
1272  }
1273  //if (x!=NULL)
1274  //{
1275  //  if (p_LmIsConstant(x,nacRing))
1276  //  {
1277  //    number inv=nacInvers(pGetCoeff(x));
1278  //    napMultN(lu->z,inv);
1279  //    n_Delete(&inv,nacRing);
1280  //    napDelete(&x);
1281  //  }
1282  //}
1283  lu->n = x;
1284  lu->s = FALSE;
1285  if (/*lu->n*/ x!=NULL)
1286  {
1287     number luu=(number)lu;
1288     //if (p_IsConstant(lu->n,nacRing)) ntCoefNormalize(luu);
1289     //else
1290                ntNormalize(luu);
1291     lu=(lnumber)luu;
1292  }
1293  //else lu->s=2;
1294  ntTest((number)lu);
1295  return (number)lu;
1296}
1297
1298/*2
1299*  subtraction; r:= la - lb
1300*/
1301number ntSub(number la, number lb)
1302{
1303  lnumber lu;
1304
1305  if (lb==NULL) return ntCopy(la);
1306  if (la==NULL)
1307  {
1308    lu = (lnumber)ntCopy(lb);
1309    lu->z = napNeg(lu->z);
1310    return (number)lu;
1311  }
1312
1313  lnumber a = (lnumber)la;
1314  lnumber b = (lnumber)lb;
1315
1316  #ifdef LDEBUG
1317  omCheckAddrSize(a,sizeof(slnumber));
1318  omCheckAddrSize(b,sizeof(slnumber));
1319  #endif
1320
1321  napoly x, y;
1322  if (b->n!=NULL) x = pp_Mult_qq(a->z, b->n,nacRing);
1323  else            x = napCopy(a->z);
1324  if (a->n!=NULL) y = p_Mult_q(napCopy(b->z), napCopyNeg(a->n),nacRing);
1325  else            y = napCopyNeg(b->z);
1326  napoly res = napAdd(x, y);
1327  if (res==NULL)
1328  {
1329    return (number)NULL;
1330  }
1331  lu = ALLOC_LNUMBER();
1332  lu->z=res;
1333  if (a->n!=NULL)
1334  {
1335    if (b->n!=NULL) x = pp_Mult_qq(a->n, b->n,nacRing);
1336    else            x = napCopy(a->n);
1337  }
1338  else
1339  {
1340    if (b->n!=NULL) x = napCopy(b->n);
1341    else            x = NULL;
1342  }
1343  lu->n = x;
1344  lu->s = FALSE;
1345  if (/*lu->n*/ x!=NULL)
1346  {
1347     number luu=(number)lu;
1348     //if (p_IsConstant(lu->n,nacRing)) ntCoefNormalize(luu);
1349     //else
1350                         ntNormalize(luu);
1351     lu=(lnumber)luu;
1352  }
1353  //else lu->s=2;
1354  ntTest((number)lu);
1355  return (number)lu;
1356}
1357
1358/*2
1359*  multiplication; r:= la * lb
1360*/
1361number ntMult(number la, number lb)
1362{
1363  if ((la==NULL) || (lb==NULL))
1364    return NULL;
1365
1366  lnumber a = (lnumber)la;
1367  lnumber b = (lnumber)lb;
1368  lnumber lo;
1369  napoly x;
1370
1371  #ifdef LDEBUG
1372  omCheckAddrSize(a,sizeof(slnumber));
1373  omCheckAddrSize(b,sizeof(slnumber));
1374  #endif
1375  ntTest(la);
1376  ntTest(lb);
1377
1378  lo = ALLOC_LNUMBER();
1379  lo->z = pp_Mult_qq(a->z, b->z,nacRing);
1380
1381  if (a->n==NULL)
1382  {
1383    if (b->n==NULL)
1384      x = NULL;
1385    else
1386      x = napCopy(b->n);
1387  }
1388  else
1389  {
1390    if (b->n==NULL)
1391    {
1392      x = napCopy(a->n);
1393    }
1394    else
1395    {
1396      x = pp_Mult_qq(b->n, a->n, nacRing);
1397    }
1398  }
1399  if ((x!=NULL) && (p_LmIsConstant(x,nacRing)) && nacIsOne(pGetCoeff(x)))
1400    p_Delete(&x,nacRing);
1401  lo->n = x;
1402  lo->s = 0;
1403  number luu=(number)lo;
1404  if(lo->z==NULL)
1405  {
1406    FREE_LNUMBER(lo);
1407    lo=NULL;
1408  }
1409  else if (lo->n!=NULL)
1410  {
1411    // if (p_IsConstant(lo->n,nacRing)) ntCoefNormalize(luu);
1412    // else
1413                      ntNormalize(luu);
1414    lo=(lnumber)luu;
1415  }
1416  luu=(number)lo;
1417  if ((lo!=NULL) 
1418  && (naMinimalPoly!=NULL)
1419  &&(p_GetExp(lo->z,1,nacRing)>=p_GetExp(naMinimalPoly,1,nacRing)))
1420    lo->z=napRemainder(lo->z,naMinimalPoly);
1421  //if (naMinimalPoly==NULL) lo->s=2;
1422  ntTest((number)lo);
1423  return (number)lo;
1424}
1425
1426number ntIntDiv(number la, number lb)
1427{
1428  ntTest(la);
1429  ntTest(lb);
1430  lnumber res;
1431  lnumber a = (lnumber)la;
1432  lnumber b = (lnumber)lb;
1433  if (a==NULL)
1434  {
1435    return NULL;
1436  }
1437  if (b==NULL)
1438  {
1439    WerrorS(nDivBy0);
1440    return NULL;
1441  }
1442#ifdef LDEBUG
1443  omCheckAddrSize(a,sizeof(slnumber));
1444  omCheckAddrSize(b,sizeof(slnumber));
1445#endif
1446  assume(a->z!=NULL && b->z!=NULL);
1447  assume(a->n==NULL && b->n==NULL);
1448  res = ALLOC_LNUMBER();
1449  res->z = napCopy(a->z);
1450  res->n = napCopy(b->z);
1451  res->s = 0;
1452  number nres=(number)res;
1453  ntNormalize(nres);
1454
1455  //napDelete(&res->n);
1456  ntTest(nres);
1457  return nres;
1458}
1459
1460/*2
1461*  division; lo:= la / lb
1462*/
1463number ntDiv(number la, number lb)
1464{
1465  lnumber lo;
1466  lnumber a = (lnumber)la;
1467  lnumber b = (lnumber)lb;
1468  napoly x;
1469
1470  if (a==NULL)
1471    return NULL;
1472
1473  if (b==NULL)
1474  {
1475    WerrorS(nDivBy0);
1476    return NULL;
1477  }
1478  #ifdef LDEBUG
1479  omCheckAddrSize(a,sizeof(slnumber));
1480  omCheckAddrSize(b,sizeof(slnumber));
1481  #endif
1482  lo = ALLOC_LNUMBER();
1483  if (b->n!=NULL)
1484    lo->z = pp_Mult_qq(a->z, b->n,nacRing);
1485  else
1486    lo->z = napCopy(a->z);
1487  if (a->n!=NULL)
1488    x = pp_Mult_qq(b->z, a->n, nacRing);
1489  else
1490    x = napCopy(b->z);
1491  if ((p_LmIsConstant(x,nacRing)) && nacIsOne(pGetCoeff(x)))
1492    p_Delete(&x,nacRing);
1493  lo->n = x;
1494  lo->s = 0;
1495  if (lo->n!=NULL)
1496  {
1497    number luu=(number)lo;
1498     //if (p_IsConstant(lo->n,nacRing)) ntCoefNormalize(luu);
1499     //else
1500                         ntNormalize(luu);
1501    lo=(lnumber)luu;
1502  }
1503  //else lo->s=2;
1504  ntTest((number)lo);
1505  return (number)lo;
1506}
1507
1508/*2
1509*  za:= - za, inplace
1510*/
1511number ntNeg(number za)
1512{
1513  if (za!=NULL)
1514  {
1515    lnumber e = (lnumber)za;
1516    ntTest(za);
1517    e->z = napNeg(e->z);
1518  }
1519  return za;
1520}
1521
1522/*2
1523* 1/a
1524*/
1525number ntInvers(number a)
1526{
1527  lnumber lo;
1528  lnumber b = (lnumber)a;
1529  napoly x;
1530
1531  if (b==NULL)
1532  {
1533    WerrorS(nDivBy0);
1534    return NULL;
1535  }
1536  #ifdef LDEBUG
1537  omCheckAddrSize(b,sizeof(slnumber));
1538  #endif
1539  lo = ALLOC0_LNUMBER();
1540  lo->s = b->s;
1541  if (b->n!=NULL)
1542    lo->z = napCopy(b->n);
1543  else
1544    lo->z = p_ISet(1,nacRing);
1545  x = b->z;
1546  if ((!p_LmIsConstant(x,nacRing)) || !nacIsOne(pGetCoeff(x)))
1547    x = napCopy(x);
1548  else
1549  {
1550    lo->n = NULL;
1551    ntTest((number)lo);
1552    return (number)lo;
1553  }
1554  lo->n = x;
1555  if (lo->n!=NULL)
1556  {
1557     number luu=(number)lo;
1558     //if (p_IsConstant(lo->n,nacRing)) ntCoefNormalize(luu);
1559     //else
1560                           ntNormalize(luu);
1561     lo=(lnumber)luu;
1562  }
1563  ntTest((number)lo);
1564  return (number)lo;
1565}
1566
1567
1568BOOLEAN ntIsZero(number za)
1569{
1570  lnumber zb = (lnumber)za;
1571  ntTest(za);
1572#ifdef LDEBUG
1573  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(2)");
1574#endif
1575  return (zb==NULL);
1576}
1577
1578
1579BOOLEAN ntGreaterZero(number za)
1580{
1581  lnumber zb = (lnumber)za;
1582#ifdef LDEBUG
1583  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(3)");
1584#endif
1585  ntTest(za);
1586  if (zb!=NULL)
1587  {
1588    return (nacGreaterZero(pGetCoeff(zb->z))||(!p_LmIsConstant(zb->z,nacRing)));
1589  }
1590  /* else */ return FALSE;
1591}
1592
1593
1594/*2
1595* a = b ?
1596*/
1597BOOLEAN ntEqual (number a, number b)
1598{
1599  if(a==b) return TRUE;
1600  if((a==NULL)&&(b!=NULL)) return FALSE;
1601  if((b==NULL)&&(a!=NULL)) return FALSE;
1602
1603  lnumber aa=(lnumber)a;
1604  lnumber bb=(lnumber)b;
1605
1606  int an_deg=0;
1607  if(aa->n!=NULL)
1608    an_deg=napDeg(aa->n);
1609  int bn_deg=0;
1610  if(bb->n!=NULL)
1611    bn_deg=napDeg(bb->n);
1612  if(an_deg+napDeg(bb->z)!=bn_deg+napDeg(aa->z))
1613    return FALSE;
1614#if 0
1615  ntNormalize(a);
1616  aa=(lnumber)a;
1617  ntNormalize(b);
1618  bb=(lnumber)b;
1619  if((aa->n==NULL)&&(bb->n!=NULL)) return FALSE;
1620  if((bb->n==NULL)&&(aa->n!=NULL)) return FALSE;
1621  if(napComp(aa->z,bb->z)!=0) return FALSE;
1622  if((aa->n!=NULL) && (napComp(aa->n,bb->n))) return FALSE;
1623#endif
1624  number h = ntSub(a, b);
1625  BOOLEAN bo = ntIsZero(h);
1626  ntDelete(&h,currRing);
1627  return bo;
1628}
1629
1630/* This method will only consider the numerators of a and b.
1631   Moreover it may return TRUE only if one or both numerators
1632   are zero or if their degrees are equal. Then TRUE is returned iff
1633   coeff(numerator(a)) > coeff(numerator(b));
1634   In all other cases, FALSE will be returned. */
1635BOOLEAN ntGreater (number a, number b)
1636{
1637  int az = 0; int ad = 0;
1638  if (ntIsZero(a)) az = 1;
1639  else ad = napDeg(((lnumber)a)->z);
1640  int bz = 0; int bd = 0;
1641  if (ntIsZero(b)) bz = 1;
1642  else bd = napDeg(((lnumber)b)->z);
1643 
1644  if ((az == 1) && (bz == 1)) /* a = b = 0 */ return FALSE;
1645  if (az == 1) /* a = 0, b != 0 */
1646  {
1647    return (!nacGreaterZero(pGetCoeff(((lnumber)b)->z)));
1648  }
1649  if (bz == 1) /* a != 0, b = 0 */
1650  {
1651    return (nacGreaterZero(pGetCoeff(((lnumber)a)->z)));
1652  }
1653  if (ad == bd) 
1654    return nacGreater(pGetCoeff(((lnumber)a)->z),
1655                      pGetCoeff(((lnumber)b)->z));
1656  return FALSE;
1657}
1658
1659/*2
1660* reads a number
1661*/
1662const char  *ntRead(const char *s, number *p)
1663{
1664  napoly x;
1665  lnumber a;
1666  s = napRead(s, &x);
1667  if (x==NULL)
1668  {
1669    *p = NULL;
1670    return s;
1671  }
1672  *p = (number)ALLOC0_LNUMBER();
1673  a = (lnumber)*p;
1674  a->z = x;
1675  if(a->z==NULL)
1676  {
1677    FREE_LNUMBER(a);
1678    *p=NULL;
1679  }
1680  else
1681  {
1682    a->n = NULL;
1683    a->s = 0;
1684    ntTest(*p);
1685  }
1686  return s;
1687}
1688
1689/*2
1690* tries to convert a number to a name
1691*/
1692char * ntName(number n)
1693{
1694  lnumber ph = (lnumber)n;
1695  if (ph==NULL)
1696    return NULL;
1697  int i;
1698  char *s=(char *)omAlloc(4* ntNumbOfPar);
1699  char *t=(char *)omAlloc(8);
1700  s[0]='\0';
1701  for (i = 0; i <= ntNumbOfPar - 1; i++)
1702  {
1703    int e=p_GetExp(ph->z,i+1,nacRing);
1704    if (e > 0)
1705    {
1706      if (e >1)
1707      {
1708        sprintf(t,"%s%d",ntParNames[i],e);
1709        strcat(s,t);
1710      }
1711      else
1712      {
1713        strcat(s,ntParNames[i]);
1714      }
1715    }
1716  }
1717  omFreeSize((ADDRESS)t,8);
1718  if (s[0]=='\0')
1719  {
1720    omFree((ADDRESS)s);
1721    return NULL;
1722  }
1723  return s;
1724}
1725
1726/*2
1727*  writes a number
1728*/
1729void ntWrite(number &phn, const ring r)
1730{
1731  lnumber ph = (lnumber)phn;
1732  if (ph==NULL)
1733    StringAppendS("0");
1734  else
1735  {
1736    phn->s = 0;
1737    BOOLEAN has_denom=(ph->n!=NULL);
1738    napWrite(ph->z,has_denom/*(ph->n!=NULL)*/,r);
1739    if (has_denom/*(ph->n!=NULL)*/)
1740    {
1741      StringAppendS("/");
1742      napWrite(ph->n,TRUE,r);
1743    }
1744  }
1745}
1746
1747/*2
1748* za == 1 ?
1749*/
1750BOOLEAN ntIsOne(number za)
1751{
1752  lnumber a = (lnumber)za;
1753  if (a==NULL) return FALSE;
1754#ifdef LDEBUG
1755  omCheckAddrSize(a,sizeof(slnumber));
1756  if (a->z==NULL)
1757  {
1758    WerrorS("internal zero error(4)");
1759    return FALSE;
1760  }
1761#endif
1762  if (a->n==NULL)
1763  {
1764    if (p_LmIsConstant(a->z,nacRing))
1765    {
1766      return nacIsOne(pGetCoeff(a->z));
1767    }
1768    else                 return FALSE;
1769  }
1770#if 0
1771  number t;
1772  x = a->z;
1773  y = a->n;
1774  do
1775  {
1776    if (napComp(x, y))
1777      return FALSE;
1778    else
1779    {
1780      t = nacSub(pGetCoeff(x), pGetCoeff(y));
1781      if (!nacIsZero(t))
1782      {
1783        n_Delete(&t,nacRing);
1784        return FALSE;
1785      }
1786      else
1787        n_Delete(&t,nacRing);
1788    }
1789    pIter(x);
1790    pIter(y);
1791  }
1792  while ((x!=NULL) && (y!=NULL));
1793  if ((x!=NULL) || (y!=NULL)) return FALSE;
1794  p_Delete(&a->z,nacRing);
1795  p_Delete(&a->n,nacRing);
1796  a->z = p_ISet(1,nacRing);
1797  a->n = NULL;
1798  return TRUE;
1799#else
1800  return FALSE;
1801#endif
1802}
1803
1804/*2
1805* za == -1 ?
1806*/
1807BOOLEAN ntIsMOne(number za)
1808{
1809  lnumber a = (lnumber)za;
1810  if (a==NULL) return FALSE;
1811#ifdef LDEBUG
1812  omCheckAddrSize(a,sizeof(slnumber));
1813  if (a->z==NULL)
1814  {
1815    WerrorS("internal zero error(5)");
1816    return FALSE;
1817  }
1818#endif
1819  if (a->n==NULL)
1820  {
1821    if (p_LmIsConstant(a->z,nacRing)) return n_IsMOne(pGetCoeff(a->z),nacRing);
1822    /*else                   return FALSE;*/
1823  }
1824  return FALSE;
1825}
1826
1827/*2
1828* returns the i-th power of p (i>=0)
1829*/
1830void ntPower(number p, int i, number *rc)
1831{
1832  number x;
1833  *rc = ntInit(1,currRing);
1834  for (; i > 0; i--)
1835  {
1836    x = ntMult(*rc, p);
1837    ntDelete(rc,currRing);
1838    *rc = x;
1839  }
1840}
1841
1842/*2
1843* result =gcd(a,b)
1844*/
1845number ntGcd(number a, number b, const ring r)
1846{
1847  if (a==NULL)  return ntCopy(b);
1848  if (b==NULL)  return ntCopy(a);
1849
1850  lnumber x, y;
1851  lnumber result = ALLOC0_LNUMBER();
1852
1853  x = (lnumber)a;
1854  y = (lnumber)b;
1855#ifndef HAVE_FACTORY
1856  result->z = napGcd(x->z, y->z); // change from napGcd0
1857#else
1858  int c=ABS(nGetChar());
1859  if (c==1) c=0;
1860  setCharacteristic( c );
1861
1862  napoly rz=napGcd(x->z, y->z);
1863  CanonicalForm F, G, R;
1864  R=convSingPFactoryP(rz,r->algring);
1865  p_Normalize(x->z,nacRing);
1866  F=convSingPFactoryP(x->z,r->algring)/R;
1867  p_Normalize(y->z,nacRing);
1868  G=convSingPFactoryP(y->z,r->algring)/R;
1869  F = gcd( F, G );
1870  if (F.isOne())
1871    result->z= rz;
1872  else
1873  {
1874    p_Delete(&rz,r->algring);
1875    result->z=convFactoryPSingP( F*R,r->algring );
1876    p_Normalize(result->z,nacRing);
1877  }
1878#endif
1879  ntTest((number)result);
1880  return (number)result;
1881}
1882
1883
1884/*2
1885* ntNumbOfPar = 1:
1886* clears denominator         algebraic case;
1887* tries to simplify ratio    transcendental case;
1888*
1889* cancels monomials
1890* occuring in denominator
1891* and enumerator  ?          ntNumbOfPar != 1;
1892*
1893* #defines for Factory:
1894* FACTORY_GCD_TEST: do not apply built in gcd for
1895*   univariate polynomials, always use Factory
1896*/
1897//#define FACTORY_GCD_TEST
1898void ntCoefNormalize(number pp)
1899{
1900  if (pp==NULL) return;
1901  lnumber p = (lnumber)pp;
1902  number nz; // all denom. of the numerator
1903  nz=p_GetAllDenom(p->z,nacRing);
1904  BOOLEAN norm=FALSE;
1905  if (!n_IsOne(nz,nacRing))
1906  {
1907    norm=TRUE;
1908    p->z=p_Mult_nn(p->z,nz,nacRing);
1909    if (p->n==NULL)
1910    {
1911      p->n=p_NSet(nz,nacRing);
1912    }
1913    else
1914    {
1915      p->n=p_Mult_nn(p->n,nz,nacRing);
1916      n_Delete(&nz, nacRing);
1917    }
1918  }
1919  else
1920  {
1921    n_Delete(&nz, nacRing);
1922  }
1923  if (norm)
1924  {
1925    norm=FALSE;
1926    p_Normalize(p->z,nacRing);
1927    p_Normalize(p->n,nacRing);
1928  }
1929  number nn;
1930  nn=p_GetAllDenom(p->n,nacRing);
1931  if (!n_IsOne(nn,nacRing))
1932  {
1933    norm=TRUE;
1934    p->n=p_Mult_nn(p->n,nn,nacRing);
1935    p->z=p_Mult_nn(p->z,nn,nacRing);
1936    n_Delete(&nn, nacRing);
1937  }
1938  else
1939  {
1940    n_Delete(&nn, nacRing);
1941  }
1942  if (norm)
1943  {
1944    p_Normalize(p->z,nacRing);
1945    p_Normalize(p->n,nacRing);
1946  }
1947  // remove common factors in n, z:
1948  if (p->n!=NULL)
1949  {
1950    poly pp=p->z;
1951    nz=n_Copy(pGetCoeff(pp),nacRing);
1952    pIter(pp);
1953    while(pp!=NULL)
1954    {
1955      if (n_IsOne(nz,nacRing)) break;
1956      number d=n_Gcd(nz,pGetCoeff(pp),nacRing);
1957      n_Delete(&nz,nacRing); nz=d;
1958      pIter(pp);
1959    }
1960    if (!n_IsOne(nz,nacRing))
1961    {
1962      pp=p->n;
1963      nn=n_Copy(pGetCoeff(pp),nacRing);
1964      pIter(pp);
1965      while(pp!=NULL)
1966      {
1967        if (n_IsOne(nn,nacRing)) break;
1968        number d=n_Gcd(nn,pGetCoeff(pp),nacRing);
1969        n_Delete(&nn,nacRing); nn=d;
1970        pIter(pp);
1971      }
1972      number ng=n_Gcd(nz,nn,nacRing);
1973      n_Delete(&nn,nacRing);
1974      if (!n_IsOne(ng,nacRing))
1975      {
1976        number ni=n_Invers(ng,nacRing);
1977        p->z=p_Mult_nn(p->z,ni,nacRing);
1978        p->n=p_Mult_nn(p->n,ni,nacRing);
1979        p_Normalize(p->z,nacRing);
1980        p_Normalize(p->n,nacRing);
1981        n_Delete(&ni,nacRing);
1982      }
1983      n_Delete(&ng,nacRing);
1984    }
1985    n_Delete(&nz,nacRing);
1986  }
1987  if (p->n!=NULL)
1988  {
1989    if(!nacGreaterZero(pGetCoeff(p->n)))
1990    {
1991      p->z=napNeg(p->z);
1992      p->n=napNeg(p->n);
1993    }
1994
1995    if (/*(p->n!=NULL) && */
1996    (p_IsConstant(p->n,nacRing))
1997    && (n_IsOne(pGetCoeff(p->n),nacRing)))
1998    {
1999      p_Delete(&(p->n), nacRing);
2000      p->n = NULL;
2001    }
2002  }
2003}
2004
2005void ntNormalize(number &pp)
2006{
2007
2008  //ntTest(pp); // input may not be "normal"
2009  lnumber p = (lnumber)pp;
2010
2011  if (p==NULL)
2012    return;
2013  ntCoefNormalize(pp);
2014  p->s = 2;
2015  napoly x = p->z;
2016  napoly y = p->n;
2017
2018  if (y==NULL) return;
2019
2020  if ((x!=NULL) && (y!=NULL))
2021  {
2022    int i;
2023    for (i=ntNumbOfPar-1; i>=0; i--)
2024    {
2025      napoly xx=x;
2026      napoly yy=y;
2027      int m = napExpi(i, yy, xx);
2028      if (m != 0)          // in this case xx!=NULL!=yy
2029      {
2030        while (xx != NULL)
2031        {
2032          napAddExp(xx,i+1, -m);
2033          pIter(xx);
2034        }
2035        while (yy != NULL)
2036        {
2037          napAddExp(yy,i+1, -m);
2038          pIter(yy);
2039        }
2040      }
2041    }
2042  }
2043  if (p_LmIsConstant(y,nacRing)) /* i.e. => simplify to (1/c)*z / monom */
2044  {
2045    if (nacIsOne(pGetCoeff(y)))
2046    {
2047      p_LmDelete(&y,nacRing);
2048      p->n = NULL;
2049      ntTest(pp);
2050      return;
2051    }
2052    number h1 = nacInvers(pGetCoeff(y));
2053    nacNormalize(h1);
2054    napMultN(x, h1);
2055    n_Delete(&h1,nacRing);
2056    p_LmDelete(&y,nacRing);
2057    p->n = NULL;
2058    ntTest(pp);
2059    return;
2060  }
2061#ifndef FACTORY_GCD_TEST
2062  if (ntNumbOfPar == 1) /* apply built-in gcd */
2063  {
2064    napoly x1,y1;
2065    if (p_GetExp(x,1,nacRing) >= p_GetExp(y,1,nacRing))
2066    {
2067      x1 = napCopy(x);
2068      y1 = napCopy(y);
2069    }
2070    else
2071    {
2072      x1 = napCopy(y);
2073      y1 = napCopy(x);
2074    }
2075    napoly r;
2076    loop
2077    {
2078      r = ntRemainder(x1, y1);
2079      if ((r==NULL) || (pNext(r)==NULL)) break;
2080      x1 = y1;
2081      y1 = r;
2082    }
2083    if (r!=NULL)
2084    {
2085      p_Delete(&r,nacRing);
2086      p_Delete(&y1,nacRing);
2087    }
2088    else
2089    {
2090      napDivMod(x, y1, &(p->z), &r);
2091      napDivMod(y, y1, &(p->n), &r);
2092      p_Delete(&y1,nacRing);
2093    }
2094    x = p->z;
2095    y = p->n;
2096    /* collect all denoms from y and multiply x and y by it */
2097    if (ntIsChar0)
2098    {
2099      number n=napLcm(y);
2100      napMultN(x,n);
2101      napMultN(y,n);
2102      n_Delete(&n,nacRing);
2103      while(x!=NULL)
2104      {
2105        nacNormalize(pGetCoeff(x));
2106        pIter(x);
2107      }
2108      x = p->z;
2109      while(y!=NULL)
2110      {
2111        nacNormalize(pGetCoeff(y));
2112        pIter(y);
2113      }
2114      y = p->n;
2115    }
2116    if (pNext(y)==NULL)
2117    {
2118      if (nacIsOne(pGetCoeff(y)))
2119      {
2120        if (p_GetExp(y,1,nacRing)==0)
2121        {
2122          p_LmDelete(&y,nacRing);
2123          p->n = NULL;
2124        }
2125        ntTest(pp);
2126        return;
2127      }
2128    }
2129  }
2130#endif /* FACTORY_GCD_TEST */
2131#ifdef HAVE_FACTORY
2132#ifndef FACTORY_GCD_TEST
2133  else
2134#endif
2135  {
2136    napoly xx,yy;
2137    singclap_algdividecontent(x,y,xx,yy);
2138    if (xx!=NULL)
2139    {
2140      p->z=xx;
2141      p->n=yy;
2142      p_Delete(&x,nacRing);
2143      p_Delete(&y,nacRing);
2144    }
2145  }
2146#endif
2147  /* remove common factors from z and n */
2148  x=p->z;
2149  y=p->n;
2150  if(!nacGreaterZero(pGetCoeff(y)))
2151  {
2152    x=napNeg(x);
2153    y=napNeg(y);
2154  }
2155  number g=nacCopy(pGetCoeff(x));
2156  pIter(x);
2157  while (x!=NULL)
2158  {
2159    number d=nacGcd(g,pGetCoeff(x), nacRing);
2160    if(nacIsOne(d))
2161    {
2162      n_Delete(&g,nacRing);
2163      n_Delete(&d,nacRing);
2164      ntTest(pp);
2165      return;
2166    }
2167    n_Delete(&g,nacRing);
2168    g = d;
2169    pIter(x);
2170  }
2171  while (y!=NULL)
2172  {
2173    number d=nacGcd(g,pGetCoeff(y), nacRing);
2174    if(nacIsOne(d))
2175    {
2176      n_Delete(&g,nacRing);
2177      n_Delete(&d,nacRing);
2178      ntTest(pp);
2179      return;
2180    }
2181    n_Delete(&g,nacRing);
2182    g = d;
2183    pIter(y);
2184  }
2185  x=p->z;
2186  y=p->n;
2187  while (x!=NULL)
2188  {
2189    number d = nacIntDiv(pGetCoeff(x),g);
2190    napSetCoeff(x,d);
2191    pIter(x);
2192  }
2193  while (y!=NULL)
2194  {
2195    number d = nacIntDiv(pGetCoeff(y),g);
2196    napSetCoeff(y,d);
2197    pIter(y);
2198  }
2199  n_Delete(&g,nacRing);
2200  ntTest(pp);
2201}
2202
2203/*2
2204* returns in result->n 1
2205* and in     result->z the lcm(a->z,b->n)
2206*/
2207number ntLcm(number la, number lb, const ring r)
2208{
2209  lnumber result;
2210  lnumber a = (lnumber)la;
2211  lnumber b = (lnumber)lb;
2212  result = ALLOC0_LNUMBER();
2213  ntTest(la);
2214  ntTest(lb);
2215  napoly x = p_Copy(a->z, r->algring);
2216  number t = napLcm(b->z); // get all denom of b->z
2217  if (!nacIsOne(t))
2218  {
2219    number bt, rr;
2220    napoly xx=x;
2221    while (xx!=NULL)
2222    {
2223      bt = nacGcd(t, pGetCoeff(xx), r->algring);
2224      rr = nacMult(t, pGetCoeff(xx));
2225      n_Delete(&pGetCoeff(xx),r->algring);
2226      pGetCoeff(xx) = nacDiv(rr, bt);
2227      nacNormalize(pGetCoeff(xx));
2228      n_Delete(&bt,r->algring);
2229      n_Delete(&rr,r->algring);
2230      pIter(xx);
2231    }
2232  }
2233  n_Delete(&t,r->algring);
2234  result->z = x;
2235#ifdef HAVE_FACTORY
2236  if (b->n!=NULL)
2237  {
2238    result->z=singclap_alglcm(result->z,b->n);
2239    p_Delete(&x,r->algring);
2240  }
2241#endif
2242  ntTest(la);
2243  ntTest(lb);
2244  ntTest((number)result);
2245  return ((number)result);
2246}
2247
2248/*2
2249* map Z/p -> Q(a)
2250*/
2251number ntMapP0(number c)
2252{
2253  if (npIsZero(c)) return NULL;
2254  lnumber l=ALLOC_LNUMBER();
2255  l->s=2;
2256  l->z=(napoly)p_Init(nacRing);
2257  int i=(int)((long)c);
2258  if (i>((long)ntMapRing->ch>>2)) i-=(long)ntMapRing->ch;
2259  pGetCoeff(l->z)=nlInit(i, nacRing);
2260  l->n=NULL;
2261  return (number)l;
2262}
2263
2264/*2
2265* map Q -> Q(a)
2266*/
2267number ntMap00(number c)
2268{
2269  if (nlIsZero(c)) return NULL;
2270  lnumber l=ALLOC_LNUMBER();
2271  l->s=0;
2272  l->z=(napoly)p_Init(nacRing);
2273  pGetCoeff(l->z)=nlCopy(c);
2274  l->n=NULL;
2275  return (number)l;
2276}
2277
2278/*2
2279* map Z/p -> Z/p(a)
2280*/
2281number ntMapPP(number c)
2282{
2283  if (npIsZero(c)) return NULL;
2284  lnumber l=ALLOC_LNUMBER();
2285  l->s=2;
2286  l->z=(napoly)p_Init(nacRing);
2287  pGetCoeff(l->z)=c; /* omit npCopy, because npCopy is a no-op */
2288  l->n=NULL;
2289  return (number)l;
2290}
2291
2292/*2
2293* map Z/p' -> Z/p(a)
2294*/
2295number ntMapPP1(number c)
2296{
2297  if (npIsZero(c)) return NULL;
2298  int i=(int)((long)c);
2299  if (i>(long)ntMapRing->ch) i-=(long)ntMapRing->ch;
2300  number n=npInit(i,ntMapRing);
2301  if (npIsZero(n)) return NULL;
2302  lnumber l=ALLOC_LNUMBER();
2303  l->s=2;
2304  l->z=(napoly)p_Init(nacRing);
2305  pGetCoeff(l->z)=n;
2306  l->n=NULL;
2307  return (number)l;
2308}
2309
2310/*2
2311* map Q -> Z/p(a)
2312*/
2313number ntMap0P(number c)
2314{
2315  if (nlIsZero(c)) return NULL;
2316  number n=npInit(nlModP(c,npPrimeM),nacRing);
2317  if (npIsZero(n)) return NULL;
2318  npTest(n);
2319  lnumber l=ALLOC_LNUMBER();
2320  l->s=2;
2321  l->z=(napoly)p_Init(nacRing);
2322  pGetCoeff(l->z)=n;
2323  l->n=NULL;
2324  return (number)l;
2325}
2326
2327/*2
2328* map _(a) -> _(b)
2329*/
2330number ntMapQaQb(number c)
2331{
2332  if (c==NULL) return NULL;
2333  lnumber erg= ALLOC0_LNUMBER();
2334  lnumber src =(lnumber)c;
2335  erg->s=src->s;
2336  erg->z=napMap(src->z);
2337  erg->n=napMap(src->n);
2338  return (number)erg;
2339}
2340
2341nMapFunc ntSetMap(const ring src, const ring dst)
2342{
2343  ntMapRing=src;
2344  if (rField_is_Q_a(dst)) /* -> Q(a) */
2345  {
2346    if (rField_is_Q(src))
2347    {
2348      return ntMap00;   /*Q -> Q(a)*/
2349    }
2350    if (rField_is_Zp(src))
2351    {
2352      return ntMapP0;  /* Z/p -> Q(a)*/
2353    }
2354    if (rField_is_Q_a(src))
2355    {
2356      int i;
2357      ntParsToCopy=0;
2358      for(i=0;i<rPar(src);i++)
2359      {
2360        if ((i>=rPar(dst))
2361        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2362           return NULL;
2363        ntParsToCopy++;
2364      }
2365      nacMap=nacCopy;
2366      if ((ntParsToCopy==rPar(dst))&&(ntParsToCopy==rPar(src)))
2367        return ntCopy;    /* Q(a) -> Q(a) */
2368      return ntMapQaQb;   /* Q(a..) -> Q(a..) */
2369    }
2370  }
2371  /*-----------------------------------------------------*/
2372  if (rField_is_Zp_a(dst)) /* -> Z/p(a) */
2373  {
2374    if (rField_is_Q(src))
2375    {
2376      return ntMap0P;   /*Q -> Z/p(a)*/
2377    }
2378    if (rField_is_Zp(src))
2379    {
2380      if (src->ch==dst->ch)
2381      {
2382        return ntMapPP;  /* Z/p -> Z/p(a)*/
2383      }
2384      else
2385      {
2386        return ntMapPP1;  /* Z/p' -> Z/p(a)*/
2387      }
2388    }
2389    if (rField_is_Zp_a(src))
2390    {
2391      if (rChar(src)==rChar(dst))
2392      {
2393        nacMap=nacCopy;
2394      }
2395      else
2396      {
2397        nacMap = npMapP;
2398      }
2399      int i;
2400      ntParsToCopy=0;
2401      for(i=0;i<rPar(src);i++)
2402      {
2403        if ((i>=rPar(dst))
2404        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2405           return NULL;
2406        ntParsToCopy++;
2407      }
2408      if ((ntParsToCopy==rPar(dst))&&(ntParsToCopy==rPar(src))
2409      && (nacMap==nacCopy))
2410        return ntCopy;    /* Z/p(a) -> Z/p(a) */
2411      return ntMapQaQb;   /* Z/p(a),Z/p'(a) -> Z/p(b)*/
2412    }
2413  }
2414  return NULL;      /* default */
2415}
2416
2417/*2
2418* convert a napoly number into a poly
2419*/
2420poly ntPermNumber(number z, int * par_perm, int P, ring oldRing)
2421{
2422  if (z==NULL) return NULL;
2423  poly res=NULL;
2424  poly p;
2425  napoly za=((lnumber)z)->z;
2426  napoly zb=((lnumber)z)->n;
2427  nMapFunc nMap=ntSetMap(oldRing,currRing);
2428  if (currRing->parameter!=NULL)
2429    nMap=currRing->algring->cf->cfSetMap(oldRing->algring, nacRing);
2430  else
2431    nMap=currRing->cf->cfSetMap(oldRing->algring, currRing);
2432  if (nMap==NULL) return NULL; /* emergency exit only */
2433  do
2434  {
2435    p = pInit();
2436    pNext(p)=NULL;
2437    nNew(&pGetCoeff(p));
2438    int i;
2439    for(i=pVariables;i;i--)
2440       pSetExp(p,i, 0);
2441    if (rRing_has_Comp(currRing)) pSetComp(p, 0);
2442    napoly pa=NULL;
2443    lnumber pan;
2444    if (currRing->parameter!=NULL)
2445    {
2446      assume(oldRing->algring!=NULL);
2447      pGetCoeff(p)=(number)ALLOC0_LNUMBER();
2448      pan=(lnumber)pGetCoeff(p);
2449      pan->s=2;
2450      pan->z=napInitz(nMap(pGetCoeff(za)));
2451      pa=pan->z;
2452    }
2453    else
2454    {
2455      pGetCoeff(p)=nMap(pGetCoeff(za));
2456    }
2457    for(i=0;i<P;i++)
2458    {
2459      if(napGetExpFrom(za,i+1,oldRing)!=0)
2460      {
2461        if(par_perm==NULL)
2462        {
2463          if ((rPar(currRing)>=i) && (pa!=NULL))
2464          {
2465            napSetExp(pa,i+1,napGetExpFrom(za,i+1,oldRing));
2466            p_Setm(pa,nacRing);
2467          }
2468          else
2469          {
2470            pDelete(&p);
2471            break;
2472          }
2473        }
2474        else if(par_perm[i]>0)
2475          pSetExp(p,par_perm[i],napGetExpFrom(za,i+1,oldRing));
2476        else if((par_perm[i]<0)&&(pa!=NULL))
2477        {
2478          napSetExp(pa,-par_perm[i], napGetExpFrom(za,i+1,oldRing));
2479          p_Setm(pa,nacRing);
2480        }
2481        else
2482        {
2483          pDelete(&p);
2484          break;
2485        }
2486      }
2487    }
2488    if (p!=NULL)
2489    {
2490      pSetm(p);
2491      if (zb!=NULL)
2492      {
2493        if  (currRing->P>0)
2494        {
2495          pan->n=napPerm(zb,par_perm,oldRing,nMap);
2496          if(pan->n==NULL) /* error in mapping or mapping to variable */
2497            pDelete(&p);
2498        }
2499        else
2500          pDelete(&p);
2501      }
2502      pTest(p);
2503      res=pAdd(res,p);
2504    }
2505    pIter(za);
2506  }
2507  while (za!=NULL);
2508  pTest(res);
2509  return res;
2510}
2511
2512number   ntGetDenom(number &n, const ring r)
2513{
2514  lnumber x=(lnumber)n;
2515  if (x->n!=NULL)
2516  {
2517    lnumber rr=ALLOC0_LNUMBER();
2518    rr->z=p_Copy(x->n,r->algring);
2519    rr->s = 2;
2520    return (number)rr;
2521  }
2522  return n_Init(1,r);
2523}
2524
2525number   ntGetNumerator(number &n, const ring r)
2526{
2527  lnumber x=(lnumber)n;
2528  lnumber rr=ALLOC0_LNUMBER();
2529  rr->z=p_Copy(x->z,r->algring);
2530  rr->s = 2;
2531  return (number)rr;
2532}
2533
2534#ifdef LDEBUG
2535BOOLEAN ntDBTest(number a, const char *f,const int l)
2536{
2537  lnumber x=(lnumber)a;
2538  if (x == NULL)
2539    return TRUE;
2540  #ifdef LDEBUG
2541  omCheckAddrSize(a, sizeof(slnumber));
2542  #endif
2543  napoly p = x->z;
2544  if (p==NULL)
2545  {
2546    Print("0/* in %s:%d\n",f,l);
2547    return FALSE;
2548  }
2549  while(p!=NULL)
2550  {
2551    if (( ntIsChar0  && nlIsZero(pGetCoeff(p)))
2552    || ((!ntIsChar0) && npIsZero(pGetCoeff(p))))
2553    {
2554      Print("coeff 0 in %s:%d\n",f,l);
2555      return FALSE;
2556    }
2557    if (ntIsChar0 && !(nlDBTest(pGetCoeff(p),f,l)))
2558      return FALSE;
2559    pIter(p);
2560  }
2561  p = x->n;
2562  while(p!=NULL)
2563  {
2564    if (ntIsChar0 && !(nlDBTest(pGetCoeff(p),f,l)))
2565      return FALSE;
2566    pIter(p);
2567  }
2568  return TRUE;
2569}
2570#endif
2571#endif
Note: See TracBrowser for help on using the repository browser.