source: git/kernel/longtrans.cc @ 2d3daa

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