source: git/kernel/longalg.cc @ 493225

spielwiese
Last change on this file since 493225 was 493225, checked in by Hans Schönemann <hannes@…>, 14 years ago
nWrite indep. from currRing git-svn-id: file:///usr/local/Singular/svn/trunk@12377 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$ */
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);
56#define nacWrite(A) n_Write(A,nacRing)
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  nacGreaterZero = nacRing->cf->nGreaterZero;
138  nacIsOne       = nacRing->cf->nIsOne;
139  nacIsMOne      = nacRing->cf->nIsMOne;
140  nacGcd         = nacRing->cf->nGcd;
141  nacLcm         = nacRing->cf->nLcm;
142  nacMult        = nacRing->cf->nMult;
143  nacDiv         = nacRing->cf->nDiv;
144  nacIntDiv      = nacRing->cf->nIntDiv;
145  nacInvers      = nacRing->cf->nInvers;
146  nacDelete      = nacRing->cf->cfDelete;
147}
148
149/*============= procedure for polynomials: napXXXX =======================*/
150
151
152
153#ifdef LDEBUG
154static void napTest(napoly p)
155{
156  while (p != NULL)
157  {
158    if (naIsChar0)
159      nlDBTest(pGetCoeff(p), "", 0);
160    pIter(p);
161  }
162}
163#else
164#define napTest(p) ((void) 0)
165#endif
166
167#define napSetCoeff(p,n) {n_Delete(&pGetCoeff(p),nacRing);pGetCoeff(p)=n;}
168#define napComp(p,q)     p_LmCmp((poly)p,(poly)q, nacRing)
169#define napMultT(A,E)    A=(napoly)p_Mult_mm((poly)A,(poly)E,nacRing)
170#define napDeg(p)        (int)p_ExpVectorQuerSum(p, nacRing)
171
172/*3
173* creates  an napoly
174*/
175napoly napInitz(number z)
176{
177  napoly a = (napoly)p_Init(nacRing);
178  pGetCoeff(a) = z;
179  return a;
180}
181
182/*3
183* copy a napoly. poly
184*/
185static napoly napCopyNeg(napoly p)
186{
187  napoly r=napCopy(p);
188  r=(napoly)p_Neg((poly)r, nacRing);
189  return r;
190}
191
192/*3
193* returns ph * z
194*/
195static void napMultN(napoly p, number z)
196{
197  number t;
198
199  while (p!=NULL)
200  {
201    t = nacMult(pGetCoeff(p), z);
202    nacNormalize(t);
203    n_Delete(&pGetCoeff(p),nacRing);
204    pGetCoeff(p) = t;
205    pIter(p);
206  }
207}
208
209/*3
210*  division with rest; f = g*q + r, returns r and destroy f
211*/
212napoly napRemainder(napoly f, const napoly  g)
213{
214  napoly a, h, qq;
215
216  qq = (napoly)p_Init(nacRing);
217  pNext(qq) = NULL;
218  p_Normalize(g, nacRing);
219  p_Normalize(f, nacRing);
220  a = f;
221  do
222  {
223    napSetExp(qq,1, p_GetExp(a,1,nacRing) - p_GetExp(g,1,nacRing));
224    napSetm(qq);
225    pGetCoeff(qq) = nacDiv(pGetCoeff(a), pGetCoeff(g));
226    pGetCoeff(qq) = nacNeg(pGetCoeff(qq));
227    nacNormalize(pGetCoeff(qq));
228    h = napCopy(g);
229    napMultT(h, qq);
230    p_Normalize(h,nacRing);
231    n_Delete(&pGetCoeff(qq),nacRing);
232    a = napAdd(a, h);
233  }
234  while ((a!=NULL) && (p_GetExp(a,1,nacRing) >= p_GetExp(g,1,nacRing)));
235  omFreeBinAddr(qq);
236  return a;
237}
238
239/*3
240*  division with rest; f = g*q + r,  destroy f
241*/
242static void napDivMod(napoly f, napoly  g, napoly *q, napoly *r)
243{
244  napoly a, h, b, qq;
245
246  qq = (napoly)p_Init(nacRing);
247  pNext(qq) = b = NULL;
248  p_Normalize(g,nacRing);
249  p_Normalize(f,nacRing);
250  a = f;
251  do
252  {
253    napSetExp(qq,1, p_GetExp(a,1,nacRing) - p_GetExp(g,1,nacRing));
254    p_Setm(qq,nacRing);
255    pGetCoeff(qq) = nacDiv(pGetCoeff(a), pGetCoeff(g));
256    nacNormalize(pGetCoeff(qq));
257    b = napAdd(b, napCopy(qq));
258    pGetCoeff(qq) = nacNeg(pGetCoeff(qq));
259    h = napCopy(g);
260    napMultT(h, qq);
261    p_Normalize(h,nacRing);
262    n_Delete(&pGetCoeff(qq),nacRing);
263    a = napAdd(a, h);
264  }
265  while ((a!=NULL) && (p_GetExp(a,1,nacRing) >= p_GetExp(g,1,nacRing)));
266  omFreeBinAddr(qq);
267  *q = b;
268  *r = a;
269}
270
271/*3
272*  returns z with z*x mod c = 1
273*/
274static napoly napInvers(napoly x, const napoly c)
275{
276  napoly y, r, qa, qn, q;
277  number t, h;
278
279  if (p_GetExp(x,1,nacRing) >= p_GetExp(c,1,nacRing))
280    x = napRemainder(x, c);
281  if (x==NULL)
282  {
283    goto zero_divisor;
284  }
285  if (p_GetExp(x,1,nacRing)==0)
286  {
287    if (!nacIsOne(pGetCoeff(x)))
288    {
289      nacNormalize(pGetCoeff(x));
290      t = nacInvers(pGetCoeff(x));
291      nacNormalize(t);
292      n_Delete(&pGetCoeff(x),nacRing);
293      pGetCoeff(x) = t;
294    }
295    return x;
296  }
297  y = napCopy(c);
298  napDivMod(y, x, &qa, &r);
299  if (r==NULL)
300  {
301    goto zero_divisor;
302  }
303  if (p_GetExp(r,1,nacRing)==0)
304  {
305    nacNormalize(pGetCoeff(r));
306    t = nacInvers(pGetCoeff(r));
307    nacNormalize(t);
308    t = nacNeg(t);
309    napMultN(qa, t);
310    n_Delete(&t,nacRing);
311    p_Normalize(qa,nacRing);
312    p_Delete(&x,nacRing);
313    p_Delete(&r,nacRing);
314    return qa;
315  }
316  y = x;
317  x = r;
318  napDivMod(y, x, &q, &r);
319  if (r==NULL)
320  {
321    goto zero_divisor;
322  }
323  if (p_GetExp(r,1,nacRing)==0)
324  {
325    q = p_Mult_q(q, qa,nacRing);
326    q = napAdd(q, p_ISet(1,nacRing));
327    nacNormalize(pGetCoeff(r));
328    t = nacInvers(pGetCoeff(r));
329    napMultN(q, t);
330    p_Normalize(q,nacRing);
331    n_Delete(&t,nacRing);
332    p_Delete(&x,nacRing);
333    p_Delete(&r,nacRing);
334    if (p_GetExp(q,1,nacRing) >= p_GetExp(c,1,nacRing))
335      q = napRemainder(q, c);
336    return q;
337  }
338  q = p_Mult_q(q, napCopy(qa),nacRing);
339  q = napAdd(q, p_ISet(1,nacRing));
340  qa = napNeg(qa);
341  loop
342  {
343    y = x;
344    x = r;
345    napDivMod(y, x, &qn, &r);
346    if (r==NULL)
347    {
348      break;
349    }
350    if (p_GetExp(r,1,nacRing)==0)
351    {
352      q = p_Mult_q(q, qn,nacRing);
353      q = napNeg(q);
354      q = napAdd(q, qa);
355      nacNormalize(pGetCoeff(r));
356      t = nacInvers(pGetCoeff(r));
357      //nacNormalize(t);
358      napMultN(q, t);
359      p_Normalize(q,nacRing);
360      n_Delete(&t,nacRing);
361      p_Delete(&x,nacRing);
362      p_Delete(&r,nacRing);
363      if (p_GetExp(q,1,nacRing) >= p_GetExp(c,1,nacRing))
364        q = napRemainder(q, c);
365      return q;
366    }
367    y = q;
368    q = p_Mult_q(napCopy(q), qn, nacRing);
369    q = napNeg(q);
370    q = napAdd(q, qa);
371    qa = y;
372  }
373// zero divisor found:
374zero_divisor:
375  Werror("zero divisor found - your minpoly is not irreducible");
376  return x;
377}
378
379/*3
380* the max degree of an napoly poly (used for test of "simple" et al.)
381*/
382static int  napMaxDeg(napoly p)
383{
384  int  d = 0;
385  while(p!=NULL)
386  {
387    d=si_max(d,napDeg(p));
388    pIter(p);
389  }
390  return d;
391}
392
393/*3
394* the max degree of an napoly poly (used for test of "simple" et al.)
395*/
396static int  napMaxDegLen(napoly p, int &l)
397{
398  int  d = 0;
399  int ll=0;
400  while(p!=NULL)
401  {
402    d=si_max(d,napDeg(p));
403    pIter(p);
404    ll++;
405  }
406  l=ll;
407  return d;
408}
409
410
411/*3
412*writes a polynomial number
413*/
414void napWrite(napoly p,const BOOLEAN has_denom, const ring r)
415{
416  ring nacring=r->algring;
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    n_Write(pGetCoeff(p),nacring);
431    if (kl) StringAppendS(")");
432  }
433  else
434  {
435    StringAppendS("(");
436    loop
437    {
438      BOOLEAN wroteCoeff=FALSE;
439      if ((p_LmIsConstant(p,nacring))
440      || ((!n_IsOne(pGetCoeff(p),nacring))
441        && (!n_IsMOne(pGetCoeff(p),nacring))))
442      {
443        n_Write(pGetCoeff(p),nacring);
444        wroteCoeff=(r->ShortOut==0);
445      }
446      else if (n_IsMOne(pGetCoeff(p),nacring))
447      {
448        StringAppendS("-");
449      }
450      int  i;
451      for (i = 0; i < r->P; 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=(r->ShortOut==0);
460          StringAppendS(r->parameter[i]);
461          if (e > 1)
462          {
463            if (r->ShortOut == 0)
464              StringAppendS("^");
465            StringAppend("%d", e);
466          }
467        }
468      } /*for*/
469      pIter(p);
470      if (p==NULL)
471        break;
472      if (n_GreaterZero(pGetCoeff(p),nacring))
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*  addition; lu:= la + lb
1003*/
1004number naAdd(number la, number lb)
1005{
1006  napoly x, y;
1007  lnumber lu;
1008  lnumber a = (lnumber)la;
1009  lnumber b = (lnumber)lb;
1010  if (a==NULL) return naCopy(lb);
1011  if (b==NULL) return naCopy(la);
1012  omCheckAddrSize(a,sizeof(snumber));
1013  omCheckAddrSize(b,sizeof(snumber));
1014  lu = (lnumber)omAllocBin(rnumber_bin);
1015  if (b->n!=NULL) x = pp_Mult_qq(a->z, b->n,nacRing);
1016  else            x = napCopy(a->z);
1017  if (a->n!=NULL) y = pp_Mult_qq(b->z, a->n,nacRing);
1018  else            y = napCopy(b->z);
1019  lu->z = napAdd(x, y);
1020  if (lu->z==NULL)
1021  {
1022    omFreeBin((ADDRESS)lu,  rnumber_bin);
1023    return (number)NULL;
1024  }
1025  if (a->n!=NULL)
1026  {
1027    if (b->n!=NULL) x = pp_Mult_qq(a->n, b->n,nacRing);
1028    else            x = napCopy(a->n);
1029  }
1030  else
1031  {
1032    if (b->n!=NULL) x = napCopy(b->n);
1033    else            x = NULL;
1034  }
1035  //if (x!=NULL)
1036  //{
1037  //  if (p_LmIsConstant(x,nacRing))
1038  //  {
1039  //    number inv=nacInvers(pGetCoeff(x));
1040  //    napMultN(lu->z,inv);
1041  //    n_Delete(&inv,nacRing);
1042  //    napDelete(&x);
1043  //  }
1044  //}
1045  lu->n = x;
1046  lu->s = FALSE;
1047  if (lu->n!=NULL)
1048  {
1049     number luu=(number)lu;
1050     //if (p_IsConstant(lu->n,nacRing)) naCoefNormalize(luu);
1051     //else           
1052                naNormalize(luu);
1053     lu=(lnumber)luu;
1054  }
1055  naTest((number)lu);
1056  return (number)lu;
1057}
1058
1059/*2
1060*  subtraction; r:= la - lb
1061*/
1062number naSub(number la, number lb)
1063{
1064  lnumber lu;
1065
1066  if (lb==NULL) return naCopy(la);
1067  if (la==NULL)
1068  {
1069    lu = (lnumber)naCopy(lb);
1070    lu->z = napNeg(lu->z);
1071    return (number)lu;
1072  }
1073
1074  lnumber a = (lnumber)la;
1075  lnumber b = (lnumber)lb;
1076
1077  omCheckAddrSize(a,sizeof(snumber));
1078  omCheckAddrSize(b,sizeof(snumber));
1079
1080  napoly x, y;
1081  lu = (lnumber)omAllocBin(rnumber_bin);
1082  if (b->n!=NULL) x = pp_Mult_qq(a->z, b->n,nacRing);
1083  else            x = napCopy(a->z);
1084  if (a->n!=NULL) y = p_Mult_q(napCopy(b->z), napCopyNeg(a->n),nacRing);
1085  else            y = napCopyNeg(b->z);
1086  lu->z = napAdd(x, y);
1087  if (lu->z==NULL)
1088  {
1089    omFreeBin((ADDRESS)lu,  rnumber_bin);
1090    return (number)NULL;
1091  }
1092  if (a->n!=NULL)
1093  {
1094    if (b->n!=NULL) x = pp_Mult_qq(a->n, b->n,nacRing);
1095    else            x = napCopy(a->n);
1096  }
1097  else
1098  {
1099    if (b->n!=NULL) x = napCopy(b->n);
1100    else            x = NULL;
1101  }
1102  lu->n = x;
1103  lu->s = FALSE;
1104  if (lu->n!=NULL)
1105  {
1106     number luu=(number)lu;
1107     //if (p_IsConstant(lu->n,nacRing)) naCoefNormalize(luu);
1108     //else   
1109                         naNormalize(luu);
1110     lu=(lnumber)luu;
1111  }
1112  naTest((number)lu);
1113  return (number)lu;
1114}
1115
1116/*2
1117*  multiplication; r:= la * lb
1118*/
1119number naMult(number la, number lb)
1120{
1121  if ((la==NULL) || (lb==NULL))
1122    return NULL;
1123
1124  lnumber a = (lnumber)la;
1125  lnumber b = (lnumber)lb;
1126  lnumber lo;
1127  napoly x;
1128
1129  omCheckAddrSize(a,sizeof(snumber));
1130  omCheckAddrSize(b,sizeof(snumber));
1131  naTest(la);
1132  naTest(lb);
1133
1134  lo = (lnumber)omAllocBin(rnumber_bin);
1135  lo->z = pp_Mult_qq(a->z, b->z,nacRing);
1136
1137  if (a->n==NULL)
1138  {
1139    if (b->n==NULL)
1140      x = NULL;
1141    else
1142      x = napCopy(b->n);
1143  }
1144  else
1145  {
1146    if (b->n==NULL)
1147    {
1148      x = napCopy(a->n);
1149    }
1150    else
1151    {
1152      x = pp_Mult_qq(b->n, a->n, nacRing);
1153    }
1154  }
1155  if (naMinimalPoly!=NULL)
1156  {
1157    if (p_GetExp(lo->z,1,nacRing) >= p_GetExp(naMinimalPoly,1,nacRing))
1158      lo->z = napRemainder(lo->z, naMinimalPoly);
1159    if ((x!=NULL) && (p_GetExp(x,1,nacRing) >= p_GetExp(naMinimalPoly,1,nacRing)))
1160      x = napRemainder(x, naMinimalPoly);
1161  }
1162  if (naI!=NULL)
1163  {
1164    lo->z = napRedp (lo->z);
1165    if (lo->z != NULL)
1166       lo->z = napTailred (lo->z);
1167    if (x!=NULL)
1168    {
1169      x = napRedp (x);
1170      if (x!=NULL)
1171        x = napTailred (x);
1172    }
1173  }
1174  if ((x!=NULL) && (p_LmIsConstant(x,nacRing)) && nacIsOne(pGetCoeff(x)))
1175    p_Delete(&x,nacRing);
1176  lo->n = x;
1177  if(lo->z==NULL)
1178  {
1179    omFreeBin((ADDRESS)lo, rnumber_bin);
1180    lo=NULL;
1181  }
1182  else if (lo->n!=NULL)
1183  {
1184    lo->s = 0;
1185    number luu=(number)lo;
1186    // if (p_IsConstant(lo->n,nacRing)) naCoefNormalize(luu);
1187    // else     
1188                      naNormalize(luu);
1189    lo=(lnumber)luu;
1190  }
1191  naTest((number)lo);
1192  return (number)lo;
1193}
1194
1195number naIntDiv(number la, number lb)
1196{
1197  lnumber res;
1198  lnumber a = (lnumber)la;
1199  lnumber b = (lnumber)lb;
1200  if (a==NULL)
1201  {
1202    return NULL;
1203  }
1204  if (b==NULL)
1205  {
1206    WerrorS(nDivBy0);
1207    return NULL;
1208  }
1209  assume(a->z!=NULL && b->z!=NULL);
1210  assume(a->n==NULL && b->n==NULL);
1211  res = (lnumber)omAllocBin(rnumber_bin);
1212  res->z = napCopy(a->z);
1213  res->n = napCopy(b->z);
1214  res->s = 0;
1215  number nres=(number)res;
1216  naNormalize(nres);
1217
1218  //napDelete(&res->n);
1219  naTest(nres);
1220  return nres;
1221}
1222
1223/*2
1224*  division; lo:= la / lb
1225*/
1226number naDiv(number la, number lb)
1227{
1228  lnumber lo;
1229  lnumber a = (lnumber)la;
1230  lnumber b = (lnumber)lb;
1231  napoly x;
1232
1233  if (a==NULL)
1234    return NULL;
1235
1236  if (b==NULL)
1237  {
1238    WerrorS(nDivBy0);
1239    return NULL;
1240  }
1241  omCheckAddrSize(a,sizeof(snumber));
1242  omCheckAddrSize(b,sizeof(snumber));
1243  lo = (lnumber)omAllocBin(rnumber_bin);
1244  if (b->n!=NULL)
1245    lo->z = pp_Mult_qq(a->z, b->n,nacRing);
1246  else
1247    lo->z = napCopy(a->z);
1248  if (a->n!=NULL)
1249    x = pp_Mult_qq(b->z, a->n, nacRing);
1250  else
1251    x = napCopy(b->z);
1252  if (naMinimalPoly!=NULL)
1253  {
1254    if (p_GetExp(lo->z,1,nacRing) >= p_GetExp(naMinimalPoly,1,nacRing))
1255      lo->z = napRemainder(lo->z, naMinimalPoly);
1256    if (p_GetExp(x,1,nacRing) >= p_GetExp(naMinimalPoly,1,nacRing))
1257      x = napRemainder(x, naMinimalPoly);
1258  }
1259  if (naI!=NULL)
1260  {
1261    lo->z = napRedp (lo->z);
1262    if (lo->z != NULL)
1263       lo->z = napTailred (lo->z);
1264    if (x!=NULL)
1265    {
1266      x = napRedp (x);
1267      if (x!=NULL)
1268        x = napTailred (x);
1269    }
1270  }
1271  if ((p_LmIsConstant(x,nacRing)) && nacIsOne(pGetCoeff(x)))
1272    p_Delete(&x,nacRing);
1273  lo->n = x;
1274  if (lo->n!=NULL)
1275  {
1276    lo->s = 0;
1277    number luu=(number)lo;
1278     //if (p_IsConstant(lo->n,nacRing)) naCoefNormalize(luu);
1279     //else   
1280                         naNormalize(luu);
1281    lo=(lnumber)luu;
1282  }
1283  naTest((number)lo);
1284  return (number)lo;
1285}
1286
1287/*2
1288*  za:= - za
1289*/
1290number naNeg(number za)
1291{
1292  if (za!=NULL)
1293  {
1294    lnumber e = (lnumber)za;
1295    naTest(za);
1296    e->z = napNeg(e->z);
1297  }
1298  return za;
1299}
1300
1301/*2
1302* 1/a
1303*/
1304number naInvers(number a)
1305{
1306  lnumber lo;
1307  lnumber b = (lnumber)a;
1308  napoly x;
1309
1310  if (b==NULL)
1311  {
1312    WerrorS(nDivBy0);
1313    return NULL;
1314  }
1315  omCheckAddrSize(b,sizeof(snumber));
1316  lo = (lnumber)omAlloc0Bin(rnumber_bin);
1317  lo->s = b->s;
1318  if (b->n!=NULL)
1319    lo->z = napCopy(b->n);
1320  else
1321    lo->z = p_ISet(1,nacRing);
1322  x = b->z;
1323  if ((!p_LmIsConstant(x,nacRing)) || !nacIsOne(pGetCoeff(x)))
1324    x = napCopy(x);
1325  else
1326  {
1327    lo->n = NULL;
1328    naTest((number)lo);
1329    return (number)lo;
1330  }
1331  if (naMinimalPoly!=NULL)
1332  {
1333    x = napInvers(x, naMinimalPoly);
1334    x = p_Mult_q(x, lo->z,nacRing);
1335    if (p_GetExp(x,1,nacRing) >= p_GetExp(naMinimalPoly,1,nacRing))
1336      x = napRemainder(x, naMinimalPoly);
1337    lo->z = x;
1338    lo->n = NULL;
1339    while (x!=NULL)
1340    {
1341      nacNormalize(pGetCoeff(x));
1342      pIter(x);
1343    }
1344  }
1345  else
1346    lo->n = x;
1347  if (lo->n!=NULL)
1348  {
1349     number luu=(number)lo;
1350     //if (p_IsConstant(lo->n,nacRing)) naCoefNormalize(luu);
1351     //else 
1352                           naNormalize(luu);
1353     lo=(lnumber)luu;
1354  }
1355  naTest((number)lo);
1356  return (number)lo;
1357}
1358
1359
1360BOOLEAN naIsZero(number za)
1361{
1362  lnumber zb = (lnumber)za;
1363  naTest(za);
1364#ifdef LDEBUG
1365  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(2)");
1366#endif
1367  return (zb==NULL);
1368}
1369
1370
1371BOOLEAN naGreaterZero(number za)
1372{
1373  lnumber zb = (lnumber)za;
1374#ifdef LDEBUG
1375  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(3)");
1376#endif
1377  naTest(za);
1378  if (zb!=NULL)
1379  {
1380    return (nacGreaterZero(pGetCoeff(zb->z))||(!p_LmIsConstant(zb->z,nacRing)));
1381  }
1382  /* else */ return FALSE;
1383}
1384
1385
1386/*2
1387* a = b ?
1388*/
1389BOOLEAN naEqual (number a, number b)
1390{
1391  if(a==b) return TRUE;
1392  if((a==NULL)&&(b!=NULL)) return FALSE;
1393  if((b==NULL)&&(a!=NULL)) return FALSE;
1394
1395  lnumber aa=(lnumber)a;
1396  lnumber bb=(lnumber)b;
1397
1398  int an_deg=0;
1399  if(aa->n!=NULL)
1400    an_deg=napDeg(aa->n);
1401  int bn_deg=0;
1402  if(bb->n!=NULL)
1403    bn_deg=napDeg(bb->n);
1404  if(an_deg+napDeg(bb->z)!=bn_deg+napDeg(aa->z))
1405    return FALSE;
1406#if 0
1407  naNormalize(a);
1408  aa=(lnumber)a;
1409  naNormalize(b);
1410  bb=(lnumber)b;
1411  if((aa->n==NULL)&&(bb->n!=NULL)) return FALSE;
1412  if((bb->n==NULL)&&(aa->n!=NULL)) return FALSE;
1413  if(napComp(aa->z,bb->z)!=0) return FALSE;
1414  if((aa->n!=NULL) && (napComp(aa->n,bb->n))) return FALSE;
1415#endif
1416  number h = naSub(a, b);
1417  BOOLEAN bo = naIsZero(h);
1418  naDelete(&h,currRing);
1419  return bo;
1420}
1421
1422
1423BOOLEAN naGreater (number a, number b)
1424{
1425  if (naIsZero(a))
1426    return FALSE;
1427  if (naIsZero(b))
1428    return TRUE; /* a!= 0)*/
1429  return napDeg(((lnumber)a)->z)>napDeg(((lnumber)b)->z);
1430}
1431
1432/*2
1433* reads a number
1434*/
1435const char  *naRead(const char *s, number *p)
1436{
1437  napoly x;
1438  lnumber a;
1439  s = napRead(s, &x);
1440  if (x==NULL)
1441  {
1442    *p = NULL;
1443    return s;
1444  }
1445  *p = (number)omAlloc0Bin(rnumber_bin);
1446  a = (lnumber)*p;
1447  if ((naMinimalPoly!=NULL)
1448  && (p_GetExp(x,1,nacRing) >= p_GetExp(naMinimalPoly,1,nacRing)))
1449    a->z = napRemainder(x, naMinimalPoly);
1450  else if (naI!=NULL)
1451  {
1452    a->z = napRedp(x);
1453    if (a->z != NULL)
1454      a->z = napTailred (a->z);
1455  }
1456  else
1457    a->z = x;
1458  if(a->z==NULL)
1459  {
1460    omFreeBin((ADDRESS)*p, rnumber_bin);
1461    *p=NULL;
1462  }
1463  else
1464  {
1465    a->n = NULL;
1466    a->s = 0;
1467    naTest(*p);
1468  }
1469  return s;
1470}
1471
1472/*2
1473* tries to convert a number to a name
1474*/
1475char * naName(number n)
1476{
1477  lnumber ph = (lnumber)n;
1478  if (ph==NULL)
1479    return NULL;
1480  int i;
1481  char *s=(char *)omAlloc(4* naNumbOfPar);
1482  char *t=(char *)omAlloc(8);
1483  s[0]='\0';
1484  for (i = 0; i <= naNumbOfPar - 1; i++)
1485  {
1486    int e=p_GetExp(ph->z,i+1,nacRing);
1487    if (e > 0)
1488    {
1489      if (e >1)
1490      {
1491        sprintf(t,"%s%d",naParNames[i],e);
1492        strcat(s,t);
1493      }
1494      else
1495      {
1496        strcat(s,naParNames[i]);
1497      }
1498    }
1499  }
1500  omFreeSize((ADDRESS)t,8);
1501  if (s[0]=='\0')
1502  {
1503    omFree((ADDRESS)s);
1504    return NULL;
1505  }
1506  return s;
1507}
1508
1509/*2
1510*  writes a number
1511*/
1512void naWrite(number &phn, const ring r)
1513{
1514  lnumber ph = (lnumber)phn;
1515  if (ph==NULL)
1516    StringAppendS("0");
1517  else
1518  {
1519    phn->s = 0;
1520    BOOLEAN has_denom=(ph->n!=NULL);
1521    napWrite(ph->z,has_denom/*(ph->n!=NULL)*/,r);
1522    if (has_denom/*(ph->n!=NULL)*/)
1523    {
1524      StringAppendS("/");
1525      napWrite(ph->n,TRUE,r);
1526    }
1527  }
1528}
1529
1530/*2
1531* za == 1 ?
1532*/
1533BOOLEAN naIsOne(number za)
1534{
1535  lnumber a = (lnumber)za;
1536  napoly x, y;
1537  number t;
1538  if (a==NULL) return FALSE;
1539  omCheckAddrSize(a,sizeof(snumber));
1540#ifdef LDEBUG
1541  if (a->z==NULL)
1542  {
1543    WerrorS("internal zero error(4)");
1544    return FALSE;
1545  }
1546#endif
1547  if (a->n==NULL)
1548  {
1549    if (p_LmIsConstant(a->z,nacRing))
1550    {
1551      return nacIsOne(pGetCoeff(a->z));
1552    }
1553    else                 return FALSE;
1554  }
1555#if 0
1556  x = a->z;
1557  y = a->n;
1558  do
1559  {
1560    if (napComp(x, y))
1561      return FALSE;
1562    else
1563    {
1564      t = nacSub(pGetCoeff(x), pGetCoeff(y));
1565      if (!nacIsZero(t))
1566      {
1567        n_Delete(&t,nacRing);
1568        return FALSE;
1569      }
1570      else
1571        n_Delete(&t,nacRing);
1572    }
1573    pIter(x);
1574    pIter(y);
1575  }
1576  while ((x!=NULL) && (y!=NULL));
1577  if ((x!=NULL) || (y!=NULL)) return FALSE;
1578  p_Delete(&a->z,nacRing);
1579  p_Delete(&a->n,nacRing);
1580  a->z = p_ISet(1,nacRing);
1581  a->n = NULL;
1582  return TRUE;
1583#else
1584  return FALSE;
1585#endif
1586}
1587
1588/*2
1589* za == -1 ?
1590*/
1591BOOLEAN naIsMOne(number za)
1592{
1593  lnumber a = (lnumber)za;
1594  napoly x, y;
1595  number t;
1596  if (a==NULL) return FALSE;
1597  omCheckAddrSize(a,sizeof(snumber));
1598#ifdef LDEBUG
1599  if (a->z==NULL)
1600  {
1601    WerrorS("internal zero error(5)");
1602    return FALSE;
1603  }
1604#endif
1605  if (a->n==NULL)
1606  {
1607    if (p_LmIsConstant(a->z,nacRing)) return nacIsMOne(pGetCoeff(a->z));
1608    /*else                   return FALSE;*/
1609  }
1610  return FALSE;
1611}
1612
1613/*2
1614* returns the i-th power of p (i>=0)
1615*/
1616void naPower(number p, int i, number *rc)
1617{
1618  number x;
1619  *rc = naInit(1,currRing);
1620  for (; i > 0; i--)
1621  {
1622    x = naMult(*rc, p);
1623    naDelete(rc,currRing);
1624    *rc = x;
1625  }
1626}
1627
1628/*2
1629* result =gcd(a,b)
1630*/
1631number naGcd(number a, number b, const ring r)
1632{
1633  if (a==NULL)  return naCopy(b);
1634  if (b==NULL)  return naCopy(a);
1635
1636  lnumber x, y;
1637  lnumber result = (lnumber)omAlloc0Bin(rnumber_bin);
1638
1639  x = (lnumber)a;
1640  y = (lnumber)b;
1641  if ((naNumbOfPar == 1) && (naMinimalPoly!=NULL))
1642  {
1643    if (pNext(x->z)!=NULL)
1644      result->z = p_Copy(x->z, r->algring);
1645    else
1646      result->z = napGcd0(x->z, y->z);
1647  }
1648  else
1649#ifndef HAVE_FACTORY
1650    result->z = napGcd(x->z, y->z); // change from napGcd0
1651#else
1652  {
1653    int c=ABS(nGetChar());
1654    if (c==1) c=0;
1655    setCharacteristic( c );
1656
1657    napoly rz=napGcd(x->z, y->z);
1658    CanonicalForm F, G, R;
1659    R=convSingPFactoryP(rz,r->algring);
1660    p_Normalize(x->z,nacRing);
1661    F=convSingPFactoryP(x->z,r->algring)/R;
1662    p_Normalize(y->z,nacRing);
1663    G=convSingPFactoryP(y->z,r->algring)/R;
1664    F = gcd( F, G );
1665    if (F.isOne())
1666      result->z= rz;
1667    else
1668    {
1669      p_Delete(&rz,r->algring);
1670      result->z=convFactoryPSingP( F*R,r->algring );
1671      p_Normalize(result->z,nacRing);
1672    }
1673  }
1674#endif
1675  naTest((number)result);
1676  return (number)result;
1677}
1678
1679
1680/*2
1681* naNumbOfPar = 1:
1682* clears denominator         algebraic case;
1683* tries to simplify ratio    transcendental case;
1684*
1685* cancels monomials
1686* occuring in denominator
1687* and enumerator  ?          naNumbOfPar != 1;
1688*
1689* #defines for Factory:
1690* FACTORY_GCD_TEST: do not apply built in gcd for
1691*   univariate polynomials, always use Factory
1692*/
1693//#define FACTORY_GCD_TEST
1694void naCoefNormalize(number pp)
1695{
1696  if (pp==NULL) return;
1697  lnumber p = (lnumber)pp;
1698  number nz; // all denom. of the numerator
1699  nz=p_GetAllDenom(p->z,nacRing);
1700  BOOLEAN norm=FALSE;
1701  if (!n_IsOne(nz,nacRing))
1702  {
1703    norm=TRUE;
1704    p->z=p_Mult_nn(p->z,nz,nacRing);
1705    if (p->n==NULL)
1706    {
1707      p->n=p_NSet(nz,nacRing);
1708    }
1709    else
1710    {
1711      p->n=p_Mult_nn(p->n,nz,nacRing);
1712      n_Delete(&nz, nacRing);
1713    }
1714  }
1715  else
1716  {
1717    n_Delete(&nz, nacRing);
1718  }
1719  if (norm)
1720  {
1721    norm=FALSE;
1722    p_Normalize(p->z,nacRing);
1723    p_Normalize(p->n,nacRing);
1724  }
1725  number nn;
1726  nn=p_GetAllDenom(p->n,nacRing);
1727  if (!n_IsOne(nn,nacRing))
1728  {
1729    norm=TRUE;
1730    p->n=p_Mult_nn(p->n,nn,nacRing);
1731    p->z=p_Mult_nn(p->z,nn,nacRing);
1732    n_Delete(&nn, nacRing);
1733  }
1734  else
1735  {
1736    n_Delete(&nn, nacRing);
1737  }
1738  if (norm)
1739  {
1740    p_Normalize(p->z,nacRing);
1741    p_Normalize(p->n,nacRing);
1742  }
1743  // remove common factors in n, z:
1744  if (p->n!=NULL)
1745  {
1746    poly pp=p->z;
1747    nz=n_Copy(pGetCoeff(pp),nacRing);
1748    pIter(pp);
1749    while(pp!=NULL)
1750    { 
1751      if (n_IsOne(nz,nacRing)) break;
1752      number d=n_Gcd(nz,pGetCoeff(pp),nacRing);
1753      n_Delete(&nz,nacRing); nz=d;
1754      pIter(pp);
1755    }
1756    if (!n_IsOne(nz,nacRing))
1757    {
1758      pp=p->n;
1759      nn=n_Copy(pGetCoeff(pp),nacRing);
1760      pIter(pp);
1761      while(pp!=NULL)
1762      { 
1763        if (n_IsOne(nn,nacRing)) break;
1764        number d=n_Gcd(nn,pGetCoeff(pp),nacRing);
1765        n_Delete(&nn,nacRing); nn=d;
1766        pIter(pp);
1767      }
1768      number ng=n_Gcd(nz,nn,nacRing);
1769      n_Delete(&nn,nacRing);
1770      if (!n_IsOne(ng,nacRing))
1771      {
1772        number ni=n_Invers(ng,nacRing);
1773        p->z=p_Mult_nn(p->z,ni,nacRing);
1774        p->n=p_Mult_nn(p->n,ni,nacRing);
1775        p_Normalize(p->z,nacRing);
1776        p_Normalize(p->n,nacRing);
1777        n_Delete(&ni,nacRing);
1778      }
1779      n_Delete(&ng,nacRing);
1780    }
1781    n_Delete(&nz,nacRing);
1782  }
1783  if (p->n!=NULL)
1784  {
1785    if(!nacGreaterZero(pGetCoeff(p->n)))
1786    {
1787      p->z=napNeg(p->z);
1788      p->n=napNeg(p->n);
1789    }
1790
1791    if (/*(p->n!=NULL) && */
1792    (p_IsConstant(p->n,nacRing))
1793    && (n_IsOne(pGetCoeff(p->n),nacRing)))
1794    {
1795      p_Delete(&(p->n), nacRing);
1796      p->n = NULL;
1797    }
1798  }
1799}
1800void naNormalize(number &pp)
1801{
1802
1803  //naTest(pp); // input may not be "normal"
1804  lnumber p = (lnumber)pp;
1805
1806  if (p==NULL)
1807    return;
1808  naCoefNormalize(pp);
1809  p->s = 2;
1810  napoly x = p->z;
1811  napoly y = p->n;
1812
1813  BOOLEAN norm=FALSE;
1814
1815  if ((y!=NULL) && (naMinimalPoly!=NULL))
1816  {
1817    y = napInvers(y, naMinimalPoly);
1818    x = p_Mult_q(x, y,nacRing);
1819    if (p_GetExp(x,1,nacRing) >= p_GetExp(naMinimalPoly,1,nacRing))
1820      x = napRemainder(x, naMinimalPoly);
1821    p->z = x;
1822    p->n = y = NULL;
1823    norm=naIsChar0;
1824  }
1825
1826  /* check for degree of x too high: */
1827  if ((x!=NULL) && (naMinimalPoly!=NULL) && (x!=naMinimalPoly)
1828  && (p_GetExp(x,1,nacRing)>p_GetExp(naMinimalPoly,1,nacRing)))
1829  // DO NOT REDUCE naMinimalPoly with itself
1830  {
1831    x = napRemainder(x, naMinimalPoly);
1832    p->z = x;
1833    norm=naIsChar0;
1834  }
1835  /* normalize all coefficients in n and z (if in Q) */
1836  if (norm) 
1837  {
1838    naCoefNormalize(pp);
1839    x = p->z;
1840    y = p->n;
1841  }
1842  if (y==NULL) return;
1843
1844  if ((naMinimalPoly == NULL) && (x!=NULL) && (y!=NULL))
1845  {
1846    int i;
1847    for (i=naNumbOfPar-1; i>=0; i--)
1848    {
1849      napoly xx=x;
1850      napoly yy=y;
1851      int m = napExpi(i, yy, xx);
1852      if (m != 0)          // in this case xx!=NULL!=yy
1853      {
1854        while (xx != NULL)
1855        {
1856          napAddExp(xx,i+1, -m);
1857          pIter(xx);
1858        }
1859        while (yy != NULL)
1860        {
1861          napAddExp(yy,i+1, -m);
1862          pIter(yy);
1863        }
1864      }
1865    }
1866  }
1867  if (p_LmIsConstant(y,nacRing)) /* i.e. => simplify to (1/c)*z / monom */
1868  {
1869    if (nacIsOne(pGetCoeff(y)))
1870    {
1871      p_LmDelete(&y,nacRing);
1872      p->n = NULL;
1873      naTest(pp);
1874      return;
1875    }
1876    number h1 = nacInvers(pGetCoeff(y));
1877    nacNormalize(h1);
1878    napMultN(x, h1);
1879    n_Delete(&h1,nacRing);
1880    p_LmDelete(&y,nacRing);
1881    p->n = NULL;
1882    naTest(pp);
1883    return;
1884  }
1885#ifndef FACTORY_GCD_TEST
1886  if (naNumbOfPar == 1) /* apply built-in gcd */
1887  {
1888    napoly x1,y1;
1889    if (p_GetExp(x,1,nacRing) >= p_GetExp(y,1,nacRing))
1890    {
1891      x1 = napCopy(x);
1892      y1 = napCopy(y);
1893    }
1894    else
1895    {
1896      x1 = napCopy(y);
1897      y1 = napCopy(x);
1898    }
1899    napoly r;
1900    loop
1901    {
1902      r = napRemainder(x1, y1);
1903      if ((r==NULL) || (pNext(r)==NULL)) break;
1904      x1 = y1;
1905      y1 = r;
1906    }
1907    if (r!=NULL)
1908    {
1909      p_Delete(&r,nacRing);
1910      p_Delete(&y1,nacRing);
1911    }
1912    else
1913    {
1914      napDivMod(x, y1, &(p->z), &r);
1915      napDivMod(y, y1, &(p->n), &r);
1916      p_Delete(&y1,nacRing);
1917    }
1918    x = p->z;
1919    y = p->n;
1920    /* collect all denoms from y and multiply x and y by it */
1921    if (naIsChar0)
1922    {
1923      number n=napLcm(y);
1924      napMultN(x,n);
1925      napMultN(y,n);
1926      n_Delete(&n,nacRing);
1927      while(x!=NULL)
1928      {
1929        nacNormalize(pGetCoeff(x));
1930        pIter(x);
1931      }
1932      x = p->z;
1933      while(y!=NULL)
1934      {
1935        nacNormalize(pGetCoeff(y));
1936        pIter(y);
1937      }
1938      y = p->n;
1939    }
1940    if (pNext(y)==NULL)
1941    {
1942      if (nacIsOne(pGetCoeff(y)))
1943      {
1944        if (p_GetExp(y,1,nacRing)==0)
1945        {
1946          p_LmDelete(&y,nacRing);
1947          p->n = NULL;
1948        }
1949        naTest(pp);
1950        return;
1951      }
1952    }
1953  }
1954#endif /* FACTORY_GCD_TEST */
1955#ifdef HAVE_FACTORY
1956#ifndef FACTORY_GCD_TEST
1957  else
1958#endif
1959  {
1960    napoly xx,yy;
1961    singclap_algdividecontent(x,y,xx,yy);
1962    if (xx!=NULL)
1963    {
1964      p->z=xx;
1965      p->n=yy;
1966      p_Delete(&x,nacRing);
1967      p_Delete(&y,nacRing);
1968    }
1969  }
1970#endif
1971  /* remove common factors from z and n */
1972  x=p->z;
1973  y=p->n;
1974  if(!nacGreaterZero(pGetCoeff(y)))
1975  {
1976    x=napNeg(x);
1977    y=napNeg(y);
1978  }
1979  number g=nacCopy(pGetCoeff(x));
1980  pIter(x);
1981  while (x!=NULL)
1982  {
1983    number d=nacGcd(g,pGetCoeff(x), nacRing);
1984    if(nacIsOne(d))
1985    {
1986      n_Delete(&g,nacRing);
1987      n_Delete(&d,nacRing);
1988      naTest(pp);
1989      return;
1990    }
1991    n_Delete(&g,nacRing);
1992    g = d;
1993    pIter(x);
1994  }
1995  while (y!=NULL)
1996  {
1997    number d=nacGcd(g,pGetCoeff(y), nacRing);
1998    if(nacIsOne(d))
1999    {
2000      n_Delete(&g,nacRing);
2001      n_Delete(&d,nacRing);
2002      naTest(pp);
2003      return;
2004    }
2005    n_Delete(&g,nacRing);
2006    g = d;
2007    pIter(y);
2008  }
2009  x=p->z;
2010  y=p->n;
2011  while (x!=NULL)
2012  {
2013    number d = nacIntDiv(pGetCoeff(x),g);
2014    napSetCoeff(x,d);
2015    pIter(x);
2016  }
2017  while (y!=NULL)
2018  {
2019    number d = nacIntDiv(pGetCoeff(y),g);
2020    napSetCoeff(y,d);
2021    pIter(y);
2022  }
2023  n_Delete(&g,nacRing);
2024  naTest(pp);
2025}
2026
2027/*2
2028* returns in result->n 1
2029* and in     result->z the lcm(a->z,b->n)
2030*/
2031number naLcm(number la, number lb, const ring r)
2032{
2033  lnumber result;
2034  lnumber a = (lnumber)la;
2035  lnumber b = (lnumber)lb;
2036  result = (lnumber)omAlloc0Bin(rnumber_bin);
2037  //if (((naMinimalPoly==NULL) && (naI==NULL)) || !naIsChar0)
2038  //{
2039  //  result->z = p_ISet(1,nacRing);
2040  //  return (number)result;
2041  //}
2042  //naNormalize(lb);
2043  naTest(la);
2044  naTest(lb);
2045  napoly x = p_Copy(a->z, r->algring);
2046  number t = napLcm(b->z); // get all denom of b->z
2047  if (!nacIsOne(t))
2048  {
2049    number bt, rr;
2050    napoly xx=x;
2051    while (xx!=NULL)
2052    {
2053      bt = nacGcd(t, pGetCoeff(xx), r->algring);
2054      rr = nacMult(t, pGetCoeff(xx));
2055      n_Delete(&pGetCoeff(xx),r->algring);
2056      pGetCoeff(xx) = nacDiv(rr, bt);
2057      nacNormalize(pGetCoeff(xx));
2058      n_Delete(&bt,r->algring);
2059      n_Delete(&rr,r->algring);
2060      pIter(xx);
2061    }
2062  }
2063  n_Delete(&t,r->algring);
2064  result->z = x;
2065#ifdef HAVE_FACTORY
2066  if (b->n!=NULL)
2067  {
2068    result->z=singclap_alglcm(result->z,b->n);
2069    p_Delete(&x,r->algring);
2070  }
2071#endif
2072  naTest(la);
2073  naTest(lb);
2074  naTest((number)result);
2075  return ((number)result);
2076}
2077
2078/*2
2079* input: a set of constant polynomials
2080* sets the global variable naI
2081*/
2082void naSetIdeal(ideal I)
2083{
2084  int i;
2085
2086  if (idIs0(I))
2087  {
2088    for (i=naI->anz-1; i>=0; i--)
2089      p_Delete(&naI->liste[i],nacRing);
2090    omFreeBin((ADDRESS)naI, snaIdeal_bin);
2091    naI=NULL;
2092  }
2093  else
2094  {
2095    lnumber h;
2096    number a;
2097    napoly x;
2098
2099    naI=(naIdeal)omAllocBin(snaIdeal_bin);
2100    naI->anz=IDELEMS(I);
2101    naI->liste=(napoly*)omAlloc(naI->anz*sizeof(napoly));
2102    for (i=IDELEMS(I)-1; i>=0; i--)
2103    {
2104      h=(lnumber)pGetCoeff(I->m[i]);
2105      /* We only need the enumerator of h, as we expect it to be a polynomial */
2106      naI->liste[i]=napCopy(h->z);
2107      /* If it isn't normalized (lc = 1) do this */
2108      if (!nacIsOne(pGetCoeff(naI->liste[i])))
2109      {
2110        x=naI->liste[i];
2111        nacNormalize(pGetCoeff(x));
2112        a=nacCopy(pGetCoeff(x));
2113        number aa=nacInvers(a);
2114        n_Delete(&a,nacRing);
2115        napMultN(x,aa);
2116        n_Delete(&aa,nacRing);
2117      }
2118    }
2119  }
2120}
2121
2122/*2
2123* map Z/p -> Q(a)
2124*/
2125number naMapP0(number c)
2126{
2127  if (npIsZero(c)) return NULL;
2128  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2129  l->s=2;
2130  l->z=(napoly)p_Init(nacRing);
2131  int i=(int)((long)c);
2132  if (i>((long)naMapRing->ch>>2)) i-=(long)naMapRing->ch;
2133  pGetCoeff(l->z)=nlInit(i, nacRing);
2134  l->n=NULL;
2135  return (number)l;
2136}
2137
2138/*2
2139* map Q -> Q(a)
2140*/
2141number naMap00(number c)
2142{
2143  if (nlIsZero(c)) return NULL;
2144  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2145  l->s=0;
2146  l->z=(napoly)p_Init(nacRing);
2147  pGetCoeff(l->z)=nlCopy(c);
2148  l->n=NULL;
2149  return (number)l;
2150}
2151
2152/*2
2153* map Z/p -> Z/p(a)
2154*/
2155number naMapPP(number c)
2156{
2157  if (npIsZero(c)) return NULL;
2158  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2159  l->s=2;
2160  l->z=(napoly)p_Init(nacRing);
2161  pGetCoeff(l->z)=c; /* omit npCopy, because npCopy is a no-op */
2162  l->n=NULL;
2163  return (number)l;
2164}
2165
2166/*2
2167* map Z/p' -> Z/p(a)
2168*/
2169number naMapPP1(number c)
2170{
2171  if (npIsZero(c)) return NULL;
2172  int i=(int)((long)c);
2173  if (i>(long)naMapRing->ch) i-=(long)naMapRing->ch;
2174  number n=npInit(i,naMapRing);
2175  if (npIsZero(n)) return NULL;
2176  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2177  l->s=2;
2178  l->z=(napoly)p_Init(nacRing);
2179  pGetCoeff(l->z)=n;
2180  l->n=NULL;
2181  return (number)l;
2182}
2183
2184/*2
2185* map Q -> Z/p(a)
2186*/
2187number naMap0P(number c)
2188{
2189  if (nlIsZero(c)) return NULL;
2190  number n=npInit(nlModP(c,npPrimeM),nacRing);
2191  if (npIsZero(n)) return NULL;
2192  npTest(n);
2193  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2194  l->s=2;
2195  l->z=(napoly)p_Init(nacRing);
2196  pGetCoeff(l->z)=n;
2197  l->n=NULL;
2198  return (number)l;
2199}
2200
2201static number (*nacMap)(number);
2202static int naParsToCopy;
2203static napoly napMap(napoly p)
2204{
2205  napoly w, a;
2206
2207  if (p==NULL) return NULL;
2208  a = w = (napoly)p_Init(nacRing);
2209  int i;
2210  for(i=1;i<=naParsToCopy;i++)
2211    napSetExp(a,i,napGetExpFrom(p,i,naMapRing));
2212  p_Setm(a,nacRing);
2213  pGetCoeff(w) = nacMap(pGetCoeff(p));
2214  loop
2215  {
2216    pIter(p);
2217    if (p==NULL) break;
2218    pNext(a) = (napoly)p_Init(nacRing);
2219    pIter(a);
2220    for(i=1;i<=naParsToCopy;i++)
2221      napSetExp(a,i,napGetExpFrom(p,i,naMapRing));
2222    p_Setm(a,nacRing);
2223    pGetCoeff(a) = nacMap(pGetCoeff(p));
2224  }
2225  pNext(a) = NULL;
2226  return w;
2227}
2228
2229static napoly napPerm(napoly p,const int *par_perm,const ring src_ring,const nMapFunc nMap)
2230{
2231  napoly w, a;
2232
2233  if (p==NULL) return NULL;
2234  w = (napoly)p_Init(nacRing);
2235  int i;
2236  BOOLEAN not_null=TRUE;
2237  loop
2238  {
2239    for(i=1;i<=rPar(src_ring);i++)
2240    {
2241      int e;
2242      if (par_perm!=NULL) e=par_perm[i-1];
2243      else                e=-i;
2244      int ee=napGetExpFrom(p,i,src_ring);
2245      if (e<0)
2246        napSetExp(w,-e,ee);
2247      else if (ee>0)
2248        not_null=FALSE;
2249    }
2250    pGetCoeff(w) = nMap(pGetCoeff(p));
2251    p_Setm(w,nacRing);
2252    pIter(p);
2253    if (!not_null)
2254    {
2255      if (p==NULL)
2256      {
2257        p_Delete(&w,nacRing);
2258        return NULL;
2259      }
2260      /* else continue*/
2261      n_Delete(&(pGetCoeff(w)),nacRing);
2262    }
2263    else
2264    {
2265      if (p==NULL) return w;
2266      else
2267      {
2268        pNext(w)=napPerm(p,par_perm,src_ring,nMap);
2269        return w;
2270      }
2271    }
2272  }
2273}
2274
2275/*2
2276* map _(a) -> _(b)
2277*/
2278number naMapQaQb(number c)
2279{
2280  if (c==NULL) return NULL;
2281  lnumber erg= (lnumber)omAlloc0Bin(rnumber_bin);
2282  lnumber src =(lnumber)c;
2283  erg->s=src->s;
2284  erg->z=napMap(src->z);
2285  erg->n=napMap(src->n);
2286  if (naMinimalPoly!=NULL)
2287  {
2288    if (p_GetExp(erg->z,1,nacRing) >= p_GetExp(naMinimalPoly,1,nacRing))
2289    {
2290      erg->z = napRemainder(erg->z, naMinimalPoly);
2291      if (erg->z==NULL)
2292      {
2293        number t_erg=(number)erg;
2294        naDelete(&t_erg,currRing);
2295        return (number)NULL;
2296      }
2297    }
2298    if (erg->n!=NULL)
2299    {
2300      if (p_GetExp(erg->n,1,nacRing) >= p_GetExp(naMinimalPoly,1,nacRing))
2301        erg->n = napRemainder(erg->n, naMinimalPoly);
2302      if ((p_LmIsConstant(erg->n,nacRing)) && nacIsOne(pGetCoeff(erg->n)))
2303        p_Delete(&(erg->n),nacRing);
2304    }
2305  }
2306  return (number)erg;
2307}
2308
2309nMapFunc naSetMap(const ring src, const ring dst)
2310{
2311  naMapRing=src;
2312  if (rField_is_Q_a(dst)) /* -> Q(a) */
2313  {
2314    if (rField_is_Q(src))
2315    {
2316      return naMap00;   /*Q -> Q(a)*/
2317    }
2318    if (rField_is_Zp(src))
2319    {
2320      return naMapP0;  /* Z/p -> Q(a)*/
2321    }
2322    if (rField_is_Q_a(src))
2323    {
2324      int i;
2325      naParsToCopy=0;
2326      for(i=0;i<rPar(src);i++)
2327      {
2328        if ((i>=rPar(dst))
2329        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2330           return NULL;
2331        naParsToCopy++;
2332      }
2333      nacMap=nacCopy;
2334      if ((naParsToCopy==rPar(dst))&&(naParsToCopy==rPar(src)))
2335        return naCopy;    /* Q(a) -> Q(a) */
2336      return naMapQaQb;   /* Q(a..) -> Q(a..) */
2337    }
2338  }
2339  /*-----------------------------------------------------*/
2340  if (rField_is_Zp_a(dst)) /* -> Z/p(a) */
2341  {
2342    if (rField_is_Q(src))
2343    {
2344      return naMap0P;   /*Q -> Z/p(a)*/
2345    }
2346    if (rField_is_Zp(src))
2347    {
2348      if (src->ch==dst->ch)
2349      {
2350        return naMapPP;  /* Z/p -> Z/p(a)*/
2351      }
2352      else
2353      {
2354        return naMapPP1;  /* Z/p' -> Z/p(a)*/
2355      }
2356    }
2357    if (rField_is_Zp_a(src))
2358    {
2359      if (rChar(src)==rChar(dst))
2360      {
2361        nacMap=nacCopy;
2362      }
2363      else
2364      {
2365        nacMap = npMapP;
2366      }
2367      int i;
2368      naParsToCopy=0;
2369      for(i=0;i<rPar(src);i++)
2370      {
2371        if ((i>=rPar(dst))
2372        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2373           return NULL;
2374        naParsToCopy++;
2375      }
2376      if ((naParsToCopy==rPar(dst))&&(naParsToCopy==rPar(src))
2377      && (nacMap==nacCopy))
2378        return naCopy;    /* Z/p(a) -> Z/p(a) */
2379      return naMapQaQb;   /* Z/p(a),Z/p'(a) -> Z/p(b)*/
2380    }
2381  }
2382  return NULL;      /* default */
2383}
2384
2385/*2
2386* convert a napoly number into a poly
2387*/
2388poly naPermNumber(number z, int * par_perm, int P, ring oldRing)
2389{
2390  if (z==NULL) return NULL;
2391  poly res=NULL;
2392  poly p;
2393  napoly za=((lnumber)z)->z;
2394  napoly zb=((lnumber)z)->n;
2395  nMapFunc nMap=naSetMap(oldRing,currRing);
2396  if (currRing->parameter!=NULL)
2397    nMap=currRing->algring->cf->cfSetMap(oldRing->algring, nacRing);
2398  else
2399    nMap=currRing->cf->cfSetMap(oldRing->algring, currRing);
2400  if (nMap==NULL) return NULL; /* emergency exit only */
2401  do
2402  {
2403    p = pInit();
2404    pNext(p)=NULL;
2405    nNew(&pGetCoeff(p));
2406    int i;
2407    for(i=pVariables;i;i--)
2408       pSetExp(p,i, 0);
2409    pSetComp(p, 0);
2410    napoly pa=NULL;
2411    lnumber pan;
2412    if (currRing->parameter!=NULL)
2413    {
2414      assume(oldRing->algring!=NULL);
2415      pGetCoeff(p)=(number)omAlloc0Bin(rnumber_bin);
2416      pan=(lnumber)pGetCoeff(p);
2417      pan->s=2;
2418      pan->z=napInitz(nMap(pGetCoeff(za)));
2419      pa=pan->z;
2420    }
2421    else
2422    {
2423      pGetCoeff(p)=nMap(pGetCoeff(za));
2424    }
2425    for(i=0;i<P;i++)
2426    {
2427      if(napGetExpFrom(za,i+1,oldRing)!=0)
2428      {
2429        if(par_perm==NULL)
2430        {
2431          if ((rPar(currRing)>=i) && (pa!=NULL))
2432          {
2433            napSetExp(pa,i+1,napGetExpFrom(za,i+1,oldRing));
2434            p_Setm(pa,nacRing);
2435          }
2436          else
2437          {
2438            pDelete(&p);
2439            break;
2440          }
2441        }
2442        else if(par_perm[i]>0)
2443          pSetExp(p,par_perm[i],napGetExpFrom(za,i+1,oldRing));
2444        else if((par_perm[i]<0)&&(pa!=NULL))
2445        {
2446          napSetExp(pa,-par_perm[i], napGetExpFrom(za,i+1,oldRing));
2447          p_Setm(pa,nacRing);
2448        }
2449        else
2450        {
2451          pDelete(&p);
2452          break;
2453        }
2454      }
2455    }
2456    if (p!=NULL)
2457    {
2458      pSetm(p);
2459      if (zb!=NULL)
2460      {
2461        if  (currRing->P>0)
2462        {
2463          pan->n=napPerm(zb,par_perm,oldRing,nMap);
2464          if(pan->n==NULL) /* error in mapping or mapping to variable */
2465            pDelete(&p);
2466        }
2467        else
2468          pDelete(&p);
2469      }
2470      pTest(p);
2471      res=pAdd(res,p);
2472    }
2473    pIter(za);
2474  }
2475  while (za!=NULL);
2476  pTest(res);
2477  return res;
2478}
2479
2480number   naGetDenom(number &n, const ring r)
2481{
2482  lnumber x=(lnumber)n;
2483  if (x->n!=NULL)
2484  {
2485    lnumber rr=(lnumber)omAlloc0Bin(rnumber_bin);
2486    rr->z=p_Copy(x->n,r->algring);
2487    rr->s = 2;
2488    return (number)rr;
2489  }
2490  return n_Init(1,r);
2491}
2492
2493number   naGetNumerator(number &n, const ring r)
2494{
2495  lnumber x=(lnumber)n;
2496  lnumber rr=(lnumber)omAlloc0Bin(rnumber_bin);
2497  rr->z=p_Copy(x->z,r->algring);
2498  rr->s = 2;
2499  return (number)rr;
2500}
2501
2502#ifdef LDEBUG
2503BOOLEAN naDBTest(number a, const char *f,const int l)
2504{
2505  lnumber x=(lnumber)a;
2506  if (x == NULL)
2507    return TRUE;
2508  omCheckAddrSize(a, sizeof(snumber));
2509  napoly p = x->z;
2510  if (p==NULL)
2511  {
2512    Print("0/* in %s:%d\n",f,l);
2513    return FALSE;
2514  }
2515  while(p!=NULL)
2516  {
2517    if ((naIsChar0 && nlIsZero(pGetCoeff(p)))
2518    || ((!naIsChar0) && npIsZero(pGetCoeff(p))))
2519    {
2520      Print("coeff 0 in %s:%d\n",f,l);
2521      return FALSE;
2522    }
2523    if((naMinimalPoly!=NULL)
2524    &&(p_GetExp(p,1,nacRing)>p_GetExp(naMinimalPoly,1,nacRing))
2525    &&(p!=naMinimalPoly))
2526    {
2527      Print("deg>minpoly in %s:%d\n",f,l);
2528      return FALSE;
2529    }
2530    //if (naIsChar0 && (((int)p->ko &3) == 0) && (p->ko->s==0) && (x->s==2))
2531    //{
2532    //  Print("normalized with non-normal coeffs in %s:%d\n",f,l);
2533    //  return FALSE;
2534    //}
2535    if (naIsChar0 && !(nlDBTest(pGetCoeff(p),f,l)))
2536      return FALSE;
2537    pIter(p);
2538  }
2539  p = x->n;
2540  while(p!=NULL)
2541  {
2542    if (naIsChar0 && !(nlDBTest(pGetCoeff(p),f,l)))
2543      return FALSE;
2544    pIter(p);
2545  }
2546  return TRUE;
2547}
2548#endif
Note: See TracBrowser for help on using the repository browser.