source: git/kernel/longalg.cc @ 6620d75

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