source: git/kernel/gring.cc @ d51339

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