source: git/kernel/gring.cc @ 43cbc0

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