source: git/kernel/longtrans.cc @ 8eea06

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