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

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