source: git/kernel/gring.cc @ d0f98e

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