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

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