source: git/kernel/gring.cc @ 835d83

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