source: git/kernel/longalg.cc @ e4b56d

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