source: git/kernel/longalg.cc @ 599326

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