source: git/libpolys/polys/nc/old.gring.cc @ 232bbd5

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