source: git/kernel/longtrans.cc @ 152d55

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