source: git/kernel/longalg.cc @ fef045c

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