source: git/kernel/longalg.cc @ 47b2b2d

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