source: git/libpolys/polys/nc/old.gring.cc @ 8179468

spielwiese
Last change on this file since 8179468 was 8179468, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Better forward declarations and includes for bucket-related stuff TODO: refine?
  • Property mode set to 100644
File size: 78.9 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    gring.cc
6 *  Purpose: noncommutative kernel procedures
7 *  Author:  levandov (Viktor Levandovsky)
8 *  Created: 8/00 - 11/00
9 *******************************************************************/
10
11#define MYTEST 0
12#define OUTPUT 0
13
14#if MYTEST
15#define OM_CHECK 4
16#define OM_TRACK 5
17#endif
18
19#include "config.h"
20#include <misc/auxiliary.h>
21
22#ifdef HAVE_PLURAL
23
24# define PLURAL_INTERNAL_DECLARATIONS
25#include "nc.h"
26#include "sca.h"
27#include "gb_hack.h"
28
29#include <polys/monomials/ring.h>
30   
31#include <coeffs/numbers.h>
32#include <polys/coeffrings.h>
33
34// #include <polys/febase.h>
35#include <misc/options.h>
36
37#include <polys/monomials/ring.h>
38#include <polys/monomials/p_polys.h>
39
40#include <polys/simpleideals.h>
41#include <polys/matpol.h>
42
43#include <polys/kbuckets.h>
44#include <polys/sbuckets.h>
45
46// #include <polys/kstd1.h>
47#include <polys/prCopy.h>
48
49#include <polys/operations/p_Mult_q.h>
50// dirty tricks:
51#include <polys/templates/p_MemAdd.h>
52
53// #include <polys/pInline1.h>
54
55
56#include "summator.h"
57
58#include "ncSAMult.h" // for CMultiplier etc classes
59#include "ncSAFormula.h" // for CFormulaPowerMultiplier and enum Enum_ncSAType
60
61// #ifdef HAVE_RATGRING
62// #include <polys/ratgring.h>
63// #endif
64
65
66/* copy : */
67poly nc_p_CopyGet(poly a, const ring r);
68poly nc_p_CopyPut(poly a, const ring r);
69
70poly nc_p_Bracket_qq(poly p, const poly q, const ring r);
71
72// only SCA can be used by default, formulas are off by default
73int  iNCExtensions = SCAMASK | NOFORMULAMASK; 
74
75int& getNCExtensions()
76{
77  return (iNCExtensions);
78}
79
80int setNCExtensions(int iMask)
81{
82  const int iOld = getNCExtensions();
83  getNCExtensions() = iMask;
84  return (iOld);
85}
86
87bool ncExtensions(int iMask) //  = 0x0FFFF
88{
89  return ((getNCExtensions() & iMask) == iMask);
90}
91
92/* global nc_macros : */
93
94#define freeT(A,v) omFreeSize((ADDRESS)A,(v+1)*sizeof(int))
95#define freeN(A,k) omFreeSize((ADDRESS)A,k*sizeof(number))
96
97
98// some forward declarations:
99
100
101// polynomial multiplication functions for p_Procs :
102poly gnc_pp_Mult_mm(const poly p, const poly m, const ring r, poly &last);
103poly gnc_p_Mult_mm(poly p, const poly m, const ring r);
104poly gnc_mm_Mult_p(const poly m, poly p, const ring r);
105poly gnc_mm_Mult_pp(const poly m, const poly p, const ring r);
106
107
108/* syzygies : */
109poly gnc_CreateSpolyOld(const poly p1, const poly p2/*, poly spNoether*/, const ring r);
110poly gnc_ReduceSpolyOld(const poly p1, poly p2/*, poly spNoether*/, const ring r);
111
112poly gnc_CreateSpolyNew(const poly p1, const poly p2/*, poly spNoether*/, const ring r);
113poly gnc_ReduceSpolyNew(const poly p1, poly p2/*, poly spNoether*/, const ring r);
114
115
116
117void gnc_kBucketPolyRedNew(kBucket_pt b, poly p, number *c);
118void gnc_kBucketPolyRed_ZNew(kBucket_pt b, poly p, number *c);
119
120void gnc_kBucketPolyRedOld(kBucket_pt b, poly p, number *c);
121void gnc_kBucketPolyRed_ZOld(kBucket_pt b, poly p, number *c);
122
123
124// poly gnc_ReduceSpolyNew(poly p1, poly p2, poly spNoether, const ring r);
125// void gnc_ReduceSpolyTail(poly p1, poly q, poly q2, poly spNoether, const ring r);
126
127// void nc_kBucketPolyRed(kBucket_pt b, poly p);
128
129void nc_CleanUp(nc_struct* p); // just free memory!
130void nc_rCleanUp(ring r); // smaller than kill: just free mem
131
132
133#if 0
134// deprecated functions:
135//  poly gnc_p_Minus_mm_Mult_qq_ign(poly p, const poly m, poly q, int & d1, poly d2, const ring ri, poly &d3);
136//  poly gnc_p_Minus_mm_Mult_qq(poly p, const poly m, poly q, const ring r);
137//  poly nc_p_Minus_mm_Mult_qq(poly p, const poly m, const poly q, int &lp, int lq, const ring r);
138//  poly nc_p_Plus_mm_Mult_qq (poly p, const poly m, const poly q, int &lp, int lq, const ring r);
139#endif
140
141
142
143/*2
144* returns the LCM of the head terms of a and b
145* without coefficient!!!
146*/
147poly p_Lcm(const poly a, const poly b, const long lCompM, const ring r)
148{
149  poly m = // p_One( r);
150          p_Init(r);
151
152  const int pVariables = r->N;
153
154  for (int i = pVariables; i!=0; i--)
155  {
156    const int lExpA = p_GetExp (a, i, r);
157    const int lExpB = p_GetExp (b, i, r);
158
159    p_SetExp (m, i, si_max(lExpA, lExpB), r);
160  }
161
162  p_SetComp (m, lCompM, r);
163
164  p_Setm(m,r);
165
166#ifdef PDEBUG
167//  p_Test(m,r);
168#endif
169
170  n_New(&(p_GetCoeff(m, r)), r);
171
172  return(m);
173}
174
175poly p_Lcm(const poly a, const poly b, const ring r)
176{
177#ifdef PDEBUG
178  p_Test(a, r);
179  p_Test(b, r);
180#endif
181
182  const long lCompP1 = p_GetComp(a, r);
183  const long lCompP2 = p_GetComp(b, r);
184
185  const poly m = p_Lcm(a, b, si_max(lCompP1, lCompP2), r);
186
187#ifdef PDEBUG
188//  p_Test(m,r);
189#endif
190  return(m);
191}
192
193
194
195///////////////////////////////////////////////////////////////////////////////
196poly nc_p_Minus_mm_Mult_qq(poly p, const poly m, const poly q, int &shorter,
197                                    const poly, const ring r)
198{
199  poly mc  = p_Neg( p_Copy(m, r), r );
200  poly mmc = nc_mm_Mult_pp( mc, q, r );
201  p_Delete(&mc, r);
202
203  int org_p=pLength(p);
204  int org_q=pLength(q);
205
206  p = p_Add_q(p, mmc, r);
207
208  shorter = pLength(p)-org_p-org_q; // ring independent!
209
210  return(p);
211}
212
213// returns p + m*q destroys p, const: q, m
214poly nc_p_Plus_mm_Mult_qq(poly p, const poly m, const poly q, int &lp,
215                              const int, const ring r)
216{
217  p = p_Add_q(p, nc_mm_Mult_pp( m, q, r ), r);
218
219  lp = pLength(p);
220
221  return(p);
222}
223
224#if 0
225poly gnc_p_Minus_mm_Mult_qq_ign(poly p, const poly m, poly q, int & d1, poly d2, const ring r, poly &d3)
226{
227  poly t;
228  int  i;
229
230  return gnc_p_Minus_mm_Mult_qq(p, m, q, d1, i, t, r);
231}
232#endif
233
234
235//----------- auxiliary routines--------------------------
236poly _gnc_p_Mult_q(poly p, poly q, const int copy, const ring r) // not used anymore!
237  /* destroy p,q unless copy=1 */
238{
239  poly res=NULL;
240  poly qq,pp;
241  if (copy)
242  {
243    qq=p_Copy(q,r);
244    pp=p_Copy(p,r);
245  }
246  else
247  {
248    qq=q;
249    pp=p;
250  }
251  while (qq!=NULL)
252  {
253    res=p_Add_q(res, pp_Mult_mm(pp, qq, r), r); // p_Head(qq, r)?
254    qq=p_LmDeleteAndNext(qq,r);
255  }
256  p_Delete(&pp,r);
257  return(res);
258}
259
260// return pPolyP * pPolyQ; destroy or reuse pPolyP and pPolyQ
261poly _nc_p_Mult_q(poly pPolyP, poly pPolyQ, const ring rRing)
262{
263  assume( rIsPluralRing(rRing) );
264#ifdef PDEBUG
265  p_Test(pPolyP, rRing);
266  p_Test(pPolyQ, rRing);
267#endif
268#ifdef RDEBUG
269  rTest(rRing);
270#endif
271
272  int lp, lq;
273
274  pqLength(pPolyP, pPolyQ, lp, lq, MIN_LENGTH_BUCKET);
275
276  bool bUsePolynomial = TEST_OPT_NOT_BUCKETS || (si_max(lp, lq) < MIN_LENGTH_BUCKET); // ???
277
278  CPolynomialSummator sum(rRing, bUsePolynomial);
279
280  if (lq <= lp) // ?
281  {
282    // always length(q) times "p * q[j]"
283    for( ; pPolyQ!=NULL; pPolyQ  = p_LmDeleteAndNext( pPolyQ, rRing ) )
284      sum += pp_Mult_mm( pPolyP, pPolyQ, rRing);
285
286    p_Delete( &pPolyP, rRing );
287  } else
288  {
289    // always length(p) times "p[i] * q"
290    for( ; pPolyP!=NULL; pPolyP  = p_LmDeleteAndNext( pPolyP, rRing ) )
291      sum += nc_mm_Mult_pp( pPolyP, pPolyQ, rRing);
292
293    p_Delete( &pPolyQ, rRing );
294  }
295
296  return(sum);
297}
298
299// return pPolyP * pPolyQ; preserve pPolyP and pPolyQ
300poly _nc_pp_Mult_qq(const poly pPolyP, const poly pPolyQ, const ring rRing)
301{
302  assume( rIsPluralRing(rRing) );
303#ifdef PDEBUG
304  p_Test(pPolyP, rRing);
305  p_Test(pPolyQ, rRing);
306#endif
307#ifdef RDEBUG
308  rTest(rRing);
309#endif
310
311  int lp, lq;
312
313  pqLength(pPolyP, pPolyQ, lp, lq, MIN_LENGTH_BUCKET);
314
315  bool bUsePolynomial = TEST_OPT_NOT_BUCKETS || (si_max(lp, lq) < MIN_LENGTH_BUCKET); // ???
316
317  CPolynomialSummator sum(rRing, bUsePolynomial);
318
319  if (lq <= lp) // ?
320  {
321    // always length(q) times "p * q[j]"
322    for( poly q = pPolyQ; q !=NULL; q = pNext(q) )
323      sum += pp_Mult_mm(pPolyP, q, rRing);
324  } else
325  {
326    // always length(p) times "p[i] * q"
327    for( poly p = pPolyP; p !=NULL; p = pNext(p) )
328      sum += nc_mm_Mult_pp( p, pPolyQ, rRing);
329  }
330
331  return(sum);
332}
333
334
335
336poly gnc_mm_Mult_nn (int *F, int *G, const ring r);
337poly gnc_mm_Mult_uu (int *F,int jG,int bG, const ring r);
338
339/* #define nc_uu_Mult_ww nc_uu_Mult_ww_vert */
340poly gnc_uu_Mult_ww (int i, int a, int j, int b, const ring r);
341/* poly nc_uu_Mult_ww_vert (int i, int a, int j, int b, const ring r); */
342/* poly nc_uu_Mult_ww_horvert (int i, int a, int j, int b, const ring r); */
343/* poly nc_uu_Mult_ww_hvdiag (int i, int a, int j, int b, const ring r); */
344/* not written yet */
345
346
347poly gnc_p_Mult_mm_Common(poly p, const poly m, int side, const ring r)
348/* p is poly, m is mono with coeff, destroys p */
349/* if side==1, computes p_Mult_mm; otherwise, mm_Mult_p */
350{
351  if ((p==NULL) || (m==NULL)) return NULL;
352  /*  if (pNext(p)==NULL) return(nc_mm_Mult_nn(p,pCopy(m),r)); */
353  /* excluded  - the cycle will do it anyway - OK. */
354  if (p_IsConstant(m,r)) return(p_Mult_nn(p,p_GetCoeff(m,r),r));
355
356#ifdef PDEBUG
357  p_Test(p,r);
358  p_Test(m,r);
359#endif
360  poly v=NULL;
361  int rN=r->N;
362  int *P=(int *)omAlloc0((rN+1)*sizeof(int));
363  int *M=(int *)omAlloc0((rN+1)*sizeof(int));
364  /* coefficients: */
365  number cP,cM,cOut;
366  p_GetExpV(m, M, r);
367  cM=p_GetCoeff(m,r);
368  /* components:*/
369  const int expM=p_GetComp(m,r);
370  int expP=0;
371  int expOut=0;
372  /* bucket constraints: */
373  int UseBuckets=1;
374  if (pLength(p)< MIN_LENGTH_BUCKET || TEST_OPT_NOT_BUCKETS) UseBuckets=0;
375
376  CPolynomialSummator sum(r, UseBuckets == 0);
377
378  while (p!=NULL)
379  {
380#ifdef PDEBUG
381    p_Test(p,r);
382#endif
383    expP=p_GetComp(p,r);
384    if (expP==0)
385    {
386      expOut=expM;
387    }
388    else
389    {
390      if (expM==0)
391      {
392        expOut=expP;
393#ifdef PDEBUG
394        if (side)
395        {
396          Print("gnc_p_Mult_mm: Multiplication in the left module from the right");
397        }
398#endif
399      }
400      else
401      {
402        /* REPORT_ERROR */
403#ifdef PDEBUG
404        const char* s;
405        if (side==1) s="gnc_p_Mult_mm";
406        else s="gnc_mm_Mult_p";
407        Print("%s: exponent mismatch %d and %d\n",s,expP,expM);
408#endif
409        expOut=0;
410      }
411    }
412    p_GetExpV(p,P,r);
413    cP=p_GetCoeff(p,r);
414    cOut=n_Mult(cP,cM,r);
415    if (side==1)
416    {
417      v = gnc_mm_Mult_nn(P, M, r);
418    }
419    else
420    {
421      v = gnc_mm_Mult_nn(M, P, r);
422    }
423    v = p_Mult_nn(v,cOut,r);
424    n_Delete(&cOut,r);
425    p_SetCompP(v,expOut,r);
426
427    sum += v;
428
429    p_LmDelete(&p,r);
430  }
431  freeT(P,rN);
432  freeT(M,rN);
433
434  return(sum);
435}
436
437/* poly functions defined in p_Procs : */
438poly gnc_pp_Mult_mm(const poly p, const poly m, const ring r)
439{
440  return( gnc_p_Mult_mm_Common(p_Copy(p,r), m, 1, r) );
441}
442
443poly gnc_p_Mult_mm(poly p, const poly m, const ring r)
444{
445  return( gnc_p_Mult_mm_Common(p, m, 1, r) );
446}
447
448poly gnc_mm_Mult_p(const poly m, poly p, const ring r)
449{
450  return( gnc_p_Mult_mm_Common(p, m, 0, r) );
451}
452
453poly gnc_mm_Mult_pp(const poly m, const poly p, const ring r)
454{
455  return( gnc_p_Mult_mm_Common(p_Copy(p,r), m, 0, r) );
456}
457
458
459
460poly gnc_mm_Mult_nn(int *F0, int *G0, const ring r)
461/* destroys nothing, no coeffs and exps */
462{
463  poly out=NULL;
464  int i,j;
465  int iF,jG,iG;
466  int rN=r->N;
467  int ExpSize=(((rN+1)*sizeof(int)+sizeof(long)-1)/sizeof(long))*sizeof(long);
468
469  int *F=(int *)omAlloc0((rN+1)*sizeof(int));
470  int *G=(int *)omAlloc0((rN+1)*sizeof(int));
471
472  memcpy(F, F0,(rN+1)*sizeof(int));
473  // pExpVectorCopy(F,F0);
474  memcpy(G, G0,(rN+1)*sizeof(int));
475  //  pExpVectorCopy(G,G0);
476  F[0]=0; /* important for p_MemAdd */
477  G[0]=0;
478
479  iF=rN;
480  while ((F[iF]==0)&&(iF>=1)) iF--; /* last exp_num of F */
481  if (iF==0) /* F0 is zero vector */
482  {
483    out=p_One(r);
484    p_SetExpV(out,G0,r);
485    p_Setm(out,r);
486    freeT(F,rN);
487    freeT(G,rN);
488    return(out);
489  }
490  jG=1;
491  while ((G[jG]==0)&&(jG<rN)) jG++;  /* first exp_num of G */
492  iG=rN;
493  while ((G[iG]==0)&&(iG>1)) iG--;  /* last exp_num of G */
494
495  out=p_One(r);
496
497  if (iF<=jG)
498    /* i.e. no mixed exp_num , MERGE case */
499  {
500    p_MemAdd_LengthGeneral(F, G, ExpSize/sizeof(long));
501    p_SetExpV(out,F,r);
502    p_Setm(out,r);
503    //    omFreeSize((ADDRESS)F,ExpSize);
504    freeT(F,rN);
505    freeT(G,rN);
506    return(out);
507  }
508
509  number cff=n_Init(1,r);
510  number tmp_num=NULL;
511  int cpower=0;
512
513  if (ncRingType(r)==nc_skew)
514  {
515    if (r->GetNC()->IsSkewConstant==1)
516    {
517      int tpower=0;
518      for(j=jG; j<=iG; j++)
519      {
520        if (G[j]!=0)
521        {
522          cpower = 0;
523          for(i=j+1; i<=iF; i++)
524          {
525            cpower = cpower + F[i];
526          }
527          cpower = cpower*G[j]; // bug! here may happen an arithmetic overflow!!!
528          tpower = tpower + cpower;
529        }
530      }
531      cff = n_Copy(p_GetCoeff(MATELEM(r->GetNC()->COM,1,2),r),r);
532      n_Power(cff,tpower,&tmp_num, r);
533      n_Delete(&cff,r);
534      cff = tmp_num;
535    }
536    else /* skew commutative with nonequal coeffs */
537    {
538      number totcff=n_Init(1,r);
539      for(j=jG; j<=iG; j++)
540      {
541        if (G[j]!=0)
542        {
543          cpower = 0;
544          for(i=j+1; i<=iF; i++)
545          {
546            if (F[i]!=0)
547            {
548              cpower = F[i]*G[j]; // bug! overflow danger!!!
549              cff = n_Copy(p_GetCoeff(MATELEM(r->GetNC()->COM,j,i),r),r);
550              n_Power(cff,cpower,&tmp_num, r);
551              cff = n_Mult(totcff,tmp_num, r);
552              n_Delete(&totcff, r);
553              n_Delete(&tmp_num, r);
554              totcff = n_Copy(cff,r);
555              n_Delete(&cff,r);
556            }
557          } /* end 2nd for */
558        }
559      }
560      cff=totcff;
561    }
562    p_MemAdd_LengthGeneral(F, G, ExpSize/sizeof(long));
563    p_SetExpV(out,F,r);
564    p_Setm(out,r);
565    p_SetCoeff(out,cff,r);
566    //    p_MemAdd_NegWeightAdjust(p, r); ??? do we need this?
567    freeT(F,rN);
568    freeT(G,rN);
569    return(out);
570  } /* end nc_skew */
571
572  /* now we have to destroy out! */
573  p_Delete(&out,r);
574
575  if (iG==jG)
576    /* g is univariate monomial */
577  {
578    /*    if (ri->GetNC()->type==nc_skew) -- postpone to TU */
579    out = gnc_mm_Mult_uu(F,jG,G[jG],r);
580    freeT(F,rN);
581    freeT(G,rN);
582    return(out);
583  }
584
585  int *Prv=(int *)omAlloc0((rN+1)*sizeof(int));
586  int *Nxt=(int *)omAlloc0((rN+1)*sizeof(int));
587
588  int *log=(int *)omAlloc0((rN+1)*sizeof(int));
589  int cnt=0; int cnf=0;
590
591  /* splitting F wrt jG */
592  for (i=1;i<=jG;i++)
593  {
594    Prv[i]=F[i]; Nxt[i]=0; /* mult at the very end */
595    if (F[i]!=0) cnf++;
596  }
597
598  if (cnf==0) freeT(Prv,rN);
599
600  for (i=jG+1;i<=rN;i++)
601  {
602    Nxt[i]=F[i];
603    /*    if (cnf!=0)  Prv[i]=0; */
604    if (F[i]!=0)
605    {
606      cnt++;
607    }              /* effective part for F */
608  }
609  freeT(F,rN);
610  cnt=0;
611
612  for (i=1;i<=rN;i++)
613  {
614    if (G[i]!=0)
615    {
616     cnt++;
617     log[cnt]=i;
618     }               /* lG for G */
619   }
620
621/* ---------------------- A C T I O N ------------------------ */
622  poly D=NULL;
623  poly Rout=NULL;
624  number *c=(number *)omAlloc0((rN+1)*sizeof(number));
625  c[0]=n_Init(1,r);
626
627  int *Op=Nxt;
628  int *On=G;
629  int *U=(int *)omAlloc0((rN+1)*sizeof(int));
630
631  for (i=jG;i<=rN;i++) U[i]=Nxt[i]+G[i];  /* make leadterm */
632  Nxt=NULL;
633  G=NULL;
634  cnt=1;
635  int t=0;
636  poly w=NULL;
637  poly Pn=p_One(r);
638  p_SetExpV(Pn,On,r);
639  p_Setm(Pn,r);
640
641  while (On[iG]!=0)
642  {
643     t=log[cnt];
644
645     w=gnc_mm_Mult_uu(Op,t,On[t],r);
646     c[cnt]=n_Mult(c[cnt-1],p_GetCoeff(w,r),r);
647     D = pNext(w);  /* getting coef and rest D */
648     p_LmDelete(&w,r);
649     w=NULL;
650
651     Op[t] += On[t];   /* update exp_vectors */
652     On[t] = 0;
653
654     if (t!=iG)    /* not the last step */
655     {
656       p_SetExpV(Pn,On,r);
657       p_Setm(Pn,r);
658#ifdef PDEBUG
659       p_Test(Pn,r);
660#endif
661
662//       if (pNext(D)==0)
663// is D a monomial? could be postponed higher
664//       {
665//       Rout=nc_mm_Mult_nn(D,Pn,r);
666//       }
667//       else
668//       {
669       Rout=gnc_p_Mult_mm(D,Pn,r);
670//       }
671     }
672     else
673     {
674       Rout=D;
675       D=NULL;
676     }
677
678     if (Rout!=NULL)
679     {
680       Rout=p_Mult_nn(Rout,c[cnt-1],r); /* Rest is ready */
681       out=p_Add_q(out,Rout,r);
682       Rout=NULL;
683     }
684     cnt++;
685  }
686  freeT(On,rN);
687  freeT(Op,rN);
688  p_Delete(&Pn,r);
689  omFreeSize((ADDRESS)log,(rN+1)*sizeof(int));
690
691  /* leadterm and Prv-part */
692
693  Rout=p_One(r);
694  /* U is lead.monomial */
695  U[0]=0;
696  p_SetExpV(Rout,U,r);
697  p_Setm(Rout,r);  /* use again this name Rout */
698#ifdef PDEBUG
699  p_Test(Rout,r);
700#endif
701  p_SetCoeff(Rout,c[cnt-1],r);
702  out=p_Add_q(out,Rout,r);
703  freeT(U,rN);
704  freeN(c,rN+1);
705  if (cnf!=0)  /* Prv is non-zero vector */
706  {
707    Rout=p_One(r);
708    Prv[0]=0;
709    p_SetExpV(Rout,Prv,r);
710    p_Setm(Rout,r);
711#ifdef PDEBUG
712    p_Test(Rout,r);
713#endif
714    out=gnc_mm_Mult_p(Rout,out,r); /* getting the final result */
715    freeT(Prv,rN);
716    p_Delete(&Rout,r);
717  }
718  return (out);
719}
720
721
722poly gnc_mm_Mult_uu(int *F,int jG,int bG, const ring r)
723/* f=mono(F),g=(x_iG)^bG */
724{
725  poly out=NULL;
726  int i;
727  number num=NULL;
728
729  int rN=r->N;
730  int iF=r->N;
731  while ((F[iF]==0)&&(iF>0)) iF-- ;   /* last exponent_num of F */
732
733  if (iF==0)  /* F==zero vector in other words */
734  {
735   out=p_One(r);
736   p_SetExp(out,jG,bG,r);
737   p_Setm(out,r);
738   return(out);
739  }
740
741  int jF=1;
742  while ((F[jF]==0)&&(jF<=rN)) jF++;  /* first exp of F */
743
744  if (iF<=jG)                       /* i.e. no mixed exp_num */
745  {
746    out=p_One(r);
747    F[jG]=F[jG]+bG;
748    p_SetExpV(out,F,r);
749    p_Setm(out,r);
750    return(out);
751  }
752
753  if (iF==jF)              /* uni times uni */
754  {
755   out=gnc_uu_Mult_ww(iF,F[iF],jG,bG,r);
756   return(out);
757  }
758
759  /* Now: F is mono with >=2 exponents, jG<iF */
760  /* check the quasi-commutative case */
761//   matrix LCOM=r->GetNC()->COM;
762//   number rescoef=n_Init(1,r);
763//   number tmpcoef=n_Init(1,r);
764//   int tmpint;
765//   i=iF;
766//   while (i>=jG+1)
767//     /* all the non-zero exponents */
768//   {
769//     if (MATELEM(LCOM,jG,i)!=NULL)
770//     {
771//       tmpcoef=pGetCoeff(MATELEM(LCOM,jG,i));
772//       tmpint=(int)F[i];
773//       nPower(tmpcoef,F[i],&tmpcoef);
774//       rescoef=nMult(rescoef,tmpcoef);
775//       i--;
776//     }
777//     else
778//     {
779//       if (F[i]!=0) break;
780//     }
781//   }
782//   if (iF==i)
783//   /* no action took place*/
784//   {
785
786//   }
787//   else /* power the result up to bG */
788//   {
789//     nPower(rescoef,bG,&rescoef);
790//     /* + cleanup, post-processing */
791//   }
792
793  int *Prv=(int*)omAlloc0((rN+1)*sizeof(int));
794  int *Nxt=(int*)omAlloc0((rN+1)*sizeof(int));
795  int *lF=(int *)omAlloc0((rN+1)*sizeof(int));
796
797  int cnt=0; int cnf=0;
798  /* splitting F wrt jG */
799  for (i=1;i<=jG;i++) /* mult at the very end */
800  {
801    Prv[i]=F[i]; Nxt[i]=0;
802    if (F[i]!=0) cnf++;
803  }
804
805  if (cnf==0)
806  {
807    freeT(Prv,rN); Prv = NULL;
808  }
809
810  for (i=jG+1;i<=rN;i++)
811  {
812    Nxt[i]=F[i];
813    if (cnf!=0) { Prv[i]=0;}
814    if (F[i]!=0)
815    {
816      cnt++;
817      lF[cnt]=i;
818    }                 /* eff_part,lF_for_F */
819  }
820
821  if (cnt==1) /* Nxt consists of 1 nonzero el-t only */
822  {
823    int q=lF[1];
824    poly Rout=p_One(r);
825    out=gnc_uu_Mult_ww(q,Nxt[q],jG,bG,r);
826
827    freeT(Nxt,rN);  Nxt = NULL;
828
829    if (cnf!=0)
830    {
831       Prv[0]=0;
832       p_SetExpV(Rout,Prv,r);
833       p_Setm(Rout,r);
834
835#ifdef PDEBUG
836       p_Test(Rout,r);
837#endif
838
839       freeT(Prv,rN);
840       Prv = NULL;
841
842       out=gnc_mm_Mult_p(Rout,out,r); /* getting the final result */
843    }
844
845    freeT(lF,rN);
846    lF = NULL;
847
848    p_Delete(&Rout,r);
849
850    assume(Nxt == NULL);
851    assume(lF == NULL);
852    assume(Prv == NULL);
853
854    return (out);
855  }
856/* -------------------- MAIN ACTION --------------------- */
857
858  poly D=NULL;
859  poly Rout=NULL;
860  number *c=(number *)omAlloc0((cnt+2)*sizeof(number));
861  c[cnt+1]=n_Init(1,r);
862  i=cnt+2;         /* later in freeN */
863  int *Op=Nxt;
864
865  int *On=(int *)omAlloc0((rN+1)*sizeof(int));
866  int *U=(int *)omAlloc0((rN+1)*sizeof(int));
867
868
869  //  pExpVectorCopy(U,Nxt);
870  memcpy(U, Nxt,(rN+1)*sizeof(int));
871  U[jG] = U[jG] + bG;
872
873  /* Op=Nxt and initial On=(0); */
874  Nxt=NULL;
875
876  poly Pp;
877  poly Pn;
878  int t=0;
879  int first=lF[1];
880  int nlast=lF[cnt];
881  int kk=0;
882  /*  cnt--;   */
883  /* now lF[cnt] should be <=iF-1 */
884
885  while (Op[first]!=0)
886  {
887     t=lF[cnt];   /* cnt as it was computed */
888
889     poly w=gnc_uu_Mult_ww(t,Op[t],jG,bG,r);
890     c[cnt]=n_Copy(p_GetCoeff(w,r),r);
891     D = pNext(w);  /* getting coef and rest D */
892     p_LmDelete(&w,r);
893     w=NULL;
894
895     Op[t]= 0;
896     Pp=p_One(r);
897     p_SetExpV(Pp,Op,r);
898     p_Setm(Pp,r);
899
900     if (t<nlast)
901     {
902       kk=lF[cnt+1];
903       On[kk]=F[kk];
904
905       Pn=p_One(r);
906       p_SetExpV(Pn,On,r);
907       p_Setm(Pn,r);
908
909       if (t!=first)   /* typical expr */
910       {
911         w=gnc_p_Mult_mm(D,Pn,r);
912         Rout=gnc_mm_Mult_p(Pp,w,r);
913         w=NULL;
914       }
915       else                   /* last step */
916       {
917         On[t]=0;
918         p_SetExpV(Pn,On,r);
919         p_Setm(Pn,r);
920         Rout=gnc_p_Mult_mm(D,Pn,r);
921       }
922#ifdef PDEBUG
923       p_Test(Pp,r);
924#endif
925       p_Delete(&Pn,r);
926     }
927     else                     /* first step */
928     {
929       Rout=gnc_mm_Mult_p(Pp,D,r);
930     }
931#ifdef PDEBUG
932     p_Test(Pp,r);
933#endif
934     p_Delete(&Pp,r);
935     num=n_Mult(c[cnt+1],c[cnt],r);
936     n_Delete(&c[cnt],r);
937     c[cnt]=num;
938     Rout=p_Mult_nn(Rout,c[cnt+1],r); /* Rest is ready */
939     out=p_Add_q(out,Rout,r);
940     Pp=NULL;
941     cnt--;
942  }
943  /* only to feel safe:*/
944  Pn=Pp=NULL;
945  freeT(On,rN);
946  freeT(Op,rN);
947
948/* leadterm and Prv-part with coef 1 */
949/*  U[0]=exp; */
950/*  U[jG]=U[jG]+bG;  */
951/* make leadterm */
952/* ??????????? we have done it already :-0 */
953
954  Rout=p_One(r);
955  p_SetExpV(Rout,U,r);
956  p_Setm(Rout,r);  /* use again this name */
957  p_SetCoeff(Rout,c[cnt+1],r);  /* last computed coef */
958
959  out=p_Add_q(out,Rout,r);
960
961  Rout=NULL;
962
963  freeT(U, rN);
964  freeN(c, i);
965  freeT(lF, rN);
966
967  if (cnf!=0)
968  {
969    Rout=p_One(r);
970    p_SetExpV(Rout,Prv,r);
971    p_Setm(Rout,r);
972    freeT(Prv, rN);
973    out=gnc_mm_Mult_p(Rout,out,r); /* getting the final result */
974    p_Delete(&Rout,r);
975  }
976
977  return (out);
978}
979
980poly gnc_uu_Mult_ww_vert (int i, int a, int j, int b, const ring r)
981{
982  int k,m;
983  int rN=r->N;
984  const int cMTindex = UPMATELEM(j,i,rN);
985  matrix cMT=r->GetNC()->MT[cMTindex];         /* cMT=current MT */
986
987  poly x=p_One(r);p_SetExp(x,j,1,r);p_Setm(x,r);
988/* var(j); */
989  poly y=p_One(r);p_SetExp(y,i,1,r);p_Setm(y,r);
990/*var(i);  for convenience */
991#ifdef PDEBUG
992  p_Test(x,r);
993  p_Test(y,r);
994#endif
995  poly t=NULL;
996/* ------------ Main Cycles ----------------------------*/
997
998  for (k=2;k<=a;k++)
999  {
1000     t = MATELEM(cMT,k,1);
1001
1002     if (t==NULL)   /* not computed yet */
1003     {
1004       t = nc_p_CopyGet(MATELEM(cMT,k-1,1),r);
1005       //        t=p_Copy(MATELEM(cMT,k-1,1),r);
1006       t = gnc_mm_Mult_p(y,t,r);
1007       cMT=r->GetNC()->MT[cMTindex]; // since multiplication can change the MT table...
1008       assume( t != NULL );
1009#ifdef PDEBUG
1010       p_Test(t,r);
1011#endif
1012       MATELEM(cMT,k,1) = nc_p_CopyPut(t,r);
1013       //        omCheckAddr(cMT->m);
1014       p_Delete(&t,r);
1015     }
1016     t=NULL;
1017  }
1018
1019  for (m=2;m<=b;m++)
1020  {
1021    t = MATELEM(cMT,a,m);
1022    //     t=MATELEM(cMT,a,m);
1023    if (t==NULL)   //not computed yet
1024    {
1025      t = nc_p_CopyGet(MATELEM(cMT,a,m-1),r);
1026      assume( t != NULL );
1027      //      t=p_Copy(MATELEM(cMT,a,m-1),r);
1028      t = gnc_p_Mult_mm(t,x,r);
1029      cMT=r->GetNC()->MT[cMTindex]; // since multiplication can change the MT table...
1030#ifdef PDEBUG
1031      p_Test(t,r);
1032#endif
1033      MATELEM(cMT,a,m) = nc_p_CopyPut(t,r);
1034      //      MATELEM(cMT,a,m) = t;
1035      //        omCheckAddr(cMT->m);
1036      p_Delete(&t,r);
1037    }
1038    t=NULL;
1039  }
1040  p_Delete(&x,r);
1041  p_Delete(&y,r);
1042  t=MATELEM(cMT,a,b);
1043  assume( t != NULL );
1044
1045  t= nc_p_CopyGet(t,r);
1046#ifdef PDEBUG
1047  p_Test(t,r);
1048#endif
1049  //  return(p_Copy(t,r));
1050  /* since the last computed element was cMT[a,b] */
1051  return(t);
1052}
1053
1054
1055static inline poly gnc_uu_Mult_ww_formula (int i, int a, int j, int b, const ring r)
1056{
1057  if(ncExtensions(NOFORMULAMASK))
1058    return gnc_uu_Mult_ww_vert(i, a, j, b, r);
1059
1060  CFormulaPowerMultiplier* FormulaMultiplier = GetFormulaPowerMultiplier(r);
1061  Enum_ncSAType PairType = _ncSA_notImplemented;
1062
1063  if( FormulaMultiplier != NULL )
1064    PairType = FormulaMultiplier->GetPair(j, i);
1065
1066
1067  if( PairType == _ncSA_notImplemented )
1068    return gnc_uu_Mult_ww_vert(i, a, j, b, r);
1069
1070
1071 //    return FormulaMultiplier->Multiply(j, i, b, a);
1072  poly t = CFormulaPowerMultiplier::Multiply( PairType, j, i, b, a, r);
1073
1074  int rN=r->N;
1075  matrix cMT = r->GetNC()->MT[UPMATELEM(j,i,rN)];         /* cMT=current MT */
1076
1077
1078  MATELEM(cMT, a, b) = nc_p_CopyPut(t,r);
1079
1080  //  t=MATELEM(cMT,a,b);
1081//  t= nc_p_CopyGet(MATELEM(cMT,a,b),r);
1082  //  return(p_Copy(t,r));
1083  /* since the last computed element was cMT[a,b] */
1084  return(t);
1085}
1086
1087
1088poly gnc_uu_Mult_ww (int i, int a, int j, int b, const ring r)
1089  /* (x_i)^a times (x_j)^b */
1090  /* x_i = y,  x_j = x ! */
1091{
1092  /* Check zero exceptions, (q-)commutativity and is there something to do? */
1093  assume(a!=0);
1094  assume(b!=0);
1095  poly out=p_One(r);
1096  if (i<=j)
1097  {
1098    p_SetExp(out,i,a,r);
1099    p_AddExp(out,j,b,r);
1100    p_Setm(out,r);
1101    return(out);
1102  }/* zero exeptions and usual case */
1103  /*  if ((a==0)||(b==0)||(i<=j)) return(out); */
1104
1105  if (MATELEM(r->GetNC()->COM,j,i)!=NULL)
1106    /* commutative or quasicommutative case */
1107  {
1108    p_SetExp(out,i,a,r);
1109    p_AddExp(out,j,b,r);
1110    p_Setm(out,r);
1111    if (n_IsOne(p_GetCoeff(MATELEM(r->GetNC()->COM,j,i),r),r)) /* commutative case */
1112    {
1113      return(out);
1114    }
1115    else
1116    {
1117      number tmp_number=p_GetCoeff(MATELEM(r->GetNC()->COM,j,i),r); /* quasicommutative case */
1118      n_Power(tmp_number,a*b,&tmp_number, r); // BUG! ;-(
1119      p_SetCoeff(out,tmp_number,r);
1120      return(out);
1121    }
1122  }/* end_of commutative or quasicommutative case */
1123  p_Delete(&out,r);
1124
1125
1126  if(ncExtensions(NOCACHEMASK) && !ncExtensions(NOFORMULAMASK)) // don't use cache whenever possible!
1127  { // without cache!?
1128    CFormulaPowerMultiplier* FormulaMultiplier = GetFormulaPowerMultiplier(r);
1129    Enum_ncSAType PairType = _ncSA_notImplemented;
1130
1131     if( FormulaMultiplier != NULL )
1132       PairType = FormulaMultiplier->GetPair(j, i);
1133
1134     if( PairType != _ncSA_notImplemented )
1135  // //    return FormulaMultiplier->Multiply(j, i, b, a);
1136       return CFormulaPowerMultiplier::Multiply( PairType, j, i, b, a, r);
1137  }
1138
1139
1140  /* we are here if  i>j and variables do not commute or quasicommute */
1141  /* in fact, now a>=1 and b>=1; and j<i */
1142  /* now check whether the polynomial is already computed */
1143  int rN=r->N;
1144  int vik = UPMATELEM(j,i,rN);
1145  int cMTsize=r->GetNC()->MTsize[vik];
1146  int newcMTsize=0;
1147  newcMTsize=si_max(a,b);
1148
1149  if (newcMTsize<=cMTsize)
1150  {
1151    out =  nc_p_CopyGet(MATELEM(r->GetNC()->MT[vik],a,b),r);
1152    if (out !=NULL) return (out);
1153  }
1154  int k,m;
1155  if (newcMTsize > cMTsize)
1156  {
1157    int inM=(((newcMTsize+6)/7)*7);
1158    assume (inM>=newcMTsize);
1159    newcMTsize = inM;
1160    //    matrix tmp = (matrix)omAlloc0(inM*inM*sizeof(poly));
1161    matrix tmp = mpNew(newcMTsize,newcMTsize);
1162
1163    for (k=1;k<=cMTsize;k++)
1164    {
1165      for (m=1;m<=cMTsize;m++)
1166      {
1167        out = MATELEM(r->GetNC()->MT[UPMATELEM(j,i,rN)],k,m);
1168        if ( out != NULL )
1169        {
1170          MATELEM(tmp,k,m) = out;/*MATELEM(r->GetNC()->MT[UPMATELEM(j,i,rN)],k,m)*/
1171          //           omCheckAddr(tmp->m);
1172          MATELEM(r->GetNC()->MT[UPMATELEM(j,i,rN)],k,m)=NULL;
1173          //           omCheckAddr(r->GetNC()->MT[UPMATELEM(j,i,rN)]->m);
1174          out=NULL;
1175        }
1176      }
1177    }
1178    id_Delete((ideal *)&(r->GetNC()->MT[UPMATELEM(j,i,rN)]),r);
1179    r->GetNC()->MT[UPMATELEM(j,i,rN)] = tmp;
1180    tmp=NULL;
1181    r->GetNC()->MTsize[UPMATELEM(j,i,rN)] = newcMTsize;
1182  }
1183  /* The update of multiplication matrix is finished */
1184
1185
1186  return gnc_uu_Mult_ww_formula(i, a, j, b, r);
1187
1188  out = gnc_uu_Mult_ww_vert(i, a, j, b, r);
1189  //    out = nc_uu_Mult_ww_horvert(i, a, j, b, r);
1190  return(out);
1191}
1192
1193poly gnc_uu_Mult_ww_horvert (int i, int a, int j, int b, const ring r)
1194
1195{
1196  int k,m;
1197  int rN=r->N;
1198  matrix cMT=r->GetNC()->MT[UPMATELEM(j,i,rN)];         /* cMT=current MT */
1199
1200  poly x=p_One(r);p_SetExp(x,j,1,r);p_Setm(x,r);/* var(j); */
1201  poly y=p_One(r);p_SetExp(y,i,1,r);p_Setm(y,r); /*var(i);  for convenience */
1202#ifdef PDEBUG
1203  p_Test(x,r);
1204  p_Test(y,r);
1205#endif
1206
1207  poly t=NULL;
1208
1209  int toXY;
1210  int toYX;
1211
1212  if (a==1) /* y*x^b, b>=2 */
1213  {
1214    toXY=b-1;
1215    while ( (MATELEM(cMT,1,toXY)==NULL) && (toXY>=2)) toXY--;
1216    for (m=toXY+1;m<=b;m++)
1217    {
1218      t=MATELEM(cMT,1,m);
1219      if (t==NULL)   /* remove after debug */
1220      {
1221        t = p_Copy(MATELEM(cMT,1,m-1),r);
1222        t = gnc_p_Mult_mm(t,x,r);
1223        MATELEM(cMT,1,m) = t;
1224        /*        omCheckAddr(cMT->m); */
1225      }
1226      else
1227      {
1228        /* Error, should never get there */
1229        WarnS("Error: a=1; MATELEM!=0");
1230      }
1231      t=NULL;
1232    }
1233    return(p_Copy(MATELEM(cMT,1,b),r));
1234  }
1235
1236  if (b==1) /* y^a*x, a>=2 */
1237  {
1238    toYX=a-1;
1239    while ( (MATELEM(cMT,toYX,1)==NULL) && (toYX>=2)) toYX--;
1240    for (m=toYX+1;m<=a;m++)
1241    {
1242      t=MATELEM(cMT,m,1);
1243      if (t==NULL)   /* remove after debug */
1244      {
1245        t = p_Copy(MATELEM(cMT,m-1,1),r);
1246        t = gnc_mm_Mult_p(y,t,r);
1247        MATELEM(cMT,m,1) = t;
1248        /*        omCheckAddr(cMT->m); */
1249      }
1250      else
1251      {
1252        /* Error, should never get there */
1253        WarnS("Error: b=1, MATELEM!=0");
1254      }
1255      t=NULL;
1256    }
1257    return(p_Copy(MATELEM(cMT,a,1),r));
1258  }
1259
1260/* ------------ Main Cycles ----------------------------*/
1261  /*            a>1, b>1              */
1262
1263  int dXY=0; int dYX=0;
1264  /* dXY = distance for computing x-mult, then y-mult */
1265  /* dYX = distance for computing y-mult, then x-mult */
1266  int toX=a-1; int toY=b-1; /* toX = to axe X, toY = to axe Y */
1267  toXY=b-1; toYX=a-1;
1268  /* if toX==0, toXY = dist. to computed y * x^toXY */
1269  /* if toY==0, toYX = dist. to computed y^toYX * x */
1270  while ( (MATELEM(cMT,toX,b)==NULL) && (toX>=1)) toX--;
1271  if (toX==0) /* the whole column is not computed yet */
1272  {
1273    while ( (MATELEM(cMT,1,toXY)==NULL) && (toXY>=1)) toXY--;
1274    /* toXY >=1 */
1275    dXY=b-1-toXY;
1276  }
1277  dXY=dXY+a-toX; /* the distance to nearest computed y^toX x^b */
1278
1279  while ( (MATELEM(cMT,a,toY)==NULL) && (toY>=1)) toY--;
1280  if (toY==0) /* the whole row is not computed yet */
1281  {
1282    while ( (MATELEM(cMT,toYX,1)==NULL) && (toYX>=1)) toYX--;
1283    /* toYX >=1 */
1284    dYX=a-1-toYX;
1285  }
1286  dYX=dYX+b-toY; /* the distance to nearest computed y^a x^toY */
1287
1288  if (dYX>=dXY)
1289  {
1290    /* first x, then y */
1291    if (toX==0) /* start with the row*/
1292    {
1293      for (m=toXY+1;m<=b;m++)
1294      {
1295        t=MATELEM(cMT,1,m);
1296        if (t==NULL)   /* remove after debug */
1297        {
1298          t = p_Copy(MATELEM(cMT,1,m-1),r);
1299          t = gnc_p_Mult_mm(t,x,r);
1300          MATELEM(cMT,1,m) = t;
1301          /*        omCheckAddr(cMT->m); */
1302        }
1303        else
1304        {
1305          /* Error, should never get there */
1306          WarnS("dYX>=dXY,toXY; MATELEM==0");
1307        }
1308        t=NULL;
1309      }
1310      toX=1; /* y*x^b is computed */
1311    }
1312    /* Now toX>=1 */
1313    for (k=toX+1;k<=a;k++)
1314    {
1315      t=MATELEM(cMT,k,b);
1316      if (t==NULL)   /* remove after debug */
1317      {
1318        t = p_Copy(MATELEM(cMT,k-1,b),r);
1319        t = gnc_mm_Mult_p(y,t,r);
1320        MATELEM(cMT,k,b) = t;
1321        /*        omCheckAddr(cMT->m); */
1322      }
1323      else
1324      {
1325        /* Error, should never get there */
1326        WarnS("dYX>=dXY,toX; MATELEM==0");
1327      }
1328      t=NULL;
1329    }
1330  } /* endif (dYX>=dXY) */
1331
1332
1333  if (dYX<dXY)
1334  {
1335    /* first y, then x */
1336    if (toY==0) /* start with the column*/
1337    {
1338      for (m=toYX+1;m<=a;m++)
1339      {
1340        t=MATELEM(cMT,m,1);
1341        if (t==NULL)   /* remove after debug */
1342        {
1343          t = p_Copy(MATELEM(cMT,m-1,1),r);
1344          t = gnc_mm_Mult_p(y,t,r);
1345          MATELEM(cMT,m,1) = t;
1346          /*        omCheckAddr(cMT->m); */
1347        }
1348        else
1349        {
1350          /* Error, should never get there */
1351          WarnS("dYX<dXY,toYX; MATELEM==0");
1352        }
1353        t=NULL;
1354      }
1355      toY=1; /* y^a*x is computed */
1356    }
1357    /* Now toY>=1 */
1358    for (k=toY+1;k<=b;k++)
1359    {
1360      t=MATELEM(cMT,a,k);
1361      if (t==NULL)   /* remove after debug */
1362      {
1363        t = p_Copy(MATELEM(cMT,a,k-1),r);
1364        t = gnc_p_Mult_mm(t,x,r);
1365        MATELEM(cMT,a,k) = t;
1366        /*        omCheckAddr(cMT->m); */
1367      }
1368      else
1369      {
1370        /* Error, should never get there */
1371        WarnS("dYX<dXY,toY; MATELEM==0");
1372      }
1373      t=NULL;
1374    }
1375  } /* endif (dYX<dXY) */
1376
1377  p_Delete(&x,r);
1378  p_Delete(&y,r);
1379  t=p_Copy(MATELEM(cMT,a,b),r);
1380  return(t);  /* since the last computed element was cMT[a,b] */
1381}
1382
1383
1384/* ----------------------------- Syzygies ---------------------- */
1385
1386/*2
1387* reduction of p2 with p1
1388* do not destroy p1, but p2
1389* p1 divides p2 -> for use in NF algorithm
1390*/
1391poly gnc_ReduceSpolyOld(const poly p1, poly p2/*,poly spNoether*/, const ring r)
1392{
1393  assume(p_LmDivisibleBy(p1, p2, r));
1394
1395#ifdef PDEBUG
1396  if (p_GetComp(p1,r)!=p_GetComp(p2,r)
1397  && (p_GetComp(p1,r)!=0)
1398  && (p_GetComp(p2,r)!=0))
1399  {
1400    dReportError("nc_ReduceSpolyOld: different components");
1401    return(NULL);
1402  }
1403#endif
1404  poly m = p_One(r);
1405  p_ExpVectorDiff(m,p2,p1,r);
1406  //p_Setm(m,r);
1407#ifdef PDEBUG
1408  p_Test(m,r);
1409#endif
1410  /* pSetComp(m,r)=0? */
1411  poly   N  = nc_mm_Mult_p(m, p_Head(p1,r), r);
1412  number C  =  p_GetCoeff(N,  r);
1413  number cF =  p_GetCoeff(p2, r);
1414  /* GCD stuff */
1415  number cG = n_Gcd(C, cF, r);
1416  if ( !n_IsOne(cG,r) )
1417  {
1418    cF = n_Div(cF, cG, r); n_Normalize(cF, r);
1419    C  = n_Div(C,  cG, r); n_Normalize(C, r);
1420  }
1421  else
1422  {
1423    cF = n_Copy(cF, r);
1424    C  = n_Copy(C, r);
1425  }
1426  n_Delete(&cG,r);
1427  p2 = p_Mult_nn(p2, C, r);
1428  poly out = nc_mm_Mult_pp(m, pNext(p1), r);
1429  N = p_Add_q(N, out, r);
1430  p_Test(p2,r);
1431  p_Test(N,r);
1432  if (!n_IsMOne(cF,r))
1433  {
1434    cF = n_Neg(cF,r);
1435    N  = p_Mult_nn(N, cF, r);
1436    p_Test(N,r);
1437  }
1438  out = p_Add_q(p2,N,r);
1439  p_Test(out,r);
1440  if ( out!=NULL ) p_Content(out,r);
1441  p_Delete(&m,r);
1442  n_Delete(&cF,r);
1443  n_Delete(&C,r);
1444  return(out);
1445}
1446
1447poly gnc_ReduceSpolyNew(const poly p1, poly p2, const ring r)
1448{
1449  assume(p_LmDivisibleBy(p1, p2, r));
1450
1451  const long lCompP1 = p_GetComp(p1,r);
1452  const long lCompP2 = p_GetComp(p2,r);
1453
1454  if ((lCompP1!=lCompP2) && (lCompP1!=0) && (lCompP2!=0))
1455  {
1456#ifdef PDEBUG
1457    Werror("gnc_ReduceSpolyNew: different non-zero components!");
1458#endif
1459    return(NULL);
1460  }
1461
1462  poly m = p_One(r);
1463  p_ExpVectorDiff(m, p2, p1, r);
1464  //p_Setm(m,r);
1465#ifdef PDEBUG
1466  p_Test(m,r);
1467#endif
1468
1469  /* pSetComp(m,r)=0? */
1470  poly   N  = nc_mm_Mult_p(m, p_Head(p1,r), r);
1471
1472  number C  = p_GetCoeff(N,  r);
1473  number cF = p_GetCoeff(p2, r);
1474
1475  /* GCD stuff */
1476  number cG = n_Gcd(C, cF, r);
1477
1478  if (!n_IsOne(cG, r))
1479  {
1480    cF = n_Div(cF, cG, r); n_Normalize(cF, r);
1481    C  = n_Div(C,  cG, r); n_Normalize(C, r);
1482  }
1483  else
1484  {
1485    cF = n_Copy(cF, r);
1486    C  = n_Copy(C, r);
1487  }
1488  n_Delete(&cG,r);
1489
1490  p2 = p_Mult_nn(p2, C, r); // p2 !!!
1491  p_Test(p2,r);
1492  n_Delete(&C,r);
1493  n_Delete(&cG,r);
1494
1495  poly out = nc_mm_Mult_pp(m, pNext(p1), r);
1496  p_Delete(&m,r);
1497
1498  N = p_Add_q(N, out, r);
1499  p_Test(N,r);
1500
1501  if (!n_IsMOne(cF,r)) // ???
1502  {
1503    cF = n_Neg(cF,r);
1504    N  = p_Mult_nn(N, cF, r);
1505    p_Test(N,r);
1506  }
1507  n_Delete(&cF,r);
1508
1509  out = p_Add_q(p2,N,r); // delete N, p2
1510  p_Test(out,r);
1511  if ( out!=NULL ) p_Content(out,r);
1512  return(out);
1513}
1514
1515
1516/*4
1517* creates the S-polynomial of p1 and p2
1518* do not destroy p1 and p2
1519*/
1520poly gnc_CreateSpolyOld(poly p1, poly p2/*,poly spNoether*/, const ring r)
1521{
1522#ifdef PDEBUG
1523  if ((p_GetComp(p1,r)!=p_GetComp(p2,r))
1524  && (p_GetComp(p1,r)!=0)
1525  && (p_GetComp(p2,r)!=0))
1526  {
1527    dReportError("gnc_CreateSpolyOld : different components!");
1528    return(NULL);
1529  }
1530#endif
1531  if ((ncRingType(r)==nc_lie) && p_HasNotCF(p1,p2, r)) /* prod crit */
1532  {
1533    return(nc_p_Bracket_qq(p_Copy(p2, r),p1, r));
1534  }
1535  poly pL=p_One(r);
1536  poly m1=p_One(r);
1537  poly m2=p_One(r);
1538  pL = p_Lcm(p1,p2,r);
1539  p_Setm(pL,r);
1540#ifdef PDEBUG
1541  p_Test(pL,r);
1542#endif
1543  p_ExpVectorDiff(m1,pL,p1,r);
1544  //p_SetComp(m1,0,r);
1545  //p_Setm(m1,r);
1546#ifdef PDEBUG
1547  p_Test(m1,r);
1548#endif
1549  p_ExpVectorDiff(m2,pL,p2,r);
1550  //p_SetComp(m2,0,r);
1551  //p_Setm(m2,r);
1552#ifdef PDEBUG
1553  p_Test(m2,r);
1554#endif
1555  p_Delete(&pL,r);
1556  /* zero exponents ! */
1557  poly M1    = nc_mm_Mult_p(m1,p_Head(p1,r),r);
1558  number C1  = p_GetCoeff(M1,r);
1559  poly M2    = nc_mm_Mult_p(m2,p_Head(p2,r),r);
1560  number C2  = p_GetCoeff(M2,r);
1561  /* GCD stuff */
1562  number C = n_Gcd(C1,C2,r);
1563  if (!n_IsOne(C,r))
1564  {
1565    C1=n_Div(C1,C, r);n_Normalize(C1,r);
1566    C2=n_Div(C2,C, r);n_Normalize(C2,r);
1567  }
1568  else
1569  {
1570    C1=n_Copy(C1, r);
1571    C2=n_Copy(C2, r);
1572  }
1573  n_Delete(&C,r);
1574  M1=p_Mult_nn(M1,C2,r);
1575  p_SetCoeff(m1,C2,r);
1576  if (n_IsMOne(C1,r))
1577  {
1578    M2=p_Add_q(M1,M2,r);
1579  }
1580  else
1581  {
1582    C1=n_Neg(C1,r);
1583    M2=p_Mult_nn(M2,C1,r);
1584    M2=p_Add_q(M1,M2,r);
1585    p_SetCoeff(m2,C1,r);
1586  }
1587  /* M1 is killed, M2=res = C2 M1 - C1 M2 */
1588  poly tmp=p_Copy(p1,r);
1589  tmp=p_LmDeleteAndNext(tmp,r);
1590  M1=nc_mm_Mult_p(m1,tmp,r);
1591  tmp=p_Copy(p2,r);
1592  tmp=p_LmDeleteAndNext(tmp,r);
1593  M2=p_Add_q(M2,M1,r);
1594  M1=nc_mm_Mult_p(m2,tmp,r);
1595  M2=p_Add_q(M2,M1,r);
1596  p_Delete(&m1,r);
1597  p_Delete(&m2,r);
1598  //  n_Delete(&C1,r);
1599  //  n_Delete(&C2,r);
1600#ifdef PDEBUG
1601  p_Test(M2,r);
1602#endif
1603  if (M2!=NULL) M2=p_Cleardenom(M2,r);
1604  //if (M2!=NULL) p_Content(M2); // done by pCleardenom
1605  return(M2);
1606}
1607
1608poly gnc_CreateSpolyNew(poly p1, poly p2/*,poly spNoether*/, const ring r)
1609{
1610#ifdef PDEBUG
1611  p_Test(p1, r);
1612  p_Test(p2, r);
1613#if MYTEST
1614  Print("p1: "); p_Write(p1, r);
1615  Print("p2: "); p_Write(p2, r);
1616#endif
1617#endif
1618
1619  const long lCompP1 = p_GetComp(p1,r);
1620  const long lCompP2 = p_GetComp(p2,r);
1621
1622  if ((lCompP1!=lCompP2) && (lCompP1!=0) && (lCompP2!=0))
1623  {
1624#ifdef PDEBUG
1625    Werror("gnc_CreateSpolyNew: different non-zero components!");
1626    assume(0);
1627#endif
1628    return(NULL);
1629  }
1630
1631#ifdef PDEBUG
1632  if (lCompP1!=lCompP2)
1633  {
1634    WarnS("gnc_CreateSpolyNew: vector & poly in SPoly!");
1635  }
1636#endif
1637
1638
1639//   if ((r->GetNC()->type==nc_lie) && pHasNotCF(p1,p2)) /* prod crit */
1640//   {
1641//     return(nc_p_Bracket_qq(pCopy(p2),p1));
1642//   }
1643
1644//  poly pL=p_One( r);
1645
1646  poly m1=p_One( r);
1647  poly m2=p_One( r);
1648
1649  poly pL = p_Lcm(p1,p2,r);                               // pL = lcm( lm(p1), lm(p2) )
1650
1651
1652#ifdef PDEBUG
1653//  p_Test(pL,r);
1654#endif
1655
1656  p_ExpVectorDiff(m1, pL, p1, r);                  // m1 = pL / lm(p1)
1657  //p_SetComp(m1,0,r);
1658  //p_Setm(m1,r);
1659
1660#ifdef PDEBUG
1661  p_Test(m1,r);
1662#endif
1663//  assume(p_GetComp(m1,r) == 0);
1664
1665  p_ExpVectorDiff(m2, pL, p2, r);                  // m2 = pL / lm(p2)
1666
1667  //p_SetComp(m2,0,r);
1668  //p_Setm(m2,r);
1669#ifdef PDEBUG
1670  p_Test(m2,r);
1671#endif
1672
1673#ifdef PDEBUG
1674#if MYTEST
1675  Print("m1: "); pWrite(m1);
1676  Print("m2: "); pWrite(m2);
1677#endif
1678#endif
1679
1680
1681//  assume(p_GetComp(m2,r) == 0);
1682
1683#ifdef PDEBUG
1684#if 0
1685  if(  (p_GetComp(m2,r) != 0) || (p_GetComp(m1,r) != 0) )
1686  {
1687    WarnS("gnc_CreateSpolyNew: wrong monomials!");
1688
1689
1690#ifdef RDEBUG
1691    PrintS("m1 = "); p_Write(m1, r);
1692    p_DebugPrint(m1, r);
1693
1694    PrintS("m2 = "); p_Write(m2, r);
1695    p_DebugPrint(m2, r);
1696
1697    PrintS("p1 = "); p_Write(p1, r);
1698    p_DebugPrint(p1, r);
1699
1700    PrintS("p2 = "); p_Write(p2, r);
1701    p_DebugPrint(p2, r);
1702
1703    PrintS("pL = "); p_Write(pL, r);
1704    p_DebugPrint(pL, r);
1705#endif
1706
1707  }
1708
1709#endif
1710#endif
1711
1712  p_Delete(&pL,r);
1713
1714  /* zero exponents !? */
1715  poly M1    = nc_mm_Mult_p(m1,p_Head(p1,r),r); // M1 = m1 * lt(p1)
1716  poly M2    = nc_mm_Mult_p(m2,p_Head(p2,r),r); // M2 = m2 * lt(p2)
1717
1718#ifdef PDEBUG
1719  p_Test(M1,r);
1720  p_Test(M2,r);
1721
1722#if MYTEST
1723  Print("M1: "); pWrite(M1);
1724  Print("M2: "); pWrite(M2);
1725#endif
1726#endif
1727
1728  if(M1 == NULL || M2 == NULL)
1729  {
1730#ifdef PDEBUG
1731       Print("\np1 = ");
1732       p_Write(p1, r);
1733
1734       Print("m1 = ");
1735       p_Write(m1, r);
1736
1737       Print("p2 = ");
1738       p_Write(p2, r);
1739
1740       Print("m2 = ");
1741       p_Write(m2, r);
1742
1743       Werror("ERROR in nc_CreateSpoly: result of multiplication is Zero!\n");
1744#endif
1745       return(NULL);
1746  }
1747
1748  number C1  = p_GetCoeff(M1,r);      // C1 = lc(M1)
1749  number C2  = p_GetCoeff(M2,r);      // C2 = lc(M2)
1750
1751  /* GCD stuff */
1752  number C = n_Gcd(C1, C2, r);                     // C = gcd(C1, C2)
1753
1754  if (!n_IsOne(C, r))                              // if C != 1
1755  {
1756    C1=n_Div(C1, C, r);n_Normalize(C1,r);            // C1 = C1 / C
1757    C2=n_Div(C2, C, r);n_Normalize(C2,r);            // C2 = C2 / C
1758  }
1759  else
1760  {
1761    C1=n_Copy(C1,r);
1762    C2=n_Copy(C2,r);
1763  }
1764
1765  n_Delete(&C,r); // destroy the number C
1766
1767  C1=n_Neg(C1,r);
1768
1769//   number MinusOne=n_Init(-1,r);
1770//   if (n_Equal(C1,MinusOne,r))                   // lc(M1) / gcd( lc(M1), lc(M2)) == -1 ????
1771//   {
1772//     M2=p_Add_q(M1,M2,r);                        // ?????
1773//   }
1774//   else
1775//   {
1776  M1=p_Mult_nn(M1,C2,r);                           // M1 = (C2*lc(p1)) * (lcm(lm(p1),lm(p2)) / lm(p1)) * lm(p1)
1777
1778#ifdef PDEBUG
1779  p_Test(M1,r);
1780#endif
1781
1782  M2=p_Mult_nn(M2,C1,r);                           // M2 =(-C1*lc(p2)) * (lcm(lm(p1),lm(p2)) / lm(p2)) * lm(p2)
1783
1784
1785
1786#ifdef PDEBUG
1787  p_Test(M2,r);
1788
1789#if MYTEST
1790  Print("M1: "); pWrite(M1);
1791  Print("M2: "); pWrite(M2);
1792#endif
1793#endif
1794
1795
1796  M2=p_Add_q(M1,M2,r);                             // M1 is killed, M2 = spoly(lt(p1), lt(p2)) = C2*M1 - C1*M2
1797
1798#ifdef PDEBUG
1799  p_Test(M2,r);
1800
1801#if MYTEST
1802  Print("M2: "); pWrite(M2);
1803#endif
1804
1805#endif
1806
1807// M2 == 0 for supercommutative algebras!
1808//   }
1809//   n_Delete(&MinusOne,r);
1810
1811  p_SetCoeff(m1,C2,r);                           // lc(m1) = C2!!!
1812  p_SetCoeff(m2,C1,r);                           // lc(m2) = C1!!!
1813
1814#ifdef PDEBUG
1815  p_Test(m1,r);
1816  p_Test(m2,r);
1817#endif
1818
1819//  poly tmp = p_Copy(p1,r);                         // tmp = p1
1820//  tmp=p_LmDeleteAndNext(tmp,r);                  // tmp = tail(p1)
1821//#ifdef PDEBUG
1822//  p_Test(tmp,r);
1823//#endif
1824
1825  M1 = nc_mm_Mult_pp(m1, pNext(p1), r);                      // M1 = m1 * tail(p1), delete tmp // ???
1826
1827#ifdef PDEBUG
1828  p_Test(M1,r);
1829
1830#if MYTEST
1831  Print("M1: "); pWrite(M1);
1832#endif
1833
1834#endif
1835
1836  M2=p_Add_q(M2,M1,r);                           // M2 = spoly(lt(p1), lt(p2)) + m1 * tail(p1), delete M1
1837#ifdef PDEBUG
1838  M1=NULL;
1839  p_Test(M2,r);
1840
1841#if MYTEST
1842  Print("M2: "); pWrite(M2);
1843#endif
1844
1845#endif
1846
1847//  tmp=p_Copy(p2,r);                              // tmp = p2
1848//  tmp=p_LmDeleteAndNext(tmp,r);                  // tmp = tail(p2)
1849
1850//#ifdef PDEBUG
1851//  p_Test(tmp,r);
1852//#endif
1853
1854  M1 = nc_mm_Mult_pp(m2, pNext(p2), r);                      // M1 = m2 * tail(p2), detele tmp
1855
1856#ifdef PDEBUG
1857  p_Test(M1,r);
1858
1859#if MYTEST
1860  Print("M1: "); pWrite(M1);
1861#endif
1862
1863#endif
1864
1865  M2 = p_Add_q(M2,M1,r);                           // M2 = spoly(lt(p1), lt(p2)) + m1 * tail(p1) + m2*tail(p2)
1866
1867#ifdef PDEBUG
1868  M1=NULL;
1869  p_Test(M2,r);
1870
1871#if MYTEST
1872  Print("M2: "); pWrite(M2);
1873#endif
1874
1875#endif
1876
1877  p_Delete(&m1,r);  //  => n_Delete(&C1,r);
1878  p_Delete(&m2,r);  //  => n_Delete(&C2,r);
1879
1880#ifdef PDEBUG
1881  p_Test(M2,r);
1882#endif
1883
1884  if (M2!=NULL) p_Cleardenom(M2,r);
1885
1886  return(M2);
1887}
1888
1889
1890
1891
1892#if 0
1893/*5
1894* reduction of tail(q) with p1
1895* lead(p1) divides lead(pNext(q2)) and pNext(q2) is reduced
1896* do not destroy p1, but tail(q)
1897*/
1898void gnc_ReduceSpolyTail(poly p1, poly q, poly q2, poly spNoether, const ring r)
1899{
1900  poly a1=p_Head(p1,r);
1901  poly Q=pNext(q2);
1902  number cQ=p_GetCoeff(Q,r);
1903  poly m=p_One(r);
1904  p_ExpVectorDiff(m,Q,p1,r);
1905  //  p_SetComp(m,0,r);
1906  //p_Setm(m,r);
1907#ifdef PDEBUG
1908  p_Test(m,r);
1909#endif
1910  /* pSetComp(m,r)=0? */
1911  poly M = nc_mm_Mult_pp(m, p1,r);
1912  number C=p_GetCoeff(M,r);
1913  M=p_Add_q(M,nc_mm_Mult_p(m,p_LmDeleteAndNext(p_Copy(p1,r),r),r),r); // _pp?
1914  q=p_Mult_nn(q,C,r);
1915  number MinusOne=n_Init(-1,r);
1916  if (!n_Equal(cQ,MinusOne,r))
1917  {
1918    cQ=nNeg(cQ);
1919    M=p_Mult_nn(M,cQ,r);
1920  }
1921  Q=p_Add_q(Q,M,r);
1922  pNext(q2)=Q;
1923
1924  p_Delete(&m,r);
1925  n_Delete(&C,r);
1926  n_Delete(&cQ,r);
1927  n_Delete(&MinusOne,r);
1928  /*  return(q); */
1929}
1930#endif
1931
1932
1933/*6
1934* creates the commutative lcm(lm(p1),lm(p2))
1935* do not destroy p1 and p2
1936*/
1937poly nc_CreateShortSpoly(poly p1, poly p2, const ring r)
1938{
1939#ifdef PDEBUG
1940  p_Test(p1, r);
1941  p_Test(p2, r);
1942#endif
1943
1944  const long lCompP1 = p_GetComp(p1,r);
1945  const long lCompP2 = p_GetComp(p2,r);
1946
1947  if ((lCompP1!=lCompP2) && (lCompP1!=0) && (lCompP2!=0))
1948  {
1949#ifdef PDEBUG
1950    Werror("nc_CreateShortSpoly: wrong module components!"); // !!!!
1951#endif
1952    return(NULL);
1953  }
1954
1955  poly m;
1956
1957#ifdef HAVE_RATGRING
1958  if ( rIsRatGRing(r))
1959  {
1960    /* rational version */
1961    m = p_LcmRat(p1, p2, si_max(lCompP1, lCompP2), r);
1962  } else
1963#endif
1964  {
1965    m = p_Lcm(p1, p2, si_max(lCompP1, lCompP2), r);
1966  }
1967
1968//  n_Delete(&p_GetCoeff(m, r), r);
1969//  pSetCoeff0(m, NULL);
1970
1971#ifdef PDEBUG
1972//  p_Test(m,r);
1973#endif
1974
1975  return(m);
1976}
1977
1978void gnc_kBucketPolyRedOld(kBucket_pt b, poly p, number *c)
1979{
1980  const ring r = b->bucket_ring;
1981  // b will not be multiplied by any constant in this impl.
1982  // ==> *c=1
1983  if (c!=NULL) *c=n_Init(1, r);
1984  poly m=p_One(r);
1985  p_ExpVectorDiff(m,kBucketGetLm(b),p, r);
1986  //pSetm(m);
1987#ifdef PDEBUG
1988  p_Test(m, r);
1989#endif
1990  poly pp= nc_mm_Mult_pp(m,p, r);
1991  assume(pp!=NULL);
1992  p_Delete(&m, r);
1993  number n=p_GetCoeff(pp, r);
1994  number nn;
1995  if (!n_IsMOne(n, r))
1996  {
1997    nn=n_Neg(n_Invers(n, r), r);
1998    n= n_Mult(nn,p_GetCoeff(kBucketGetLm(b), r), r);
1999    n_Delete(&nn, r);
2000    pp=p_Mult_nn(pp,n,r);
2001    n_Delete(&n, r);
2002  }
2003  else
2004  {
2005    pp=p_Mult_nn(pp,p_GetCoeff(kBucketGetLm(b), r),r);
2006  }
2007  int l=pLength(pp);
2008  kBucket_Add_q(b,pp,&l);
2009}
2010
2011void gnc_kBucketPolyRedNew(kBucket_pt b, poly p, number *c)
2012{
2013  const ring r = b->bucket_ring;
2014#ifdef PDEBUG
2015//   Print(">*");
2016#endif
2017
2018#ifdef KDEBUG
2019  if( !kbTest(b) )Werror("nc_kBucketPolyRed: broken bucket!");
2020#endif
2021
2022#ifdef PDEBUG
2023  p_Test(p, r);
2024#if MYTEST
2025  Print("p: "); p_Write(p, r);
2026#endif
2027#endif
2028
2029  // b will not be multiplied by any constant in this impl.
2030  // ==> *c=1
2031  if (c!=NULL) *c=n_Init(1, r);
2032  poly m = p_One(r);
2033  const poly pLmB = kBucketGetLm(b); // no new copy!
2034
2035  assume( pLmB != NULL );
2036
2037#ifdef PDEBUG
2038  p_Test(pLmB, r);
2039
2040#if MYTEST
2041  Print("pLmB: "); p_Write(pLmB, r);
2042#endif
2043#endif
2044
2045  p_ExpVectorDiff(m, pLmB, p, r);
2046  //pSetm(m);
2047
2048#ifdef PDEBUG
2049  p_Test(m, r);
2050#if MYTEST
2051  Print("m: "); p_Write(m, r);
2052#endif
2053#endif
2054
2055  poly pp = nc_mm_Mult_pp(m, p, r);
2056  p_Delete(&m, r);
2057
2058  assume( pp != NULL );
2059  const number n = p_GetCoeff(pp, r); // bug!
2060
2061  if (!n_IsMOne(n, r) ) // does this improve performance??!? also see below... // TODO: check later on.
2062  // if n == -1 => nn = 1 and -1/n
2063  {
2064    number nn=n_Neg(n_Invers(n, r), r);
2065    number t = n_Mult(nn,p_GetCoeff(pLmB, r), r);
2066    n_Delete(&nn, r);
2067    pp = p_Mult_nn(pp,t,r);
2068    n_Delete(&t, r);
2069  }
2070  else
2071  {
2072    pp = p_Mult_nn(pp,p_GetCoeff(pLmB, r), r);
2073  }
2074
2075  int l = pLength(pp);
2076
2077#ifdef PDEBUG
2078  p_Test(pp, r);
2079//   Print("PP: "); pWrite(pp);
2080#endif
2081
2082  kBucket_Add_q(b,pp,&l);
2083
2084
2085#ifdef PDEBUG
2086//   Print("*>");
2087#endif
2088}
2089
2090
2091void gnc_kBucketPolyRed_ZOld(kBucket_pt b, poly p, number *c)
2092{
2093  const ring r = b->bucket_ring;
2094  // b is multiplied by a constant in this impl.
2095  number ctmp;
2096  poly m=p_One(r);
2097  p_ExpVectorDiff(m,kBucketGetLm(b),p, r);
2098  //pSetm(m);
2099#ifdef PDEBUG
2100  p_Test(m, r);
2101#endif
2102  if(p_IsConstant(m,r))
2103  {
2104    p_Delete(&m, r);
2105    ctmp = kBucketPolyRed(b,p,pLength(p),NULL);
2106  }
2107  else
2108  {
2109    poly pp = nc_mm_Mult_pp(m,p,r);
2110    number c2;
2111    p_Cleardenom_n(pp,r,c2);
2112    p_Delete(&m, r);
2113    ctmp = kBucketPolyRed(b,pp,pLength(pp),NULL);
2114    //cc=*c;
2115    //*c=nMult(*c,c2);
2116    n_Delete(&c2, r);
2117    //nDelete(&cc);
2118    p_Delete(&pp, r);
2119  }
2120  if (c!=NULL) *c=ctmp;
2121  else n_Delete(&ctmp, r);
2122}
2123
2124void gnc_kBucketPolyRed_ZNew(kBucket_pt b, poly p, number *c)
2125{
2126  const ring r = b->bucket_ring;
2127  // b is multiplied by a constant in this impl.
2128  number ctmp;
2129  poly m=p_One(r);
2130  p_ExpVectorDiff(m,kBucketGetLm(b),p, r);
2131  //pSetm(m);
2132#ifdef PDEBUG
2133  p_Test(m, r);
2134#endif
2135
2136  if(p_IsConstant(m,r))
2137  {
2138    p_Delete(&m, r);
2139    ctmp = kBucketPolyRed(b,p,pLength(p),NULL);
2140  }
2141  else
2142  {
2143    poly pp = nc_mm_Mult_pp(m,p,r);
2144    number c2;
2145    p_Cleardenom_n(pp,r,c2);
2146    p_Delete(&m, r);
2147    ctmp = kBucketPolyRed(b,pp,pLength(pp),NULL);
2148    //cc=*c;
2149    //*c=nMult(*c,c2);
2150    n_Delete(&c2, r);
2151    //nDelete(&cc);
2152    p_Delete(&pp, r);
2153  }
2154  if (c!=NULL) *c=ctmp;
2155  else n_Delete(&ctmp, r);
2156}
2157
2158
2159inline void nc_PolyPolyRedOld(poly &b, poly p, number *c, const ring r)
2160  // reduces b with p, do not delete both
2161{
2162  // b will not by multiplied by any constant in this impl.
2163  // ==> *c=1
2164  if (c!=NULL) *c=n_Init(1, r);
2165  poly m=p_One(r);
2166  p_ExpVectorDiff(m,p_Head(b, r),p, r);
2167  //pSetm(m);
2168#ifdef PDEBUG
2169  p_Test(m, r);
2170#endif
2171  poly pp=nc_mm_Mult_pp(m,p,r);
2172  assume(pp!=NULL);
2173
2174  p_Delete(&m, r);
2175  number n=p_GetCoeff(pp, r);
2176  number nn;
2177  if (!n_IsMOne(n, r))
2178  {
2179    nn=n_Neg(n_Invers(n, r), r);
2180    n =n_Mult(nn,p_GetCoeff(b, r), r);
2181    n_Delete(&nn, r);
2182    pp=p_Mult_nn(pp,n,r);
2183    n_Delete(&n, r);
2184  }
2185  else
2186  {
2187    pp=p_Mult_nn(pp,p_GetCoeff(b, r),r);
2188  }
2189  b=p_Add_q(b,pp,r);
2190}
2191
2192
2193inline void nc_PolyPolyRedNew(poly &b, poly p, number *c, const ring r)
2194  // reduces b with p, do not delete both
2195{
2196#ifdef PDEBUG
2197  p_Test(b, r);
2198  p_Test(p, r);
2199#endif
2200
2201#if MYTEST
2202  PrintS("nc_PolyPolyRedNew(");
2203  p_Write0(b, r);
2204  PrintS(", ");
2205  p_Write0(p, r);
2206  PrintS(", *c): ");
2207#endif
2208
2209  // b will not by multiplied by any constant in this impl.
2210  // ==> *c=1
2211  if (c!=NULL) *c=n_Init(1, r);
2212
2213  poly pp = NULL;
2214
2215  // there is a problem when p is a square(=>0!)
2216
2217  while((b != NULL) && (pp == NULL))
2218  {
2219
2220//    poly pLmB = p_Head(b, r);
2221    poly m = p_One(r);
2222    p_ExpVectorDiff(m, b, p, r);
2223//    pDelete(&pLmB);
2224  //pSetm(m);
2225
2226#ifdef PDEBUG
2227    p_Test(m, r);
2228    p_Test(b, r);
2229#endif
2230
2231    pp = nc_mm_Mult_pp(m, p, r);
2232
2233#if MYTEST
2234    PrintS("\n{b': ");
2235    p_Write0(b, r);
2236    PrintS(", m: ");
2237    p_Write0(m, r);
2238    PrintS(", pp: ");
2239    p_Write0(pp, r);
2240    PrintS(" }\n");
2241#endif
2242
2243    p_Delete(&m, r); // one m for all tries!
2244
2245//    assume( pp != NULL );
2246
2247    if( pp == NULL )
2248    {
2249      b = p_LmDeleteAndNext(b, r);
2250
2251      if( !p_DivisibleBy(p, b, r) )
2252        return;
2253
2254    }
2255  }
2256
2257#if MYTEST
2258  PrintS("{b': ");
2259  p_Write0(b, r);
2260  PrintS(", pp: ");
2261  p_Write0(pp, r);
2262  PrintS(" }\n");
2263#endif
2264
2265
2266  if(b == NULL) return;
2267
2268
2269  assume(pp != NULL);
2270
2271  const number n = p_GetCoeff(pp, r); // no new copy
2272
2273  number nn;
2274
2275  if (!n_IsMOne(n, r)) // TODO: as above.
2276  {
2277    nn=n_Neg(n_Invers(n, r), r);
2278    number t = n_Mult(nn, p_GetCoeff(b, r), r);
2279    n_Delete(&nn, r);
2280    pp=p_Mult_nn(pp, t, r);
2281    n_Delete(&t, r);
2282  }
2283  else
2284  {
2285    pp=p_Mult_nn(pp, pGetCoeff(b), r);
2286  }
2287
2288
2289  b=p_Add_q(b,pp,r);
2290
2291}
2292
2293void nc_PolyPolyRed(poly &b, poly p, number *c, const ring r)
2294{
2295#if 0
2296  nc_PolyPolyRedOld(b, p, c, r);
2297#else
2298  nc_PolyPolyRedNew(b, p, c, r);
2299#endif
2300}
2301
2302
2303poly nc_mm_Bracket_nn(poly m1, poly m2, const ring r);
2304
2305/// returns [p,q], destroys p
2306poly nc_p_Bracket_qq(poly p, const poly q, const ring r)
2307{
2308  assume(p != NULL && q!= NULL);
2309
2310  if (!rIsPluralRing(r)) return(NULL);
2311  if (p_ComparePolys(p,q, r)) return(NULL);
2312  /* Components !? */
2313  poly Q=NULL;
2314  number coef=NULL;
2315  poly pres=NULL;
2316  int UseBuckets=1;
2317  if (((pLength(p)< MIN_LENGTH_BUCKET/2) && (pLength(q)< MIN_LENGTH_BUCKET/2))
2318  || TEST_OPT_NOT_BUCKETS)
2319    UseBuckets=0;
2320
2321
2322  CPolynomialSummator sum(r, UseBuckets == 0);
2323
2324  while (p!=NULL)
2325  {
2326    Q=q;
2327    while(Q!=NULL)
2328    {
2329      pres=nc_mm_Bracket_nn(p,Q, r); /* since no coeffs are taken into account there */
2330      if (pres!=NULL)
2331      {
2332        coef = n_Mult(p_GetCoeff(p, r),p_GetCoeff(Q, r), r);
2333        pres = p_Mult_nn(pres,coef,r);
2334
2335        sum += pres;
2336        n_Delete(&coef, r);
2337      }
2338      pIter(Q);
2339    }
2340    p=p_LmDeleteAndNext(p, r);
2341  }
2342  return(sum);
2343}
2344
2345/// returns [m1,m2] for two monoms, destroys nothing
2346/// without coeffs
2347poly nc_mm_Bracket_nn(poly m1, poly m2, const ring r)
2348{
2349  if (p_LmIsConstant(m1, r) || p_LmIsConstant(m1, r)) return(NULL);
2350  if (p_LmCmp(m1,m2, r)==0) return(NULL);
2351  int rN=r->N;
2352  int *M1=(int *)omAlloc0((rN+1)*sizeof(int));
2353  int *M2=(int *)omAlloc0((rN+1)*sizeof(int));
2354  int *aPREFIX=(int *)omAlloc0((rN+1)*sizeof(int));
2355  int *aSUFFIX=(int *)omAlloc0((rN+1)*sizeof(int));
2356  p_GetExpV(m1,M1, r);
2357  p_GetExpV(m2,M2, r);
2358  poly res=NULL;
2359  poly ares=NULL;
2360  poly bres=NULL;
2361  poly prefix=NULL;
2362  poly suffix=NULL;
2363  int nMin,nMax;
2364  number nTmp=NULL;
2365  int i,j,k;
2366  for (i=1;i<=rN;i++)
2367  {
2368    if (M2[i]!=0)
2369    {
2370      ares=NULL;
2371      for (j=1;j<=rN;j++)
2372      {
2373        if (M1[j]!=0)
2374        {
2375          bres=NULL;
2376          /* compute [ x_j^M1[j],x_i^M2[i] ] */
2377          if (i<j) {nMax=j;  nMin=i;} else {nMax=i;  nMin=j;}
2378          if ( (i==j) || ((MATELEM(r->GetNC()->COM,nMin,nMax)!=NULL) && n_IsOne(p_GetCoeff(MATELEM(r->GetNC()->C,nMin,nMax), r), r) )) /* not (the same exp. or commuting exps)*/
2379          { bres=NULL; }
2380          else
2381          {
2382            if (i<j) { bres=gnc_uu_Mult_ww(j,M1[j],i,M2[i], r); }
2383            else bres=gnc_uu_Mult_ww(i,M2[i],j,M1[j], r);
2384            if (n_IsOne(p_GetCoeff(bres, r), r))
2385            {
2386              bres=p_LmDeleteAndNext(bres, r);
2387            }
2388            else
2389            {
2390              nTmp=n_Sub(p_GetCoeff(bres, r),n_Init(1, r), r);
2391              p_SetCoeff(bres,nTmp, r); /* only lc ! */
2392            }
2393#ifdef PDEBUG
2394            p_Test(bres, r);
2395#endif
2396            if (i>j)  bres=p_Neg(bres, r);
2397          }
2398          if (bres!=NULL)
2399          {
2400            /* now mult (prefix, bres, suffix) */
2401            memcpy(aSUFFIX, M1,(rN+1)*sizeof(int));
2402            memcpy(aPREFIX, M1,(rN+1)*sizeof(int));
2403            for (k=1;k<=j;k++) aSUFFIX[k]=0;
2404            for (k=j;k<=rN;k++) aPREFIX[k]=0;
2405            aSUFFIX[0]=0;
2406            aPREFIX[0]=0;
2407            prefix=p_One(r);
2408            suffix=p_One(r);
2409            p_SetExpV(prefix,aPREFIX, r);
2410            p_Setm(prefix, r);
2411            p_SetExpV(suffix,aSUFFIX, r);
2412            p_Setm(suffix, r);
2413            if (!p_LmIsConstant(prefix, r)) bres = gnc_mm_Mult_p(prefix, bres, r);
2414            if (!p_LmIsConstant(suffix, r)) bres = gnc_p_Mult_mm(bres, suffix, r);
2415            ares=p_Add_q(ares, bres, r);
2416            /* What to give free? */
2417        /* Do we have to free aPREFIX/aSUFFIX? it seems so */
2418            p_Delete(&prefix, r);
2419            p_Delete(&suffix, r);
2420          }
2421        }
2422      }
2423      if (ares!=NULL)
2424      {
2425        /* now mult (prefix, bres, suffix) */
2426        memcpy(aSUFFIX, M2,(rN+1)*sizeof(int));
2427        memcpy(aPREFIX, M2,(rN+1)*sizeof(int));
2428        for (k=1;k<=i;k++) aSUFFIX[k]=0;
2429        for (k=i;k<=rN;k++) aPREFIX[k]=0;
2430        aSUFFIX[0]=0;
2431        aPREFIX[0]=0;
2432        prefix=p_One(r);
2433        suffix=p_One(r);
2434        p_SetExpV(prefix,aPREFIX, r);
2435        p_Setm(prefix, r);
2436        p_SetExpV(suffix,aSUFFIX, r);
2437        p_Setm(suffix, r);
2438        bres=ares;
2439        if (!p_LmIsConstant(prefix, r)) bres = gnc_mm_Mult_p(prefix, bres, r);
2440        if (!p_LmIsConstant(suffix, r)) bres = gnc_p_Mult_mm(bres, suffix, r);
2441        res=p_Add_q(res, bres, r);
2442        p_Delete(&prefix, r);
2443        p_Delete(&suffix, r);
2444      }
2445    }
2446  }
2447  freeT(M1, rN);
2448  freeT(M2, rN);
2449  freeT(aPREFIX, rN);
2450  freeT(aSUFFIX, rN);
2451#ifdef PDEBUG
2452  p_Test(res, r);
2453#endif
2454   return(res);
2455}
2456/// returns matrix with the info on noncomm multiplication
2457matrix nc_PrintMat(int a, int b, ring r, int metric)
2458{
2459
2460  if ( (a==b) || !rIsPluralRing(r) ) return(NULL);
2461  int i;
2462  int j;
2463  if (a>b) {j=b; i=a;}
2464  else {j=a; i=b;}
2465  /* i<j */
2466  int rN=r->N;
2467  int size=r->GetNC()->MTsize[UPMATELEM(i,j,rN)];
2468  matrix M = r->GetNC()->MT[UPMATELEM(i,j,rN)];
2469  /*  return(M); */
2470  int sizeofres;
2471  if (metric==0)
2472  {
2473    sizeofres=sizeof(int);
2474  }
2475  if (metric==1)
2476  {
2477    sizeofres=sizeof(number);
2478  }
2479  matrix res=mpNew(size,size);
2480  int s;
2481  int t;
2482  int length;
2483  long totdeg;
2484  poly p;
2485  for(s=1;s<=size;s++)
2486  {
2487    for(t=1;t<=size;t++)
2488    {
2489      p=MATELEM(M,s,t);
2490      if (p==NULL)
2491      {
2492        MATELEM(res,s,t)=0;
2493      }
2494      else
2495      {
2496        length = pLength(p);
2497        if (metric==0) /* length */
2498        {
2499          MATELEM(res,s,t)= p_ISet(length,r);
2500        }
2501        else if (metric==1) /* sum of deg divided by the length */
2502        {
2503          totdeg=0;
2504          while (p!=NULL)
2505          {
2506            totdeg=totdeg+p_Deg(p,r);
2507            pIter(p);
2508          }
2509          number ntd = n_Init(totdeg, r);
2510          number nln = n_Init(length, r);
2511          number nres= n_Div(ntd,nln, r);
2512          n_Delete(&ntd, r);
2513          n_Delete(&nln, r);
2514          MATELEM(res,s,t)=p_NSet(nres,r);
2515        }
2516      }
2517    }
2518  }
2519  return(res);
2520}
2521
2522inline void nc_CleanUp(nc_struct* p)
2523{
2524  assume(p != NULL);
2525  omFreeSize((ADDRESS)p,sizeof(nc_struct));
2526}
2527
2528inline void nc_CleanUp(ring r)
2529{
2530  /* small CleanUp of r->GetNC() */
2531  assume(r != NULL);
2532  nc_CleanUp(r->GetNC());
2533  r->GetNC() = NULL;
2534}
2535
2536void nc_rKill(ring r)
2537// kills the nc extension of ring r
2538{
2539  if( r->GetNC()->GetGlobalMultiplier() != NULL )
2540  {
2541    delete r->GetNC()->GetGlobalMultiplier();
2542    r->GetNC()->GetGlobalMultiplier() = NULL;
2543  }
2544
2545  if( r->GetNC()->GetFormulaPowerMultiplier() != NULL )
2546  {
2547    delete r->GetNC()->GetFormulaPowerMultiplier();
2548    r->GetNC()->GetFormulaPowerMultiplier() = NULL;
2549  }
2550
2551
2552  int i,j;
2553  int rN=r->N;
2554  if ( rN > 1 )
2555  {
2556    for(i=1;i<rN;i++)
2557    {
2558      for(j=i+1;j<=rN;j++)
2559      {
2560        id_Delete((ideal *)&(r->GetNC()->MT[UPMATELEM(i,j,rN)]),r);
2561      }
2562    }
2563    omFreeSize((ADDRESS)r->GetNC()->MT,rN*(rN-1)/2*sizeof(matrix));
2564    omFreeSize((ADDRESS)r->GetNC()->MTsize,rN*(rN-1)/2*sizeof(int));
2565    id_Delete((ideal *)&(r->GetNC()->COM),r);
2566  }
2567  id_Delete((ideal *)&(r->GetNC()->C),r);
2568  id_Delete((ideal *)&(r->GetNC()->D),r);
2569
2570  if( rIsSCA(r) && (r->GetNC()->SCAQuotient() != NULL) )
2571  {
2572    id_Delete(&r->GetNC()->SCAQuotient(), r); // Custom SCA destructor!!!
2573  }
2574
2575
2576  nc_CleanUp(r);
2577}
2578
2579
2580////////////////////////////////////////////////////////////////////////////////////////////////
2581
2582// deprecated:
2583/* for use in getting the mult. matrix elements*/
2584/* ring r must be a currRing! */
2585/* for consistency, copies a poly from the comm. r->GetNC()->basering */
2586/* to its image in NC ring */
2587poly nc_p_CopyGet(poly a, const ring r)
2588{
2589#ifndef PDEBUG
2590  p_Test(a, r);
2591#endif
2592   
2593//  if (r != currRing)
2594//  {
2595//#ifdef PDEBUF
2596//    Werror("nc_p_CopyGet call not in currRing");
2597//#endif
2598//    return(NULL);
2599//  }
2600  return(p_Copy(a,r));
2601}
2602
2603// deprecated:
2604/* for use in defining the mult. matrix elements*/
2605/* ring r must be a currRing! */
2606/* for consistency, puts a polynomial from the NC ring */
2607/* to its presentation in the comm. r->GetNC()->basering */
2608poly nc_p_CopyPut(poly a, const ring r)
2609{
2610#ifndef PDEBUG
2611  p_Test(a, r);
2612#endif
2613
2614//  if (r != currRing)
2615//  {
2616//#ifdef PDEBUF
2617//    Werror("nc_p_CopyGet call not in currRing");
2618//#endif
2619//    return(NULL);
2620//  }
2621
2622  return(p_Copy(a,r));
2623}
2624
2625/* returns TRUE if there were errors */
2626/* checks whether product of vars from PolyVar defines */
2627/* an admissible subalgebra of r */
2628/* r is indeed currRing and assumed to be noncomm. */
2629BOOLEAN nc_CheckSubalgebra(poly PolyVar, ring r)
2630{
2631//  ring save = currRing;
2632//  int WeChangeRing = 0;
2633//  if (currRing != r)
2634//    rChangeCurrRing(r);
2635//    WeChangeRing = 1;
2636//  }
2637  int rN=r->N;
2638  int *ExpVar=(int*)omAlloc0((rN+1)*sizeof(int));
2639  int *ExpTmp=(int*)omAlloc0((rN+1)*sizeof(int));
2640  p_GetExpV(PolyVar, ExpVar, r);
2641  int i; int j; int k;
2642  poly test=NULL;
2643  int OK=1;
2644  for (i=1; i<rN; i++)
2645  {
2646    if (ExpVar[i]==0) /* i.e. not in PolyVar */
2647    {
2648      for (j=i+1; j<=rN; j++)
2649      {
2650        if (ExpVar[j]==0)
2651        {
2652          test = MATELEM(r->GetNC()->D,i,j);
2653          while (test!=NULL)
2654          {
2655            p_GetExpV(test, ExpTmp, r);
2656            OK=1;
2657            for (k=1;k<=rN;k++)
2658            {
2659              if (ExpTmp[k]!=0)
2660              {
2661                if (ExpVar[k]!=0) OK=0;
2662              }
2663            }
2664            if (!OK)
2665            {
2666//              if ( WeChangeRing )
2667//                rChangeCurrRing(save);
2668              return(TRUE);
2669            }
2670            pIter(test);
2671          }
2672        }
2673      }
2674    }
2675  }
2676  freeT(ExpVar,rN);
2677  freeT(ExpTmp,rN);
2678//  if ( WeChangeRing )
2679//    rChangeCurrRing(save);
2680  return(FALSE);
2681}
2682
2683
2684/* returns TRUE if there were errors */
2685/* checks whether the current ordering */
2686/* is admissible for r and D == r->GetNC()->D */
2687/* to be executed in a currRing */
2688BOOLEAN gnc_CheckOrdCondition(matrix D, ring r)
2689{
2690  /* analyze D: an upper triangular matrix of polys */
2691  /* check the ordering condition for D */
2692//  ring save = currRing;
2693//  int WeChangeRing = 0;
2694//  if (r != currRing)
2695//  {
2696//    rChangeCurrRing(r);
2697//    WeChangeRing = 1;
2698//  }
2699  poly p,q;
2700  int i,j;
2701  int report = 0;
2702  for(i=1; i<r->N; i++)
2703  {
2704    for(j=i+1; j<=r->N; j++)
2705    {
2706      p = nc_p_CopyGet(MATELEM(D,i,j),r);
2707      if ( p != NULL)
2708      {
2709         q = p_One(r);
2710         p_SetExp(q,i,1,r);
2711         p_SetExp(q,j,1,r);
2712         p_Setm(q,r);
2713         if (p_LmCmp(q,p,r) != 1) /* i.e. lm(p)==xy < lm(q)==D_ij  */
2714           {
2715              Werror("Bad ordering at %d,%d\n",i,j);
2716#if 0 /*Singularg should not differ from Singular except in error case*/
2717      p_Write(p,r);
2718      p_Write(q,r);
2719#endif
2720              report = 1;
2721           }
2722         p_Delete(&q,r);
2723         p_Delete(&p,r);
2724         p = NULL;
2725      }
2726    }
2727  }
2728//  if ( WeChangeRing )
2729//    rChangeCurrRing(save);
2730  return(report);
2731}
2732
2733
2734
2735BOOLEAN gnc_InitMultiplication(ring r, bool bSetupQuotient = false); // just for a moment
2736
2737/// returns TRUE if there were errors
2738/// analyze inputs, check them for consistency
2739/// detects nc_type, DO NOT initialize multiplication but call for it at the end
2740/// checks the ordering condition and evtl. NDC
2741/// NOTE: all the data belong to the curr,
2742/// we change r which may be the same ring, and must have the same representation!
2743BOOLEAN nc_CallPlural(matrix CCC, matrix DDD,
2744                      poly CCN, poly DDN,
2745                      ring r,
2746                      bool bSetupQuotient, bool bCopyInput, bool bBeQuiet,
2747                      ring curr, bool dummy_ring /*=false*/)
2748{
2749  assume( r != NULL );
2750  assume( curr != NULL );
2751
2752  if( !bSetupQuotient)
2753    assume( (r->qideal == NULL) ); // The basering must NOT be a qring!??
2754
2755  assume( rSamePolyRep(r, curr) || bCopyInput ); // wrong assumption?
2756
2757
2758  if( r->N == 1 ) // clearly commutative!!!
2759  {
2760    assume(
2761           ( (CCC != NULL) && (MATCOLS(CCC) == 1) && (MATROWS(CCC) == 1) && (MATELEM(CCC,1,1) == NULL) ) ||
2762           ( (CCN == NULL) )
2763          );
2764
2765    assume(
2766           ( (DDD != NULL) && (MATCOLS(DDD) == 1) && (MATROWS(DDD) == 1) && (MATELEM(DDD,1,1) == NULL) ) ||
2767           ( (DDN == NULL) )
2768          );
2769    if(!dummy_ring)
2770    {
2771      WarnS("commutative ring with 1 variable");
2772      return FALSE;
2773    }
2774  }
2775
2776  // there must be:
2777  assume( (CCC != NULL) != (CCN != NULL) ); // exactly one data about coeffs (C).
2778  assume( !((DDD != NULL) && (DDN != NULL)) ); // at most one data about tails (D).
2779
2780//  ring save = currRing;
2781//  if( save != curr )
2782//    rChangeCurrRing(curr);
2783
2784   
2785#if OUTPUT
2786  if( CCC != NULL )
2787  {
2788    PrintS("nc_CallPlural(), Input data, CCC: \n");
2789    iiWriteMatrix(CCC, "C", 2, curr, 4);
2790  }
2791  if( DDD != NULL )
2792  {
2793    PrintS("nc_CallPlural(), Input data, DDD: \n");
2794    iiWriteMatrix(DDD, "D", 2, curr, 4);
2795  }
2796#endif
2797
2798
2799#ifndef NDEBUG
2800  id_Test((ideal)CCC, curr);
2801  id_Test((ideal)DDD, curr);
2802  p_Test(CCN, curr);
2803  p_Test(DDN, curr);
2804#endif
2805
2806  if( (!bBeQuiet) && (r->GetNC() != NULL) )
2807    WarnS("going to redefine the algebra structure");
2808
2809//  if( currRing != r )
2810//    rChangeCurrRing(r);
2811
2812  matrix CC = NULL;
2813  poly CN = NULL;
2814  matrix C; bool bCnew = false;
2815
2816  matrix DD = NULL;
2817  poly DN = NULL;
2818  matrix D; bool bDnew = false;
2819
2820  number nN, pN, qN;
2821
2822  bool IsSkewConstant = false, tmpIsSkewConstant;
2823  int i, j;
2824
2825  nc_type nctype = nc_undef;
2826
2827  //////////////////////////////////////////////////////////////////
2828  // check the correctness of arguments, without any real chagnes!!!
2829
2830
2831
2832  // check C
2833  if ((CCC != NULL) && ( (MATCOLS(CCC)==1) || MATROWS(CCC)==1 ) )
2834  {
2835    CN = MATELEM(CCC,1,1);
2836  }
2837  else
2838  {
2839    if ((CCC != NULL) && ( (MATCOLS(CCC)!=r->N) || (MATROWS(CCC)!=r->N) ))
2840    {
2841      Werror("Square %d x %d  matrix expected", r->N, r->N);
2842
2843//      if( currRing != save )
2844//        rChangeCurrRing(save);
2845      return TRUE;
2846    }
2847  }
2848  if (( CCC != NULL) && (CC == NULL)) CC = CCC; // mp_Copy(CCC, ?); // bug!?
2849  if (( CCN != NULL) && (CN == NULL)) CN = CCN;
2850
2851  // check D
2852  if ((DDD != NULL) && ( (MATCOLS(DDD)==1) || MATROWS(DDD)==1 ) )
2853  {
2854    DN = MATELEM(DDD,1,1);
2855  }
2856  else
2857  {
2858    if ((DDD != NULL) && ( (MATCOLS(DDD)!=r->N) || (MATROWS(DDD)!=r->N) ))
2859    {
2860      Werror("Square %d x %d  matrix expected",r->N,r->N);
2861
2862//      if( currRing != save )
2863//        rChangeCurrRing(save);
2864      return TRUE;
2865    }
2866  }
2867
2868  if (( DDD != NULL) && (DD == NULL)) DD = DDD; // mp_Copy(DDD, ?); // ???
2869  if (( DDN != NULL) && (DN == NULL)) DN = DDN;
2870
2871  // further checks and some analysis:
2872  // all data in 'curr'!
2873  if (CN != NULL)       /* create matrix C = CN * Id */
2874  {
2875    nN = p_GetCoeff(CN, curr);
2876    if (n_IsZero(nN, curr))
2877    {
2878      Werror("Incorrect input : zero coefficients are not allowed");
2879
2880//      if( currRing != save )
2881//        rChangeCurrRing(save);
2882      return TRUE;
2883    }
2884
2885    if (n_IsOne(nN, curr))
2886      nctype = nc_lie;
2887    else
2888      nctype = nc_general;
2889
2890    IsSkewConstant = true;
2891
2892    C = mpNew(r->N,r->N); // ring independent!
2893    bCnew = true;
2894
2895    for(i=1; i<r->N; i++)
2896      for(j=i+1; j<=r->N; j++)
2897        MATELEM(C,i,j) = prCopyR_NoSort(CN, curr, r); // nc_p_CopyPut(CN, r); // copy CN from curr into r
2898
2899#ifndef NDEBUG
2900    id_Test((ideal)C, r);
2901#endif
2902
2903  } else
2904  if ( (CN == NULL) && (CC != NULL) ) /* copy matrix C */
2905  {
2906    /* analyze C */
2907
2908    pN = NULL; /* check the consistency later */
2909
2910    if( r->N > 1 )
2911      if ( MATELEM(CC,1,2) != NULL )
2912        pN = p_GetCoeff(MATELEM(CC,1,2), curr);
2913
2914    tmpIsSkewConstant = true;
2915
2916    for(i=1; i<r->N; i++)
2917      for(j=i+1; j<=r->N; j++)
2918      {
2919        if (MATELEM(CC,i,j) == NULL)
2920          qN = NULL;
2921        else
2922          qN = p_GetCoeff(MATELEM(CC,i,j),curr);
2923
2924        if ( qN == NULL )   /* check the consistency: Cij!=0 */
2925        // find also illegal pN
2926        {
2927          Werror("Incorrect input : matrix of coefficients contains zeros in the upper triangle");
2928
2929//        if( currRing != save )
2930//            rChangeCurrRing(save);
2931          return TRUE;
2932        }
2933
2934        if (!n_Equal(pN, qN, curr)) tmpIsSkewConstant = false;
2935      }
2936
2937    if( bCopyInput )
2938    {
2939      C = mp_Copy(CC, curr, r); // Copy C into r!!!???
2940#ifndef NDEBUG
2941      id_Test((ideal)C, r);
2942#endif
2943      bCnew = true;
2944    }
2945    else
2946      C = CC;
2947
2948    IsSkewConstant = tmpIsSkewConstant;
2949
2950    if ( tmpIsSkewConstant && n_IsOne(pN, curr) )
2951      nctype = nc_lie;
2952    else
2953      nctype = nc_general;
2954  }
2955
2956  /* initialition of the matrix D */
2957  if ( DD == NULL ) /* we treat DN only (it could also be NULL) */
2958  {
2959    D = mpNew(r->N,r->N); bDnew = true;
2960
2961    if (DN  == NULL)
2962    {
2963      if ( (nctype == nc_lie) || (nctype == nc_undef) )
2964        nctype = nc_comm; /* it was nc_skew earlier */
2965      else /* nc_general, nc_skew */
2966        nctype = nc_skew;
2967    }
2968    else /* DN  != NULL */
2969      for(i=1; i<r->N; i++)
2970        for(j=i+1; j<=r->N; j++)
2971          MATELEM(D,i,j) = prCopyR_NoSort(DN, curr, r); // project DN into r->GetNC()->basering!
2972#ifndef NDEBUG
2973  id_Test((ideal)D, r);
2974#endif
2975  }
2976  else /* DD != NULL */
2977  {
2978    bool b = true; // DD == null ?
2979
2980    for(int i = 1; (i < r->N) && b; i++)
2981    for(int j = i+1; (j <= r->N) && b; j++)
2982      if (MATELEM(DD, i, j) != NULL)
2983      {
2984        b = false;
2985        break;
2986      }
2987
2988    if (b) // D == NULL!!!
2989    {
2990      if ( (nctype == nc_lie) || (nctype == nc_undef) )
2991        nctype = nc_comm; /* it was nc_skew earlier */
2992      else /* nc_general, nc_skew */
2993        nctype = nc_skew;
2994    }
2995
2996    if( bCopyInput )
2997    {
2998      D = mp_Copy(DD, curr, r); // Copy DD into r!!!
2999#ifndef NDEBUG
3000      id_Test((ideal)D, r);
3001#endif
3002      bDnew = true;
3003    }
3004    else
3005      D = DD;
3006  }
3007
3008  assume( C != NULL );
3009  assume( D != NULL );
3010
3011#if OUTPUT
3012  PrintS("nc_CallPlural(), Computed data, C: \n");
3013  iiWriteMatrix(C, "C", 2, r, 4);
3014
3015  PrintS("nc_CallPlural(), Computed data, D: \n");
3016  iiWriteMatrix(D, "D", 2, r, 4);
3017
3018  Print("\nTemporary: type = %d, IsSkewConstant = %d\n", nctype, IsSkewConstant);
3019#endif
3020
3021
3022  // check the ordering condition for D (both matrix and poly cases):
3023  if ( gnc_CheckOrdCondition(D, r) )
3024  {
3025    if( bCnew ) mp_Delete( &C, r );
3026    if( bDnew ) mp_Delete( &D, r );
3027
3028    Werror("Matrix of polynomials violates the ordering condition");
3029
3030//    if( currRing != save )
3031//      rChangeCurrRing(save);
3032    return TRUE;
3033  }
3034
3035  // okay now we are ready for this!!!
3036
3037  // create new non-commutative structure
3038  nc_struct *nc_new = (nc_struct *)omAlloc0(sizeof(nc_struct));
3039
3040  ncRingType(nc_new, nctype);
3041
3042  nc_new->C = C; // if C and D were given by matrices at the beginning they are in r
3043  nc_new->D = D; // otherwise they should be in r->GetNC()->basering(polynomial * Id_{N})
3044
3045  nc_new->IsSkewConstant = (IsSkewConstant?1:0);
3046
3047  // Setup new NC structure!!!
3048  if (r->GetNC() != NULL)
3049  {
3050#ifndef NDEBUG
3051    WarnS("Changing the NC-structure of an existing NC-ring!!!");
3052#endif   
3053    nc_rKill(r);
3054  }
3055
3056  r->GetNC() = nc_new;
3057
3058//  if( currRing != save )
3059//    rChangeCurrRing(save);
3060
3061  return gnc_InitMultiplication(r, bSetupQuotient);
3062}
3063
3064//////////////////////////////////////////////////////////////////////////////
3065
3066bool nc_rCopy(ring res, const ring r, bool bSetupQuotient)
3067{
3068  if (nc_CallPlural(r->GetNC()->C, r->GetNC()->D, NULL, NULL, res, bSetupQuotient, true, true, r))
3069  {
3070    WarnS("Error occured while coping/setuping the NC structure!"); // No reaction!???
3071    return true; // error
3072  }
3073
3074  return false;
3075}
3076
3077//////////////////////////////////////////////////////////////////////////////
3078BOOLEAN gnc_InitMultiplication(ring r, bool bSetupQuotient)
3079{
3080  /* returns TRUE if there were errors */
3081  /* initialize the multiplication: */
3082  /*  r->GetNC()->MTsize, r->GetNC()->MT, r->GetNC()->COM, */
3083  /* and r->GetNC()->IsSkewConstant for the skew case */
3084  if (rVar(r)==1)
3085  {
3086    ncRingType(r, nc_comm);
3087    r->GetNC()->IsSkewConstant=1;
3088    return FALSE;
3089  }
3090
3091//  ring save = currRing;
3092//  int WeChangeRing = 0;
3093
3094//  if (currRing!=r)
3095//  {
3096//    rChangeCurrRing(r);
3097//    WeChangeRing = 1;
3098//  }
3099//  assume( (currRing == r)
3100//       && (currRing->GetNC()!=NULL) );   // otherwise we cannot work with all these matrices!
3101
3102  int i,j;
3103  r->GetNC()->MT = (matrix *)omAlloc0((r->N*(r->N-1))/2*sizeof(matrix));
3104  r->GetNC()->MTsize = (int *)omAlloc0((r->N*(r->N-1))/2*sizeof(int));
3105  id_Test((ideal)r->GetNC()->C, r);
3106  matrix COM = mp_Copy(r->GetNC()->C, r);
3107  poly p,q;
3108  short DefMTsize=7;
3109  int IsNonComm=0;
3110  int tmpIsSkewConstant;
3111
3112  for(i=1; i<r->N; i++)
3113  {
3114    for(j=i+1; j<=r->N; j++)
3115    {
3116      if ( MATELEM(r->GetNC()->D,i,j) == NULL ) /* quasicommutative case */
3117      {
3118        /* 1x1 mult.matrix */
3119        r->GetNC()->MTsize[UPMATELEM(i,j,r->N)] = 1;
3120        r->GetNC()->MT[UPMATELEM(i,j,r->N)] = mpNew(1,1);
3121      }
3122      else /* pure noncommutative case */
3123      {
3124        /* TODO check the special multiplication properties */
3125        IsNonComm = 1;
3126        p_Delete(&(MATELEM(COM,i,j)),r);
3127        //MATELEM(COM,i,j) = NULL; // done by p_Delete
3128        r->GetNC()->MTsize[UPMATELEM(i,j,r->N)] = DefMTsize; /* default sizes */
3129        r->GetNC()->MT[UPMATELEM(i,j,r->N)] = mpNew(DefMTsize, DefMTsize);
3130      }
3131      /* set MT[i,j,1,1] to c_i_j*x_i*x_j + D_i_j */
3132      p = p_One(r);
3133      if (MATELEM(r->GetNC()->C,i,j)!=NULL)
3134        p_SetCoeff(p,n_Copy(pGetCoeff(MATELEM(r->GetNC()->C,i,j)),r),r);
3135      p_SetExp(p,i,1,r);
3136      p_SetExp(p,j,1,r);
3137      p_Setm(p,r);
3138      p_Test(MATELEM(r->GetNC()->D,i,j),r);
3139      q =  nc_p_CopyGet(MATELEM(r->GetNC()->D,i,j),r);
3140      p = p_Add_q(p,q,r);
3141      MATELEM(r->GetNC()->MT[UPMATELEM(i,j,r->N)],1,1) = nc_p_CopyPut(p,r);
3142      p_Delete(&p,r);
3143      // p = NULL;// done by p_Delete
3144    }
3145  }
3146  if (ncRingType(r)==nc_undef)
3147  {
3148    if (IsNonComm==1)
3149    {
3150      //      assume(pN!=NULL);
3151      //      if ((tmpIsSkewConstant==1) && (nIsOne(pGetCoeff(pN)))) r->GetNC()->type=nc_lie;
3152      //      else r->GetNC()->type=nc_general;
3153    }
3154    if (IsNonComm==0)
3155    {
3156      ncRingType(r, nc_skew); /* TODO: check whether it is commutative */
3157      r->GetNC()->IsSkewConstant=tmpIsSkewConstant;
3158    }
3159  }
3160  r->GetNC()->COM=COM;
3161 
3162
3163  nc_p_ProcsSet(r, r->p_Procs);
3164
3165  if(bSetupQuotient) // Test me!!!
3166    nc_SetupQuotient(r, NULL, false); // no copy!
3167
3168 
3169//  if (save != currRing)
3170//    rChangeCurrRing(save);
3171
3172  return FALSE;
3173}
3174
3175
3176// set pProcs for r and global variable p_Procs as for general non-commutative algebras.
3177static inline
3178void gnc_p_ProcsSet(ring rGR, p_Procs_s* p_Procs)
3179{
3180  // "commutative"
3181  p_Procs->p_Mult_mm  = rGR->p_Procs->p_Mult_mm  = gnc_p_Mult_mm;
3182  p_Procs->pp_Mult_mm = rGR->p_Procs->pp_Mult_mm = gnc_pp_Mult_mm;
3183  p_Procs->p_Minus_mm_Mult_qq = rGR->p_Procs->p_Minus_mm_Mult_qq = nc_p_Minus_mm_Mult_qq;
3184
3185  // non-commutaitve multiplication by monomial from the left
3186  rGR->GetNC()->p_Procs.mm_Mult_p   = gnc_mm_Mult_p;
3187  rGR->GetNC()->p_Procs.mm_Mult_pp  = gnc_mm_Mult_pp;
3188
3189#if 0
3190  // Previous Plural's implementation...
3191  rGR->GetNC()->p_Procs.SPoly       = gnc_CreateSpolyOld;
3192  rGR->GetNC()->p_Procs.ReduceSPoly = gnc_ReduceSpolyOld;
3193
3194  rGR->GetNC()->p_Procs.BucketPolyRed  = gnc_kBucketPolyRedOld;
3195  rGR->GetNC()->p_Procs.BucketPolyRed_Z= gnc_kBucketPolyRed_ZOld;
3196#else
3197  // A bit cleaned up and somewhat rewritten functions...
3198  rGR->GetNC()->p_Procs.SPoly       = gnc_CreateSpolyNew;
3199  rGR->GetNC()->p_Procs.ReduceSPoly = gnc_ReduceSpolyNew;
3200
3201  rGR->GetNC()->p_Procs.BucketPolyRed  = gnc_kBucketPolyRedNew;
3202  rGR->GetNC()->p_Procs.BucketPolyRed_Z= gnc_kBucketPolyRed_ZNew;
3203#endif
3204
3205  // warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object?
3206  if (rHasLocalOrMixedOrdering(rGR))
3207    rGR->GetNC()->p_Procs.GB = cast_A_to_vptr(gnc_gr_mora);
3208  else
3209    rGR->GetNC()->p_Procs.GB = cast_A_to_vptr(gnc_gr_bba);
3210
3211///////////  rGR->GetNC()->p_Procs.GB          = gnc_gr_bba; // bba even for local case!
3212// old ///    r->GetNC()->GB()            = gnc_gr_bba;
3213//   rGR->GetNC()->p_Procs.GlobalGB    = gnc_gr_bba;
3214//   rGR->GetNC()->p_Procs.LocalGB     = gnc_gr_mora;
3215//  const ring save = currRing; if( save != r ) rChangeCurrRing(r);
3216//  ideal res = gnc_gr_bba(F, Q, w, hilb, strat/*, r*/);
3217//  if( save != r )     rChangeCurrRing(save);     return (res);
3218
3219
3220#if 0
3221    // Old Stuff
3222    p_Procs->p_Mult_mm   = gnc_p_Mult_mm;
3223    _p_procs->p_Mult_mm  = gnc_p_Mult_mm;
3224
3225    p_Procs->pp_Mult_mm  = gnc_pp_Mult_mm;
3226    _p_procs->pp_Mult_mm = gnc_pp_Mult_mm;
3227
3228    p_Procs->p_Minus_mm_Mult_qq = NULL; // gnc_p_Minus_mm_Mult_qq_ign;
3229    _p_procs->p_Minus_mm_Mult_qq= NULL; // gnc_p_Minus_mm_Mult_qq_ign;
3230
3231    r->GetNC()->mmMultP()       = gnc_mm_Mult_p;
3232    r->GetNC()->mmMultPP()      = gnc_mm_Mult_pp;
3233
3234    r->GetNC()->SPoly()         = gnc_CreateSpoly;
3235    r->GetNC()->ReduceSPoly()   = gnc_ReduceSpoly;
3236
3237#endif
3238}
3239
3240
3241// set pProcs table for rGR and global variable p_Procs
3242void nc_p_ProcsSet(ring rGR, p_Procs_s* p_Procs)
3243{
3244  assume(rIsPluralRing(rGR));
3245  assume(p_Procs!=NULL);
3246
3247  gnc_p_ProcsSet(rGR, p_Procs);
3248
3249  if(rIsSCA(rGR) && ncExtensions(SCAMASK) )
3250  {
3251    sca_p_ProcsSet(rGR, p_Procs);
3252  }
3253
3254  if( ncExtensions(NOPLURALMASK) )
3255    ncInitSpecialPairMultiplication(rGR);
3256
3257  if(!rIsSCA(rGR) && !ncExtensions(NOFORMULAMASK))
3258    ncInitSpecialPowersMultiplication(rGR);
3259
3260}
3261
3262
3263/// substitute the n-th variable by e in p
3264/// destroy p
3265/// e is not a constant
3266poly nc_pSubst(poly p, int n, poly e, const ring r)
3267{
3268  int rN = r->N;
3269  int *PRE = (int *)omAlloc0((rN+1)*sizeof(int));
3270  int *SUF = (int *)omAlloc0((rN+1)*sizeof(int));
3271  int i,pow;
3272  number C;
3273  poly suf,pre;
3274  poly res = NULL;
3275  poly out = NULL;
3276  while ( p!= NULL )
3277  {
3278    C =  p_GetCoeff(p, r);
3279    p_GetExpV(p, PRE, r); /* faster splitting? */
3280    pow = PRE[n]; PRE[n]=0;
3281    res = NULL;
3282    if (pow!=0)
3283    {
3284      for (i=n+1; i<=rN; i++)
3285      {
3286         SUF[i] = PRE[i];
3287         PRE[i] = 0;
3288      }
3289      res =  p_Power(p_Copy(e, r),pow, r);
3290      /* multiply with prefix */
3291      pre = p_One(r);
3292      p_SetExpV(pre,PRE, r);
3293      p_Setm(pre, r);
3294      res = nc_mm_Mult_p(pre,res, r);
3295      /* multiply with suffix */
3296      suf = p_One(r);
3297      p_SetExpV(suf,SUF, r);
3298      p_Setm(suf, r);
3299      res = p_Mult_mm(res,suf, r);
3300      res = p_Mult_nn(res,C, r);
3301      p_SetComp(res,PRE[0], r);
3302    }
3303    else /* pow==0 */
3304    {
3305      res = p_Head(p, r);
3306    }
3307    p   = p_LmDeleteAndNext(p, r);
3308    out = p_Add_q(out,res, r);
3309  }
3310  freeT(PRE,rN);
3311  freeT(SUF,rN);
3312  return(out);
3313}
3314
3315
3316// creates a commutative nc extension; "converts" comm.ring to a Plural ring
3317ring nc_rCreateNCcomm(ring r)
3318{
3319  if (rIsPluralRing(r)) return r;
3320
3321  ring rr = rCopy(r);
3322
3323  matrix C = mpNew(rr->N,rr->N); // ring-independent!?!
3324  matrix D = mpNew(rr->N,rr->N);
3325
3326  for(int i=1; i<rr->N; i++)
3327    for(int j=i+1; j<=rr->N; j++)
3328      MATELEM(C,i,j) = p_One(rr);
3329
3330  if (nc_CallPlural(C, D, NULL, NULL, rr, false, true, false, rr, TRUE)) // TODO: what about quotient ideal?
3331    WarnS("Error initializing multiplication!"); // No reaction!???
3332
3333  return rr;
3334}
3335
3336  /* NOT USED ANYMORE: replaced by maFindPerm in ring.cc */
3337  /* for use with embeddings: currRing is a sum of smaller rings */
3338  /* and srcRing is one of such smaller rings */
3339  /* shift defines the position of a subring in srcRing */
3340  /* par_shift defines the position of a subfield in basefield of CurrRing */
3341poly p_CopyEmbed(poly p, ring srcRing, int shift, int par_shift, ring dstRing)
3342{
3343  if (dstRing == srcRing)
3344  {
3345    return(p_Copy(p,dstRing));
3346  }
3347  nMapFunc nMap=n_SetMap(srcRing->cf, dstRing->cf);
3348  poly q;
3349  //  if ( nMap == nCopy)
3350  //  {
3351  //    q = prCopyR(p,srcRing);
3352  //  }
3353  //  else
3354  {
3355    int *perm = (int *)omAlloc0((rVar(srcRing)+1)*sizeof(int));
3356    int *par_perm = (int *)omAlloc0((rPar(srcRing)+1)*sizeof(int));
3357    //    int *par_perm = (int *)omAlloc0((rPar(srcRing)+1)*sizeof(int));
3358    int i;
3359    //    if (srcRing->P > 0)
3360    //    {
3361    //      for (i=0; i<srcRing->P; i++)
3362    //  par_perm[i]=-i;
3363    //    }
3364    if ((shift<0) || (shift > rVar(srcRing))) // ???
3365    {
3366      Werror("bad shifts in p_CopyEmbed");
3367      return(0);
3368    }
3369    for (i=1; i<= srcRing->N; i++)
3370    {
3371      perm[i] = shift+i;
3372    }
3373    q = p_PermPoly(p,perm,srcRing, dstRing, nMap,par_perm, rPar(srcRing));
3374  }
3375  return(q);
3376}
3377
3378BOOLEAN rIsLikeOpposite(ring rBase, ring rCandidate)
3379{
3380  /* the same basefield */
3381  int diagnose = TRUE;
3382  nMapFunc nMap = n_SetMap(rCandidate->cf, rBase->cf); // reverse?
3383
3384//////  if (nMap != nCopy) diagnose = FALSE;
3385  if (nMap == NULL) diagnose = FALSE;
3386 
3387
3388  /* same number of variables */
3389  if (rBase->N != rCandidate->N) diagnose = FALSE;
3390  /* nc and comm ring */
3391  if ( rIsPluralRing(rBase) != rIsPluralRing(rCandidate) ) diagnose = FALSE;
3392  /* both are qrings */
3393  /* NO CHECK, since it is used in building opposite qring */
3394  /*  if ( ((rBase->qideal != NULL) && (rCandidate->qideal == NULL)) */
3395  /*       || ((rBase->qideal == NULL) && (rCandidate->qideal != NULL)) ) */
3396  /*  diagnose = FALSE; */
3397  /* TODO: varnames are e->E etc */
3398  return diagnose;
3399}
3400
3401
3402
3403
3404/// opposes a vector p from Rop to currRing (dst!)
3405poly pOppose(ring Rop, poly p, const ring dst)
3406{
3407  /* the simplest case:*/
3408  if (  Rop == dst )  return(p_Copy(p, dst));
3409  /* check Rop == rOpposite(currRing) */
3410
3411 
3412  if ( !rIsLikeOpposite(dst, Rop) )
3413  {
3414    WarnS("an opposite ring should be used");
3415    return NULL;
3416  }
3417
3418  nMapFunc nMap = n_SetMap(Rop->cf, dst->cf); // reverse?
3419
3420  /* nMapFunc nMap = nSetMap(Rop);*/
3421  /* since we know that basefields coinside! */
3422
3423  // coinside???
3424 
3425  int *perm=(int *)omAlloc0((Rop->N+1)*sizeof(int));
3426  if (!p_IsConstantPoly(p, Rop))
3427  {
3428    /* we know perm exactly */
3429    int i;
3430    for(i=1; i<=Rop->N; i++)
3431    {
3432      perm[i] = Rop->N+1-i;
3433    }
3434  }
3435  poly res = p_PermPoly(p, perm, Rop, dst, nMap);
3436  omFreeSize((ADDRESS)perm,(Rop->N+1)*sizeof(int));
3437
3438  p_Test(res, dst);
3439
3440  return res;
3441}
3442
3443/// opposes a module I from Rop to currRing(dst)
3444ideal idOppose(ring Rop, ideal I, const ring dst)
3445{
3446  /* the simplest case:*/
3447  if ( Rop == dst ) return id_Copy(I, dst);
3448
3449  /* check Rop == rOpposite(currRing) */
3450  if (!rIsLikeOpposite(dst, Rop))
3451  {
3452    WarnS("an opposite ring should be used");
3453    return NULL;
3454  }
3455  int i;
3456  ideal idOp = idInit(I->ncols, I->rank);
3457  for (i=0; i< (I->ncols)*(I->nrows); i++)
3458  {
3459    idOp->m[i] = pOppose(Rop,I->m[i], dst);
3460  }
3461  id_Test(idOp, dst);
3462  return idOp;
3463}
3464
3465
3466bool nc_SetupQuotient(ring rGR, const ring rG, bool bCopy)
3467{
3468  if( rGR->qideal == NULL )
3469    return false; // no quotient = no work! done!? What about factors of SCA?
3470
3471  bool ret = true;
3472  // currently only super-commutative extension deals with factors.
3473
3474  if( ncExtensions(SCAMASK)  )
3475  {
3476    bool sca_ret = sca_SetupQuotient(rGR, rG, bCopy);
3477
3478    if(sca_ret) // yes it was dealt with!
3479      ret = false;
3480  }
3481
3482  if( bCopy )
3483  {
3484    assume(rIsPluralRing(rGR) == rIsPluralRing(rG));
3485    assume((rGR->qideal==NULL) == (rG->qideal==NULL));
3486    assume(rIsSCA(rGR) == rIsSCA(rG));
3487    assume(ncRingType(rGR) == ncRingType(rG));
3488  }
3489
3490  return ret;
3491}
3492
3493
3494
3495// int Commutative_Context(ring r, leftv expression)
3496//   /* returns 1 if expression consists */
3497//   /*  of commutative elements */
3498// {
3499//   /* crucial: poly -> ideal, module, matrix  */
3500// }
3501
3502// int Comm_Context_Poly(ring r, poly p)
3503// {
3504//   poly COMM=r->GetNC()->COMM;
3505//   poly pp=pOne();
3506//   memset(pp->exp,0,r->ExpL_Size*sizeof(long));
3507//   while (p!=NULL)
3508//   {
3509//     for (i=0;i<=r->ExpL_Size;i++)
3510//     {
3511//       if ((p->exp[i]) && (pp->exp[i]))  return(FALSE);
3512//       /* nonzero exponent of non-comm variable */
3513//     }
3514//     pIter(p);
3515//   }
3516//   return(TRUE);
3517// }
3518#endif
Note: See TracBrowser for help on using the repository browser.