source: git/kernel/longalg.cc @ 1629ab

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