source: git/kernel/longtrans.cc @ f115489

spielwiese
Last change on this file since f115489 was f115489, checked in by Oleksandr Motsak <motsak@…>, 13 years ago
ADD: bugtest for ntIntDiv & p_Content using syzextra From: Oleksandr Motsak <motsak@mathematik.uni-kl.de> git-svn-id: file:///usr/local/Singular/svn/trunk@14091 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 50.6 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{
[f115489]1374  ntTest(la);
1375  ntTest(lb);
[b46956]1376  lnumber res;
1377  lnumber a = (lnumber)la;
1378  lnumber b = (lnumber)lb;
1379  if (a==NULL)
1380  {
1381    return NULL;
1382  }
1383  if (b==NULL)
1384  {
1385    WerrorS(nDivBy0);
1386    return NULL;
1387  }
[f115489]1388#ifdef LDEBUG
1389  omCheckAddrSize(a,sizeof(snumber));
1390  omCheckAddrSize(b,sizeof(snumber));
1391#endif
[b46956]1392  assume(a->z!=NULL && b->z!=NULL);
1393  assume(a->n==NULL && b->n==NULL);
1394  res = (lnumber)omAllocBin(rnumber_bin);
[661c214]1395  res->z = napCopy(a->z);
1396  res->n = napCopy(b->z);
[b46956]1397  res->s = 0;
1398  number nres=(number)res;
1399  ntNormalize(nres);
1400
[661c214]1401  //napDelete(&res->n);
[b46956]1402  ntTest(nres);
1403  return nres;
1404}
1405
1406/*2
1407*  division; lo:= la / lb
1408*/
1409number ntDiv(number la, number lb)
1410{
1411  lnumber lo;
1412  lnumber a = (lnumber)la;
1413  lnumber b = (lnumber)lb;
1414  napoly x;
1415
1416  if (a==NULL)
1417    return NULL;
1418
1419  if (b==NULL)
1420  {
1421    WerrorS(nDivBy0);
1422    return NULL;
1423  }
1424  #ifdef LDEBUG
1425  omCheckAddrSize(a,sizeof(snumber));
1426  omCheckAddrSize(b,sizeof(snumber));
1427  #endif
1428  lo = (lnumber)omAllocBin(rnumber_bin);
1429  if (b->n!=NULL)
[661c214]1430    lo->z = pp_Mult_qq(a->z, b->n,nacRing);
[b46956]1431  else
[661c214]1432    lo->z = napCopy(a->z);
[b46956]1433  if (a->n!=NULL)
[661c214]1434    x = pp_Mult_qq(b->z, a->n, nacRing);
[b46956]1435  else
[661c214]1436    x = napCopy(b->z);
[21972b]1437  if ((p_LmIsConstant(x,nacRing)) && nacIsOne(pGetCoeff(x)))
[661c214]1438    p_Delete(&x,nacRing);
[b46956]1439  lo->n = x;
1440  lo->s = 0;
1441  if (lo->n!=NULL)
1442  {
1443    number luu=(number)lo;
[661c214]1444     //if (p_IsConstant(lo->n,nacRing)) ntCoefNormalize(luu);
[b46956]1445     //else
1446                         ntNormalize(luu);
1447    lo=(lnumber)luu;
1448  }
1449  //else lo->s=2;
1450  ntTest((number)lo);
1451  return (number)lo;
1452}
1453
1454/*2
1455*  za:= - za, inplace
1456*/
1457number ntNeg(number za)
1458{
1459  if (za!=NULL)
1460  {
1461    lnumber e = (lnumber)za;
1462    ntTest(za);
1463    e->z = napNeg(e->z);
1464  }
1465  return za;
1466}
1467
1468/*2
1469* 1/a
1470*/
1471number ntInvers(number a)
1472{
1473  lnumber lo;
1474  lnumber b = (lnumber)a;
1475  napoly x;
1476
1477  if (b==NULL)
1478  {
1479    WerrorS(nDivBy0);
1480    return NULL;
1481  }
1482  #ifdef LDEBUG
1483  omCheckAddrSize(b,sizeof(snumber));
1484  #endif
1485  lo = (lnumber)omAlloc0Bin(rnumber_bin);
1486  lo->s = b->s;
1487  if (b->n!=NULL)
[661c214]1488    lo->z = napCopy(b->n);
[b46956]1489  else
[661c214]1490    lo->z = p_ISet(1,nacRing);
[b46956]1491  x = b->z;
[21972b]1492  if ((!p_LmIsConstant(x,nacRing)) || !nacIsOne(pGetCoeff(x)))
[661c214]1493    x = napCopy(x);
[b46956]1494  else
1495  {
1496    lo->n = NULL;
1497    ntTest((number)lo);
1498    return (number)lo;
1499  }
1500  lo->n = x;
1501  if (lo->n!=NULL)
1502  {
1503     number luu=(number)lo;
[661c214]1504     //if (p_IsConstant(lo->n,nacRing)) ntCoefNormalize(luu);
[b46956]1505     //else
1506                           ntNormalize(luu);
1507     lo=(lnumber)luu;
1508  }
1509  ntTest((number)lo);
1510  return (number)lo;
1511}
1512
1513
1514BOOLEAN ntIsZero(number za)
1515{
1516  lnumber zb = (lnumber)za;
1517  ntTest(za);
1518#ifdef LDEBUG
1519  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(2)");
1520#endif
1521  return (zb==NULL);
1522}
1523
1524
1525BOOLEAN ntGreaterZero(number za)
1526{
1527  lnumber zb = (lnumber)za;
1528#ifdef LDEBUG
1529  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(3)");
1530#endif
1531  ntTest(za);
1532  if (zb!=NULL)
1533  {
[21972b]1534    return (nacGreaterZero(pGetCoeff(zb->z))||(!p_LmIsConstant(zb->z,nacRing)));
[b46956]1535  }
1536  /* else */ return FALSE;
1537}
1538
1539
1540/*2
1541* a = b ?
1542*/
1543BOOLEAN ntEqual (number a, number b)
1544{
1545  if(a==b) return TRUE;
1546  if((a==NULL)&&(b!=NULL)) return FALSE;
1547  if((b==NULL)&&(a!=NULL)) return FALSE;
1548
1549  lnumber aa=(lnumber)a;
1550  lnumber bb=(lnumber)b;
1551
1552  int an_deg=0;
1553  if(aa->n!=NULL)
[661c214]1554    an_deg=napDeg(aa->n);
[b46956]1555  int bn_deg=0;
1556  if(bb->n!=NULL)
[661c214]1557    bn_deg=napDeg(bb->n);
1558  if(an_deg+napDeg(bb->z)!=bn_deg+napDeg(aa->z))
[b46956]1559    return FALSE;
1560#if 0
1561  ntNormalize(a);
1562  aa=(lnumber)a;
1563  ntNormalize(b);
1564  bb=(lnumber)b;
1565  if((aa->n==NULL)&&(bb->n!=NULL)) return FALSE;
1566  if((bb->n==NULL)&&(aa->n!=NULL)) return FALSE;
[661c214]1567  if(napComp(aa->z,bb->z)!=0) return FALSE;
1568  if((aa->n!=NULL) && (napComp(aa->n,bb->n))) return FALSE;
[b46956]1569#endif
1570  number h = ntSub(a, b);
1571  BOOLEAN bo = ntIsZero(h);
1572  ntDelete(&h,currRing);
1573  return bo;
1574}
1575
1576
1577BOOLEAN ntGreater (number a, number b)
1578{
1579  if (ntIsZero(a))
1580    return FALSE;
1581  if (ntIsZero(b))
1582    return TRUE; /* a!= 0)*/
[661c214]1583  return napDeg(((lnumber)a)->z)>napDeg(((lnumber)b)->z);
[b46956]1584}
1585
1586/*2
1587* reads a number
1588*/
1589const char  *ntRead(const char *s, number *p)
1590{
1591  napoly x;
1592  lnumber a;
[661c214]1593  s = napRead(s, &x);
[b46956]1594  if (x==NULL)
1595  {
1596    *p = NULL;
1597    return s;
1598  }
1599  *p = (number)omAlloc0Bin(rnumber_bin);
1600  a = (lnumber)*p;
[d0450f]1601  a->z = x;
[b46956]1602  if(a->z==NULL)
1603  {
1604    omFreeBin((ADDRESS)*p, rnumber_bin);
1605    *p=NULL;
1606  }
1607  else
1608  {
1609    a->n = NULL;
1610    a->s = 0;
1611    ntTest(*p);
1612  }
1613  return s;
1614}
1615
1616/*2
1617* tries to convert a number to a name
1618*/
1619char * ntName(number n)
1620{
1621  lnumber ph = (lnumber)n;
1622  if (ph==NULL)
1623    return NULL;
1624  int i;
[661c214]1625  char *s=(char *)omAlloc(4* ntNumbOfPar);
[b46956]1626  char *t=(char *)omAlloc(8);
1627  s[0]='\0';
[661c214]1628  for (i = 0; i <= ntNumbOfPar - 1; i++)
[b46956]1629  {
[661c214]1630    int e=p_GetExp(ph->z,i+1,nacRing);
[b46956]1631    if (e > 0)
1632    {
1633      if (e >1)
1634      {
[21972b]1635        sprintf(t,"%s%d",ntParNames[i],e);
[b46956]1636        strcat(s,t);
1637      }
1638      else
1639      {
[21972b]1640        strcat(s,ntParNames[i]);
[b46956]1641      }
1642    }
1643  }
1644  omFreeSize((ADDRESS)t,8);
1645  if (s[0]=='\0')
1646  {
1647    omFree((ADDRESS)s);
1648    return NULL;
1649  }
1650  return s;
1651}
1652
1653/*2
1654*  writes a number
1655*/
1656void ntWrite(number &phn, const ring r)
1657{
1658  lnumber ph = (lnumber)phn;
1659  if (ph==NULL)
1660    StringAppendS("0");
1661  else
1662  {
1663    phn->s = 0;
1664    BOOLEAN has_denom=(ph->n!=NULL);
[661c214]1665    napWrite(ph->z,has_denom/*(ph->n!=NULL)*/,r);
[b46956]1666    if (has_denom/*(ph->n!=NULL)*/)
1667    {
1668      StringAppendS("/");
[661c214]1669      napWrite(ph->n,TRUE,r);
[b46956]1670    }
1671  }
1672}
1673
1674/*2
1675* za == 1 ?
1676*/
1677BOOLEAN ntIsOne(number za)
1678{
1679  lnumber a = (lnumber)za;
1680  napoly x, y;
1681  number t;
1682  if (a==NULL) return FALSE;
1683#ifdef LDEBUG
1684  omCheckAddrSize(a,sizeof(snumber));
1685  if (a->z==NULL)
1686  {
1687    WerrorS("internal zero error(4)");
1688    return FALSE;
1689  }
1690#endif
1691  if (a->n==NULL)
1692  {
[661c214]1693    if (p_LmIsConstant(a->z,nacRing))
[b46956]1694    {
[21972b]1695      return nacIsOne(pGetCoeff(a->z));
[b46956]1696    }
1697    else                 return FALSE;
1698  }
1699#if 0
1700  x = a->z;
1701  y = a->n;
1702  do
1703  {
[661c214]1704    if (napComp(x, y))
[b46956]1705      return FALSE;
1706    else
1707    {
[21972b]1708      t = nacSub(pGetCoeff(x), pGetCoeff(y));
1709      if (!nacIsZero(t))
[b46956]1710      {
[661c214]1711        n_Delete(&t,nacRing);
[b46956]1712        return FALSE;
1713      }
1714      else
[661c214]1715        n_Delete(&t,nacRing);
[b46956]1716    }
1717    pIter(x);
1718    pIter(y);
1719  }
1720  while ((x!=NULL) && (y!=NULL));
1721  if ((x!=NULL) || (y!=NULL)) return FALSE;
[661c214]1722  p_Delete(&a->z,nacRing);
1723  p_Delete(&a->n,nacRing);
1724  a->z = p_ISet(1,nacRing);
[b46956]1725  a->n = NULL;
1726  return TRUE;
1727#else
1728  return FALSE;
1729#endif
1730}
1731
1732/*2
1733* za == -1 ?
1734*/
1735BOOLEAN ntIsMOne(number za)
1736{
1737  lnumber a = (lnumber)za;
1738  napoly x, y;
1739  number t;
1740  if (a==NULL) return FALSE;
1741#ifdef LDEBUG
1742  omCheckAddrSize(a,sizeof(snumber));
1743  if (a->z==NULL)
1744  {
1745    WerrorS("internal zero error(5)");
1746    return FALSE;
1747  }
1748#endif
1749  if (a->n==NULL)
1750  {
[0c2088]1751    if (p_LmIsConstant(a->z,nacRing)) return n_IsMOne(pGetCoeff(a->z),nacRing);
[b46956]1752    /*else                   return FALSE;*/
1753  }
1754  return FALSE;
1755}
1756
1757/*2
1758* returns the i-th power of p (i>=0)
1759*/
1760void ntPower(number p, int i, number *rc)
1761{
1762  number x;
1763  *rc = ntInit(1,currRing);
1764  for (; i > 0; i--)
1765  {
1766    x = ntMult(*rc, p);
1767    ntDelete(rc,currRing);
1768    *rc = x;
1769  }
1770}
1771
1772/*2
1773* result =gcd(a,b)
1774*/
1775number ntGcd(number a, number b, const ring r)
1776{
1777  if (a==NULL)  return ntCopy(b);
1778  if (b==NULL)  return ntCopy(a);
1779
1780  lnumber x, y;
1781  lnumber result = (lnumber)omAlloc0Bin(rnumber_bin);
1782
1783  x = (lnumber)a;
1784  y = (lnumber)b;
1785#ifndef HAVE_FACTORY
[661c214]1786  result->z = napGcd(x->z, y->z); // change from napGcd0
[b46956]1787#else
1788  int c=ABS(nGetChar());
1789  if (c==1) c=0;
1790  setCharacteristic( c );
1791
[661c214]1792  napoly rz=napGcd(x->z, y->z);
[b46956]1793  CanonicalForm F, G, R;
1794  R=convSingPFactoryP(rz,r->algring);
[661c214]1795  p_Normalize(x->z,nacRing);
[b46956]1796  F=convSingPFactoryP(x->z,r->algring)/R;
[661c214]1797  p_Normalize(y->z,nacRing);
[b46956]1798  G=convSingPFactoryP(y->z,r->algring)/R;
1799  F = gcd( F, G );
1800  if (F.isOne())
1801    result->z= rz;
1802  else
1803  {
1804    p_Delete(&rz,r->algring);
1805    result->z=convFactoryPSingP( F*R,r->algring );
[661c214]1806    p_Normalize(result->z,nacRing);
[b46956]1807  }
1808#endif
1809  ntTest((number)result);
1810  return (number)result;
1811}
1812
1813
1814/*2
[661c214]1815* ntNumbOfPar = 1:
[b46956]1816* clears denominator         algebraic case;
1817* tries to simplify ratio    transcendental case;
1818*
1819* cancels monomials
1820* occuring in denominator
[661c214]1821* and enumerator  ?          ntNumbOfPar != 1;
[b46956]1822*
1823* #defines for Factory:
1824* FACTORY_GCD_TEST: do not apply built in gcd for
1825*   univariate polynomials, always use Factory
1826*/
1827//#define FACTORY_GCD_TEST
1828void ntCoefNormalize(number pp)
1829{
1830  if (pp==NULL) return;
1831  lnumber p = (lnumber)pp;
1832  number nz; // all denom. of the numerator
[661c214]1833  nz=p_GetAllDenom(p->z,nacRing);
[b46956]1834  BOOLEAN norm=FALSE;
[661c214]1835  if (!n_IsOne(nz,nacRing))
[b46956]1836  {
1837    norm=TRUE;
[661c214]1838    p->z=p_Mult_nn(p->z,nz,nacRing);
[b46956]1839    if (p->n==NULL)
1840    {
[661c214]1841      p->n=p_NSet(nz,nacRing);
[b46956]1842    }
1843    else
1844    {
[661c214]1845      p->n=p_Mult_nn(p->n,nz,nacRing);
1846      n_Delete(&nz, nacRing);
[b46956]1847    }
1848  }
1849  else
1850  {
[661c214]1851    n_Delete(&nz, nacRing);
[b46956]1852  }
1853  if (norm)
1854  {
1855    norm=FALSE;
[661c214]1856    p_Normalize(p->z,nacRing);
1857    p_Normalize(p->n,nacRing);
[b46956]1858  }
1859  number nn;
[661c214]1860  nn=p_GetAllDenom(p->n,nacRing);
1861  if (!n_IsOne(nn,nacRing))
[b46956]1862  {
1863    norm=TRUE;
[661c214]1864    p->n=p_Mult_nn(p->n,nn,nacRing);
1865    p->z=p_Mult_nn(p->z,nn,nacRing);
1866    n_Delete(&nn, nacRing);
[b46956]1867  }
1868  else
1869  {
[661c214]1870    n_Delete(&nn, nacRing);
[b46956]1871  }
1872  if (norm)
1873  {
[661c214]1874    p_Normalize(p->z,nacRing);
1875    p_Normalize(p->n,nacRing);
[b46956]1876  }
1877  // remove common factors in n, z:
1878  if (p->n!=NULL)
1879  {
1880    poly pp=p->z;
[661c214]1881    nz=n_Copy(pGetCoeff(pp),nacRing);
[b46956]1882    pIter(pp);
1883    while(pp!=NULL)
1884    {
[661c214]1885      if (n_IsOne(nz,nacRing)) break;
1886      number d=n_Gcd(nz,pGetCoeff(pp),nacRing);
1887      n_Delete(&nz,nacRing); nz=d;
[b46956]1888      pIter(pp);
1889    }
[661c214]1890    if (!n_IsOne(nz,nacRing))
[b46956]1891    {
1892      pp=p->n;
[661c214]1893      nn=n_Copy(pGetCoeff(pp),nacRing);
[b46956]1894      pIter(pp);
1895      while(pp!=NULL)
1896      {
[661c214]1897        if (n_IsOne(nn,nacRing)) break;
1898        number d=n_Gcd(nn,pGetCoeff(pp),nacRing);
1899        n_Delete(&nn,nacRing); nn=d;
[b46956]1900        pIter(pp);
1901      }
[661c214]1902      number ng=n_Gcd(nz,nn,nacRing);
1903      n_Delete(&nn,nacRing);
1904      if (!n_IsOne(ng,nacRing))
[b46956]1905      {
[661c214]1906        number ni=n_Invers(ng,nacRing);
1907        p->z=p_Mult_nn(p->z,ni,nacRing);
1908        p->n=p_Mult_nn(p->n,ni,nacRing);
1909        p_Normalize(p->z,nacRing);
1910        p_Normalize(p->n,nacRing);
1911        n_Delete(&ni,nacRing);
[b46956]1912      }
[661c214]1913      n_Delete(&ng,nacRing);
[b46956]1914    }
[661c214]1915    n_Delete(&nz,nacRing);
[b46956]1916  }
1917  if (p->n!=NULL)
1918  {
[21972b]1919    if(!nacGreaterZero(pGetCoeff(p->n)))
[b46956]1920    {
1921      p->z=napNeg(p->z);
1922      p->n=napNeg(p->n);
1923    }
1924
1925    if (/*(p->n!=NULL) && */
[661c214]1926    (p_IsConstant(p->n,nacRing))
1927    && (n_IsOne(pGetCoeff(p->n),nacRing)))
[b46956]1928    {
[661c214]1929      p_Delete(&(p->n), nacRing);
[b46956]1930      p->n = NULL;
1931    }
1932  }
1933}
1934
1935void ntNormalize(number &pp)
1936{
1937
1938  //ntTest(pp); // input may not be "normal"
1939  lnumber p = (lnumber)pp;
1940
1941  if (p==NULL)
1942    return;
1943  ntCoefNormalize(pp);
1944  p->s = 2;
1945  napoly x = p->z;
1946  napoly y = p->n;
1947
1948  BOOLEAN norm=FALSE;
1949
1950  if (y==NULL) return;
1951
1952  if ((x!=NULL) && (y!=NULL))
1953  {
1954    int i;
[661c214]1955    for (i=ntNumbOfPar-1; i>=0; i--)
[b46956]1956    {
1957      napoly xx=x;
1958      napoly yy=y;
[661c214]1959      int m = napExpi(i, yy, xx);
[b46956]1960      if (m != 0)          // in this case xx!=NULL!=yy
1961      {
1962        while (xx != NULL)
1963        {
1964          napAddExp(xx,i+1, -m);
1965          pIter(xx);
1966        }
1967        while (yy != NULL)
1968        {
1969          napAddExp(yy,i+1, -m);
1970          pIter(yy);
1971        }
1972      }
1973    }
1974  }
[661c214]1975  if (p_LmIsConstant(y,nacRing)) /* i.e. => simplify to (1/c)*z / monom */
[b46956]1976  {
[21972b]1977    if (nacIsOne(pGetCoeff(y)))
[b46956]1978    {
[661c214]1979      p_LmDelete(&y,nacRing);
[b46956]1980      p->n = NULL;
1981      ntTest(pp);
1982      return;
1983    }
[21972b]1984    number h1 = nacInvers(pGetCoeff(y));
1985    nacNormalize(h1);
[661c214]1986    napMultN(x, h1);
1987    n_Delete(&h1,nacRing);
1988    p_LmDelete(&y,nacRing);
[b46956]1989    p->n = NULL;
1990    ntTest(pp);
1991    return;
1992  }
1993#ifndef FACTORY_GCD_TEST
[661c214]1994  if (ntNumbOfPar == 1) /* apply built-in gcd */
[b46956]1995  {
1996    napoly x1,y1;
[661c214]1997    if (p_GetExp(x,1,nacRing) >= p_GetExp(y,1,nacRing))
[b46956]1998    {
[661c214]1999      x1 = napCopy(x);
2000      y1 = napCopy(y);
[b46956]2001    }
2002    else
2003    {
[661c214]2004      x1 = napCopy(y);
2005      y1 = napCopy(x);
[b46956]2006    }
2007    napoly r;
2008    loop
2009    {
[661c214]2010      r = ntRemainder(x1, y1);
[b46956]2011      if ((r==NULL) || (pNext(r)==NULL)) break;
2012      x1 = y1;
2013      y1 = r;
2014    }
2015    if (r!=NULL)
2016    {
[661c214]2017      p_Delete(&r,nacRing);
2018      p_Delete(&y1,nacRing);
[b46956]2019    }
2020    else
2021    {
[661c214]2022      napDivMod(x, y1, &(p->z), &r);
2023      napDivMod(y, y1, &(p->n), &r);
2024      p_Delete(&y1,nacRing);
[b46956]2025    }
2026    x = p->z;
2027    y = p->n;
2028    /* collect all denoms from y and multiply x and y by it */
2029    if (ntIsChar0)
2030    {
[661c214]2031      number n=napLcm(y);
2032      napMultN(x,n);
2033      napMultN(y,n);
2034      n_Delete(&n,nacRing);
[b46956]2035      while(x!=NULL)
2036      {
[21972b]2037        nacNormalize(pGetCoeff(x));
[b46956]2038        pIter(x);
2039      }
2040      x = p->z;
2041      while(y!=NULL)
2042      {
[21972b]2043        nacNormalize(pGetCoeff(y));
[b46956]2044        pIter(y);
2045      }
2046      y = p->n;
2047    }
2048    if (pNext(y)==NULL)
2049    {
[21972b]2050      if (nacIsOne(pGetCoeff(y)))
[b46956]2051      {
[661c214]2052        if (p_GetExp(y,1,nacRing)==0)
[b46956]2053        {
[661c214]2054          p_LmDelete(&y,nacRing);
[b46956]2055          p->n = NULL;
2056        }
2057        ntTest(pp);
2058        return;
2059      }
2060    }
2061  }
2062#endif /* FACTORY_GCD_TEST */
2063#ifdef HAVE_FACTORY
2064#ifndef FACTORY_GCD_TEST
2065  else
2066#endif
2067  {
2068    napoly xx,yy;
2069    singclap_algdividecontent(x,y,xx,yy);
2070    if (xx!=NULL)
2071    {
2072      p->z=xx;
2073      p->n=yy;
[661c214]2074      p_Delete(&x,nacRing);
2075      p_Delete(&y,nacRing);
[b46956]2076    }
2077  }
2078#endif
2079  /* remove common factors from z and n */
2080  x=p->z;
2081  y=p->n;
[21972b]2082  if(!nacGreaterZero(pGetCoeff(y)))
[b46956]2083  {
2084    x=napNeg(x);
2085    y=napNeg(y);
2086  }
[21972b]2087  number g=nacCopy(pGetCoeff(x));
[b46956]2088  pIter(x);
2089  while (x!=NULL)
2090  {
[21972b]2091    number d=nacGcd(g,pGetCoeff(x), nacRing);
2092    if(nacIsOne(d))
[b46956]2093    {
[661c214]2094      n_Delete(&g,nacRing);
2095      n_Delete(&d,nacRing);
[b46956]2096      ntTest(pp);
2097      return;
2098    }
[661c214]2099    n_Delete(&g,nacRing);
[b46956]2100    g = d;
2101    pIter(x);
2102  }
2103  while (y!=NULL)
2104  {
[21972b]2105    number d=nacGcd(g,pGetCoeff(y), nacRing);
2106    if(nacIsOne(d))
[b46956]2107    {
[661c214]2108      n_Delete(&g,nacRing);
2109      n_Delete(&d,nacRing);
[b46956]2110      ntTest(pp);
2111      return;
2112    }
[661c214]2113    n_Delete(&g,nacRing);
[b46956]2114    g = d;
2115    pIter(y);
2116  }
2117  x=p->z;
2118  y=p->n;
2119  while (x!=NULL)
2120  {
[21972b]2121    number d = nacIntDiv(pGetCoeff(x),g);
[661c214]2122    napSetCoeff(x,d);
[b46956]2123    pIter(x);
2124  }
2125  while (y!=NULL)
2126  {
[21972b]2127    number d = nacIntDiv(pGetCoeff(y),g);
[661c214]2128    napSetCoeff(y,d);
[b46956]2129    pIter(y);
2130  }
[661c214]2131  n_Delete(&g,nacRing);
[b46956]2132  ntTest(pp);
2133}
2134
2135/*2
2136* returns in result->n 1
2137* and in     result->z the lcm(a->z,b->n)
2138*/
2139number ntLcm(number la, number lb, const ring r)
2140{
2141  lnumber result;
2142  lnumber a = (lnumber)la;
2143  lnumber b = (lnumber)lb;
2144  result = (lnumber)omAlloc0Bin(rnumber_bin);
2145  ntTest(la);
2146  ntTest(lb);
2147  napoly x = p_Copy(a->z, r->algring);
[661c214]2148  number t = napLcm(b->z); // get all denom of b->z
[21972b]2149  if (!nacIsOne(t))
[b46956]2150  {
2151    number bt, rr;
2152    napoly xx=x;
2153    while (xx!=NULL)
2154    {
[21972b]2155      bt = nacGcd(t, pGetCoeff(xx), r->algring);
2156      rr = nacMult(t, pGetCoeff(xx));
[b46956]2157      n_Delete(&pGetCoeff(xx),r->algring);
[21972b]2158      pGetCoeff(xx) = nacDiv(rr, bt);
2159      nacNormalize(pGetCoeff(xx));
[b46956]2160      n_Delete(&bt,r->algring);
2161      n_Delete(&rr,r->algring);
2162      pIter(xx);
2163    }
2164  }
2165  n_Delete(&t,r->algring);
2166  result->z = x;
2167#ifdef HAVE_FACTORY
2168  if (b->n!=NULL)
2169  {
2170    result->z=singclap_alglcm(result->z,b->n);
2171    p_Delete(&x,r->algring);
2172  }
2173#endif
2174  ntTest(la);
2175  ntTest(lb);
2176  ntTest((number)result);
2177  return ((number)result);
2178}
2179
2180/*2
2181* map Z/p -> Q(a)
2182*/
2183number ntMapP0(number c)
2184{
2185  if (npIsZero(c)) return NULL;
2186  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2187  l->s=2;
[661c214]2188  l->z=(napoly)p_Init(nacRing);
[b46956]2189  int i=(int)((long)c);
2190  if (i>((long)ntMapRing->ch>>2)) i-=(long)ntMapRing->ch;
[661c214]2191  pGetCoeff(l->z)=nlInit(i, nacRing);
[b46956]2192  l->n=NULL;
2193  return (number)l;
2194}
2195
2196/*2
2197* map Q -> Q(a)
2198*/
2199number ntMap00(number c)
2200{
2201  if (nlIsZero(c)) return NULL;
2202  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2203  l->s=0;
[661c214]2204  l->z=(napoly)p_Init(nacRing);
[b46956]2205  pGetCoeff(l->z)=nlCopy(c);
2206  l->n=NULL;
2207  return (number)l;
2208}
2209
2210/*2
2211* map Z/p -> Z/p(a)
2212*/
2213number ntMapPP(number c)
2214{
2215  if (npIsZero(c)) return NULL;
2216  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2217  l->s=2;
[661c214]2218  l->z=(napoly)p_Init(nacRing);
[b46956]2219  pGetCoeff(l->z)=c; /* omit npCopy, because npCopy is a no-op */
2220  l->n=NULL;
2221  return (number)l;
2222}
2223
2224/*2
2225* map Z/p' -> Z/p(a)
2226*/
2227number ntMapPP1(number c)
2228{
2229  if (npIsZero(c)) return NULL;
2230  int i=(int)((long)c);
2231  if (i>(long)ntMapRing->ch) i-=(long)ntMapRing->ch;
2232  number n=npInit(i,ntMapRing);
2233  if (npIsZero(n)) return NULL;
2234  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2235  l->s=2;
[661c214]2236  l->z=(napoly)p_Init(nacRing);
[b46956]2237  pGetCoeff(l->z)=n;
2238  l->n=NULL;
2239  return (number)l;
2240}
2241
2242/*2
2243* map Q -> Z/p(a)
2244*/
2245number ntMap0P(number c)
2246{
2247  if (nlIsZero(c)) return NULL;
[661c214]2248  number n=npInit(nlModP(c,npPrimeM),nacRing);
[b46956]2249  if (npIsZero(n)) return NULL;
2250  npTest(n);
2251  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2252  l->s=2;
[661c214]2253  l->z=(napoly)p_Init(nacRing);
[b46956]2254  pGetCoeff(l->z)=n;
2255  l->n=NULL;
2256  return (number)l;
2257}
2258
2259/*2
2260* map _(a) -> _(b)
2261*/
2262number ntMapQaQb(number c)
2263{
2264  if (c==NULL) return NULL;
2265  lnumber erg= (lnumber)omAlloc0Bin(rnumber_bin);
2266  lnumber src =(lnumber)c;
2267  erg->s=src->s;
[661c214]2268  erg->z=napMap(src->z);
2269  erg->n=napMap(src->n);
[b46956]2270  return (number)erg;
2271}
2272
2273nMapFunc ntSetMap(const ring src, const ring dst)
2274{
2275  ntMapRing=src;
2276  if (rField_is_Q_a(dst)) /* -> Q(a) */
2277  {
2278    if (rField_is_Q(src))
2279    {
2280      return ntMap00;   /*Q -> Q(a)*/
2281    }
2282    if (rField_is_Zp(src))
2283    {
2284      return ntMapP0;  /* Z/p -> Q(a)*/
2285    }
2286    if (rField_is_Q_a(src))
2287    {
2288      int i;
2289      ntParsToCopy=0;
2290      for(i=0;i<rPar(src);i++)
2291      {
2292        if ((i>=rPar(dst))
2293        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2294           return NULL;
2295        ntParsToCopy++;
2296      }
[21972b]2297      nacMap=nacCopy;
[b46956]2298      if ((ntParsToCopy==rPar(dst))&&(ntParsToCopy==rPar(src)))
2299        return ntCopy;    /* Q(a) -> Q(a) */
2300      return ntMapQaQb;   /* Q(a..) -> Q(a..) */
2301    }
2302  }
2303  /*-----------------------------------------------------*/
2304  if (rField_is_Zp_a(dst)) /* -> Z/p(a) */
2305  {
2306    if (rField_is_Q(src))
2307    {
2308      return ntMap0P;   /*Q -> Z/p(a)*/
2309    }
2310    if (rField_is_Zp(src))
2311    {
2312      if (src->ch==dst->ch)
2313      {
2314        return ntMapPP;  /* Z/p -> Z/p(a)*/
2315      }
2316      else
2317      {
2318        return ntMapPP1;  /* Z/p' -> Z/p(a)*/
2319      }
2320    }
2321    if (rField_is_Zp_a(src))
2322    {
2323      if (rChar(src)==rChar(dst))
2324      {
[21972b]2325        nacMap=nacCopy;
[b46956]2326      }
2327      else
2328      {
[21972b]2329        nacMap = npMapP;
[b46956]2330      }
2331      int i;
2332      ntParsToCopy=0;
2333      for(i=0;i<rPar(src);i++)
2334      {
2335        if ((i>=rPar(dst))
2336        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2337           return NULL;
2338        ntParsToCopy++;
2339      }
2340      if ((ntParsToCopy==rPar(dst))&&(ntParsToCopy==rPar(src))
[21972b]2341      && (nacMap==nacCopy))
[b46956]2342        return ntCopy;    /* Z/p(a) -> Z/p(a) */
2343      return ntMapQaQb;   /* Z/p(a),Z/p'(a) -> Z/p(b)*/
2344    }
2345  }
2346  return NULL;      /* default */
2347}
2348
2349/*2
2350* convert a napoly number into a poly
2351*/
2352poly ntPermNumber(number z, int * par_perm, int P, ring oldRing)
2353{
2354  if (z==NULL) return NULL;
2355  poly res=NULL;
2356  poly p;
2357  napoly za=((lnumber)z)->z;
2358  napoly zb=((lnumber)z)->n;
2359  nMapFunc nMap=ntSetMap(oldRing,currRing);
2360  if (currRing->parameter!=NULL)
[661c214]2361    nMap=currRing->algring->cf->cfSetMap(oldRing->algring, nacRing);
[b46956]2362  else
2363    nMap=currRing->cf->cfSetMap(oldRing->algring, currRing);
2364  if (nMap==NULL) return NULL; /* emergency exit only */
2365  do
2366  {
2367    p = pInit();
2368    pNext(p)=NULL;
2369    nNew(&pGetCoeff(p));
2370    int i;
2371    for(i=pVariables;i;i--)
2372       pSetExp(p,i, 0);
2373    if (rRing_has_Comp(currRing)) pSetComp(p, 0);
2374    napoly pa=NULL;
2375    lnumber pan;
2376    if (currRing->parameter!=NULL)
2377    {
2378      assume(oldRing->algring!=NULL);
2379      pGetCoeff(p)=(number)omAlloc0Bin(rnumber_bin);
2380      pan=(lnumber)pGetCoeff(p);
2381      pan->s=2;
[661c214]2382      pan->z=napInitz(nMap(pGetCoeff(za)));
[b46956]2383      pa=pan->z;
2384    }
2385    else
2386    {
2387      pGetCoeff(p)=nMap(pGetCoeff(za));
2388    }
2389    for(i=0;i<P;i++)
2390    {
2391      if(napGetExpFrom(za,i+1,oldRing)!=0)
2392      {
2393        if(par_perm==NULL)
2394        {
2395          if ((rPar(currRing)>=i) && (pa!=NULL))
2396          {
2397            napSetExp(pa,i+1,napGetExpFrom(za,i+1,oldRing));
[661c214]2398            p_Setm(pa,nacRing);
[b46956]2399          }
2400          else
2401          {
2402            pDelete(&p);
2403            break;
2404          }
2405        }
2406        else if(par_perm[i]>0)
2407          pSetExp(p,par_perm[i],napGetExpFrom(za,i+1,oldRing));
2408        else if((par_perm[i]<0)&&(pa!=NULL))
2409        {
2410          napSetExp(pa,-par_perm[i], napGetExpFrom(za,i+1,oldRing));
[661c214]2411          p_Setm(pa,nacRing);
[b46956]2412        }
2413        else
2414        {
2415          pDelete(&p);
2416          break;
2417        }
2418      }
2419    }
2420    if (p!=NULL)
2421    {
2422      pSetm(p);
2423      if (zb!=NULL)
2424      {
2425        if  (currRing->P>0)
2426        {
[661c214]2427          pan->n=napPerm(zb,par_perm,oldRing,nMap);
[b46956]2428          if(pan->n==NULL) /* error in mapping or mapping to variable */
2429            pDelete(&p);
2430        }
2431        else
2432          pDelete(&p);
2433      }
2434      pTest(p);
2435      res=pAdd(res,p);
2436    }
2437    pIter(za);
2438  }
2439  while (za!=NULL);
2440  pTest(res);
2441  return res;
2442}
2443
2444number   ntGetDenom(number &n, const ring r)
2445{
2446  lnumber x=(lnumber)n;
2447  if (x->n!=NULL)
2448  {
2449    lnumber rr=(lnumber)omAlloc0Bin(rnumber_bin);
2450    rr->z=p_Copy(x->n,r->algring);
2451    rr->s = 2;
2452    return (number)rr;
2453  }
2454  return n_Init(1,r);
2455}
2456
2457number   ntGetNumerator(number &n, const ring r)
2458{
2459  lnumber x=(lnumber)n;
2460  lnumber rr=(lnumber)omAlloc0Bin(rnumber_bin);
2461  rr->z=p_Copy(x->z,r->algring);
2462  rr->s = 2;
2463  return (number)rr;
2464}
2465
2466#ifdef LDEBUG
2467BOOLEAN ntDBTest(number a, const char *f,const int l)
2468{
2469  lnumber x=(lnumber)a;
2470  if (x == NULL)
2471    return TRUE;
2472  #ifdef LDEBUG
2473  omCheckAddrSize(a, sizeof(snumber));
2474  #endif
2475  napoly p = x->z;
2476  if (p==NULL)
2477  {
2478    Print("0/* in %s:%d\n",f,l);
2479    return FALSE;
2480  }
2481  while(p!=NULL)
2482  {
[d0450f]2483    if (( ntIsChar0  && nlIsZero(pGetCoeff(p)))
[b46956]2484    || ((!ntIsChar0) && npIsZero(pGetCoeff(p))))
2485    {
2486      Print("coeff 0 in %s:%d\n",f,l);
2487      return FALSE;
2488    }
2489    if (ntIsChar0 && !(nlDBTest(pGetCoeff(p),f,l)))
2490      return FALSE;
2491    pIter(p);
2492  }
2493  p = x->n;
2494  while(p!=NULL)
2495  {
2496    if (ntIsChar0 && !(nlDBTest(pGetCoeff(p),f,l)))
2497      return FALSE;
2498    pIter(p);
2499  }
2500  return TRUE;
2501}
2502#endif
Note: See TracBrowser for help on using the repository browser.