source: git/libpolys/polys/nc/gring.cc @ 4021bb

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