source: git/kernel/longtrans.cc @ cdec33

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