source: git/libpolys/polys/ext_fields/longalg.cc @ 16f8f1

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