source: git/kernel/longalg.cc @ 900802

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