source: git/kernel/longalg.cc @ dd8668

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