source: git/kernel/gring.cc @ 690e21e

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