source: git/kernel/kspoly.cc @ b29153

spielwiese
Last change on this file since b29153 was 9f5fca, checked in by Viktor Levandovskyy <levandov@…>, 15 years ago
*levandov: shrinking in nonhomog letterplace git-svn-id: file:///usr/local/Singular/svn/trunk@11235 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 14.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: kspoly.cc,v 1.16 2008-12-10 19:48:51 levandov Exp $ */
5/*
6*  ABSTRACT -  Routines for Spoly creation and reductions
7*/
8
9// #define PDEBUG 2
10#include "mod2.h"
11#include "kutil.h"
12#include "numbers.h"
13#include "p_polys.h"
14#include "p_Procs.h"
15#include "gring.h"
16#ifdef HAVE_RINGS
17#include "polys.h"
18#endif
19
20#ifdef KDEBUG
21int red_count = 0;
22int create_count = 0;
23// define this if reductions are reported on TEST_OPT_DEBUG
24// #define TEST_OPT_DEBUG_RED
25#endif
26
27/***************************************************************
28 *
29 * Reduces PR with PW
30 * Assumes PR != NULL, PW != NULL, Lm(PW) divides Lm(PR)
31 *
32 ***************************************************************/
33int ksReducePoly(LObject* PR,
34                 TObject* PW,
35                 poly spNoether,
36                 number *coef,
37                 kStrategy strat)
38{
39#ifdef KDEBUG
40  red_count++;
41#ifdef TEST_OPT_DEBUG_RED
42  if (TEST_OPT_DEBUG)
43  {
44    Print("Red %d:", red_count); PR->wrp(); Print(" with:");
45    PW->wrp();
46  }
47#endif
48#endif
49  int ret = 0;
50  ring tailRing = PR->tailRing;
51  kTest_L(PR);
52  kTest_T(PW);
53
54  poly p1 = PR->GetLmTailRing();   // p2 | p1
55  poly p2 = PW->GetLmTailRing();   // i.e. will reduce p1 with p2; lm = LT(p1) / LM(p2)
56  poly t2 = pNext(p2), lm = p1;    // t2 = p2 - LT(p2); really compute P = LC(p2)*p1 - LT(p1)/LM(p2)*p2
57  assume(p1 != NULL && p2 != NULL);// Attention, we have rings and there LC(p2) and LC(p1) are special
58  p_CheckPolyRing(p1, tailRing);
59  p_CheckPolyRing(p2, tailRing);
60
61  pAssume1(p2 != NULL && p1 != NULL &&
62           p_DivisibleBy(p2,  p1, tailRing));
63
64  pAssume1(p_GetComp(p1, tailRing) == p_GetComp(p2, tailRing) ||
65           (p_GetComp(p2, tailRing) == 0 &&
66            p_MaxComp(pNext(p2),tailRing) == 0));
67
68#ifdef HAVE_PLURAL
69  if (rIsPluralRing(currRing))
70  {
71    // for the time being: we know currRing==strat->tailRing
72    // no exp-bound checking needed
73    // (only needed if exp-bound(tailring)<exp-b(currRing))
74    number c;
75    if (PR->bucket!=NULL)  nc_kBucketPolyRed(PR->bucket, p2,&c);
76    else 
77    {
78      poly _p = (PR->t_p != NULL ? PR->t_p : PR->p);
79      assume(_p != NULL);
80      nc_PolyPolyRed(_p, p2,&c);
81      if (PR->t_p!=NULL) PR->t_p=_p; else PR->p=_p;
82      PR->pLength=pLength(_p);
83    }
84    if (coef!=NULL) *coef=c;
85    else nDelete(&c);
86    return 0;
87  }
88#endif
89
90  if (t2==NULL)           // Divisor is just one term, therefore it will
91  {                       // just cancel the leading term
92    PR->LmDeleteAndIter();
93    if (coef != NULL) *coef = n_Init(1, tailRing);
94    return 0;
95  }
96
97  p_ExpVectorSub(lm, p2, tailRing); // Calculate the Monomial we must multiply to p2
98
99  if (tailRing != currRing)
100  {
101    // check that reduction does not violate exp bound
102    while (PW->max != NULL && !p_LmExpVectorAddIsOk(lm, PW->max, tailRing))
103    {
104      // undo changes of lm
105      p_ExpVectorAdd(lm, p2, tailRing);
106      if (strat == NULL) return 2;
107      if (! kStratChangeTailRing(strat, PR, PW)) return -1;
108      tailRing = strat->tailRing;
109      p1 = PR->GetLmTailRing();
110      p2 = PW->GetLmTailRing();
111      t2 = pNext(p2);
112      lm = p1;
113      p_ExpVectorSub(lm, p2, tailRing);
114      ret = 1;
115    }
116  }
117
118  // take care of coef buisness
119  if (! n_IsOne(pGetCoeff(p2), tailRing))
120  {
121    number bn = pGetCoeff(lm);
122    number an = pGetCoeff(p2);
123    int ct = ksCheckCoeff(&an, &bn);    // Calculate special LC
124    p_SetCoeff(lm, bn, tailRing);
125    if ((ct == 0) || (ct == 2))
126      PR->Tail_Mult_nn(an);
127    if (coef != NULL) *coef = an;
128    else n_Delete(&an, tailRing);
129  }
130  else
131  {
132    if (coef != NULL) *coef = n_Init(1, tailRing);
133  }
134
135
136  // and finally,
137  PR->Tail_Minus_mm_Mult_qq(lm, t2, PW->GetpLength() - 1, spNoether);
138  assume(PW->GetpLength() == pLength(PW->p != NULL ? PW->p : PW->t_p));
139  PR->LmDeleteAndIter();
140
141  // the following is commented out: shrinking
142#ifdef HAVE_SHIFTBBA_NONEXISTENT
143  if ( (currRing->isLPring) && (!strat->homog) )
144  {
145    // assume? h->p in currRing
146    PR->GetP();
147    poly qq = p_Shrink(PR->p, currRing->isLPring, currRing);
148    PR->Clear(); // does the right things
149    PR->p = qq; 
150    PR->t_p = NULL;
151    PR->SetShortExpVector();
152  }
153#endif
154 
155#if defined(KDEBUG) && defined(TEST_OPT_DEBUG_RED)
156  if (TEST_OPT_DEBUG)
157  {
158    Print(" to: "); PR->wrp(); Print("\n");
159  }
160#endif
161  return ret;
162}
163
164/***************************************************************
165 *
166 * Creates S-Poly of p1 and p2
167 *
168 *
169 ***************************************************************/
170void ksCreateSpoly(LObject* Pair,   poly spNoether,
171                   int use_buckets, ring tailRing,
172                   poly m1, poly m2, TObject** R)
173{
174#ifdef KDEBUG
175  create_count++;
176#endif
177  kTest_L(Pair);
178  poly p1 = Pair->p1;
179  poly p2 = Pair->p2;
180  poly last;
181  Pair->tailRing = tailRing;
182
183  assume(p1 != NULL);
184  assume(p2 != NULL);
185  assume(tailRing != NULL);
186
187  poly a1 = pNext(p1), a2 = pNext(p2);
188  number lc1 = pGetCoeff(p1), lc2 = pGetCoeff(p2);
189  int co=0, ct = ksCheckCoeff(&lc1, &lc2); // gcd and zero divisors
190
191  int l1=0, l2=0;
192
193  if (p_GetComp(p1, currRing)!=p_GetComp(p2, currRing))
194  {
195    if (p_GetComp(p1, currRing)==0)
196    {
197      co=1;
198      p_SetCompP(p1,p_GetComp(p2, currRing), currRing, tailRing);
199    }
200    else
201    {
202      co=2;
203      p_SetCompP(p2, p_GetComp(p1, currRing), currRing, tailRing);
204    }
205  }
206
207  // get m1 = LCM(LM(p1), LM(p2))/LM(p1)
208  //     m2 = LCM(LM(p1), LM(p2))/LM(p2)
209  if (m1 == NULL)
210    k_GetLeadTerms(p1, p2, currRing, m1, m2, tailRing);
211
212  pSetCoeff0(m1, lc2);
213  pSetCoeff0(m2, lc1);  // and now, m1 * LT(p1) == m2 * LT(p2)
214
215  if (R != NULL)
216  {
217    if (Pair->i_r1 == -1)
218    {
219      l1 = pLength(p1) - 1;
220    }
221    else
222    {
223      l1 = (R[Pair->i_r1])->GetpLength() - 1;
224    }
225    if (Pair->i_r2 == -1)
226    {
227      l2 = pLength(p2) - 1;
228    }
229    else
230    {
231      l2 = (R[Pair->i_r2])->GetpLength() - 1;
232    }
233  }
234
235  // get m2 * a2
236  if (spNoether != NULL)
237  {
238    l2 = -1;
239    a2 = tailRing->p_Procs->pp_Mult_mm_Noether(a2, m2, spNoether, l2, tailRing,last);
240    assume(l2 == pLength(a2));
241  }
242  else
243    a2 = tailRing->p_Procs->pp_Mult_mm(a2, m2, tailRing,last);
244#ifdef HAVE_RINGS
245  if (!(rField_is_Domain(currRing))) l2 = pLength(a2);
246#endif
247
248  Pair->SetLmTail(m2, a2, l2, use_buckets, tailRing, last);
249
250  // get m2*a2 - m1*a1
251  Pair->Tail_Minus_mm_Mult_qq(m1, a1, l1, spNoether);
252
253  // Clean-up time
254  Pair->LmDeleteAndIter();
255  p_LmDelete(m1, tailRing);
256
257  if (co != 0)
258  {
259    if (co==1)
260    {
261      p_SetCompP(p1,0, currRing, tailRing);
262    }
263    else
264    {
265      p_SetCompP(p2,0, currRing, tailRing);
266    }
267  }
268
269  // the following is commented out: shrinking
270#ifdef HAVE_SHIFTBBA_NONEXISTENT
271  if (currRing->isLPring)
272  {
273    // assume? h->p in currRing
274    Pair->GetP();
275    poly qq = p_Shrink(Pair->p, currRing->isLPring, currRing);
276    Pair->Clear(); // does the right things
277    Pair->p = qq; 
278    Pair->t_p = NULL;
279    Pair->SetShortExpVector();
280  }
281#endif
282
283}
284
285int ksReducePolyTail(LObject* PR, TObject* PW, poly Current, poly spNoether)
286{
287  BOOLEAN ret;
288  number coef;
289  poly Lp =     PR->GetLmCurrRing();
290  poly Save =   PW->GetLmCurrRing();
291
292  kTest_L(PR);
293  kTest_T(PW);
294  pAssume(pIsMonomOf(Lp, Current));
295
296  assume(Lp != NULL && Current != NULL && pNext(Current) != NULL);
297  assume(PR->bucket == NULL);
298
299  LObject Red(pNext(Current), PR->tailRing);
300  TObject With(PW, Lp == Save);
301
302  pAssume(!pHaveCommonMonoms(Red.p, With.p));
303  ret = ksReducePoly(&Red, &With, spNoether, &coef);
304
305  if (!ret)
306  {
307    if (! n_IsOne(coef, currRing))
308    {
309      pNext(Current) = NULL;
310      if (Current == PR->p && PR->t_p != NULL)
311        pNext(PR->t_p) = NULL;
312      PR->Mult_nn(coef);
313    }
314
315    n_Delete(&coef, currRing);
316    pNext(Current) = Red.GetLmTailRing();
317    if (Current == PR->p && PR->t_p != NULL)
318      pNext(PR->t_p) = pNext(Current);
319  }
320
321  if (Lp == Save)
322    With.Delete();
323
324  // the following is commented out: shrinking
325#ifdef HAVE_SHIFTBBA_NONEXISTENT
326  if (currRing->isLPring)
327  {
328    // assume? h->p in currRing
329    PR->GetP();
330    poly qq = p_Shrink(PR->p, currRing->isLPring, currRing);
331    PR->Clear(); // does the right things
332    PR->p = qq; 
333    PR->t_p = NULL;
334    PR->SetShortExpVector();
335  }
336#endif
337
338  return ret;
339}
340
341/***************************************************************
342 *
343 * Auxillary Routines
344 *
345 *
346 ***************************************************************/
347
348/*
349* input - output: a, b
350* returns:
351*   a := a/gcd(a,b), b := b/gcd(a,b)
352*   and return value
353*       0  ->  a != 1,  b != 1
354*       1  ->  a == 1,  b != 1
355*       2  ->  a != 1,  b == 1
356*       3  ->  a == 1,  b == 1
357*   this value is used to control the spolys
358*/
359int ksCheckCoeff(number *a, number *b)
360{
361  int c = 0;
362  number an = *a, bn = *b;
363  nTest(an);
364  nTest(bn);
365
366  number cn = nGcd(an, bn, currRing);
367
368  if(nIsOne(cn))
369  {
370    an = nCopy(an);
371    bn = nCopy(bn);
372  }
373  else
374  {
375    an = nIntDiv(an, cn);
376    bn = nIntDiv(bn, cn);
377  }
378  nDelete(&cn);
379  if (nIsOne(an))
380  {
381    c = 1;
382  }
383  if (nIsOne(bn))
384  {
385    c += 2;
386  }
387  *a = an;
388  *b = bn;
389  return c;
390}
391
392/*2
393* creates the leading term of the S-polynomial of p1 and p2
394* do not destroy p1 and p2
395* remarks:
396*   1. the coefficient is 0 (nNew)
397*   1. a) in the case of coefficient ring, the coefficient is calculated
398*   2. pNext is undefined
399*/
400//static void bbb() { int i=0; }
401poly ksCreateShortSpoly(poly p1, poly p2, ring tailRing)
402{
403  poly a1 = pNext(p1), a2 = pNext(p2);
404  Exponent_t c1=p_GetComp(p1, currRing),c2=p_GetComp(p2, currRing);
405  Exponent_t c;
406  poly m1,m2;
407  number t1 = NULL,t2 = NULL;
408  int cm,i;
409  BOOLEAN equal;
410
411#ifdef HAVE_RINGS
412  BOOLEAN is_Ring=rField_is_Ring(currRing);
413  number lc1 = pGetCoeff(p1), lc2 = pGetCoeff(p2);
414  if (is_Ring)
415  {
416    ksCheckCoeff(&lc1, &lc2); // gcd and zero divisors
417    if (a1 != NULL) t2 = nMult(pGetCoeff(a1),lc2);
418    if (a2 != NULL) t1 = nMult(pGetCoeff(a2),lc1);
419    while (a1 != NULL && nIsZero(t2))
420    {
421      pIter(a1);
422      nDelete(&t2);
423      if (a1 != NULL) t2 = nMult(pGetCoeff(a1),lc2);
424    }
425    while (a2 != NULL && nIsZero(t1))
426    {
427      pIter(a2);
428      nDelete(&t1);
429      if (a2 != NULL) t1 = nMult(pGetCoeff(a2),lc1);
430    }
431  }
432#endif
433
434  if (a1==NULL)
435  {
436    if(a2!=NULL)
437    {
438      m2=p_Init(currRing);
439x2:
440      for (i = pVariables; i; i--)
441      {
442        c = p_GetExpDiff(p1, p2,i, currRing);
443        if (c>0)
444        {
445          p_SetExp(m2,i,(c+p_GetExp(a2,i,tailRing)),currRing);
446        }
447        else
448        {
449          p_SetExp(m2,i,p_GetExp(a2,i,tailRing),currRing);
450        }
451      }
452      if ((c1==c2)||(c2!=0))
453      {
454        p_SetComp(m2,p_GetComp(a2,tailRing), currRing);
455      }
456      else
457      {
458        p_SetComp(m2,c1,currRing);
459      }
460      p_Setm(m2, currRing);
461#ifdef HAVE_RINGS
462      if (is_Ring)
463      {
464          nDelete(&lc1);
465          nDelete(&lc2);
466          nDelete(&t2);
467          pSetCoeff0(m2, t1);
468      }
469      else
470#endif
471        nNew(&(pGetCoeff(m2)));
472      return m2;
473    }
474    else
475    {
476#ifdef HAVE_RINGS
477    if (is_Ring)
478    {
479      nDelete(&lc1);
480      nDelete(&lc2);
481      nDelete(&t1);
482      nDelete(&t2);
483    }
484#endif
485      return NULL;
486    }
487  }
488  if (a2==NULL)
489  {
490    m1=p_Init(currRing);
491x1:
492    for (i = pVariables; i; i--)
493    {
494      c = p_GetExpDiff(p2, p1,i,currRing);
495      if (c>0)
496      {
497        p_SetExp(m1,i,(c+p_GetExp(a1,i, tailRing)),currRing);
498      }
499      else
500      {
501        p_SetExp(m1,i,p_GetExp(a1,i, tailRing), currRing);
502      }
503    }
504    if ((c1==c2)||(c1!=0))
505    {
506      p_SetComp(m1,p_GetComp(a1,tailRing),currRing);
507    }
508    else
509    {
510      p_SetComp(m1,c2,currRing);
511    }
512    p_Setm(m1, currRing);
513#ifdef HAVE_RINGS
514    if (is_Ring)
515    {
516      pSetCoeff0(m1, t2);
517      nDelete(&lc1);
518      nDelete(&lc2);
519      nDelete(&t1);
520    }
521    else
522#endif
523      nNew(&(pGetCoeff(m1)));
524    return m1;
525  }
526  m1 = p_Init(currRing);
527  m2 = p_Init(currRing);
528  for(;;)
529  {
530    for (i = pVariables; i; i--)
531    {
532      c = p_GetExpDiff(p1, p2,i,currRing);
533      if (c > 0)
534      {
535        p_SetExp(m2,i,(c+p_GetExp(a2,i,tailRing)), currRing);
536        p_SetExp(m1,i,p_GetExp(a1,i, tailRing), currRing);
537      }
538      else
539      {
540        p_SetExp(m1,i,(p_GetExp(a1,i,tailRing)-c), currRing);
541        p_SetExp(m2,i,p_GetExp(a2,i, tailRing), currRing);
542      }
543    }
544    if(c1==c2)
545    {
546      p_SetComp(m1,p_GetComp(a1, tailRing), currRing);
547      p_SetComp(m2,p_GetComp(a2, tailRing), currRing);
548    }
549    else
550    {
551      if(c1!=0)
552      {
553        p_SetComp(m1,p_GetComp(a1, tailRing), currRing);
554        p_SetComp(m2,c1, currRing);
555      }
556      else
557      {
558        p_SetComp(m2,p_GetComp(a2, tailRing), currRing);
559        p_SetComp(m1,c2, currRing);
560      }
561    }
562    p_Setm(m1,currRing);
563    p_Setm(m2,currRing);
564    cm = p_LmCmp(m1, m2,currRing);
565    if (cm!=0)
566    {
567      if(cm==1)
568      {
569        p_LmFree(m2,currRing);
570#ifdef HAVE_RINGS
571        if (is_Ring)
572        {
573          pSetCoeff0(m1, t2);
574          nDelete(&lc1);
575          nDelete(&lc2);
576          nDelete(&t1);
577        }
578        else
579#endif
580          nNew(&(pGetCoeff(m1)));
581        return m1;
582      }
583      else
584      {
585        p_LmFree(m1,currRing);
586#ifdef HAVE_RINGS
587        if (is_Ring)
588        {
589          pSetCoeff0(m2, t1);
590          nDelete(&lc1);
591          nDelete(&lc2);
592          nDelete(&t2);
593        }
594        else
595#endif
596          nNew(&(pGetCoeff(m2)));
597        return m2;
598      }
599    }
600#ifdef HAVE_RINGS
601    if (is_Ring)
602    {
603      equal = nEqual(t1,t2);
604    }
605    else
606#endif
607    {
608      t1 = nMult(pGetCoeff(a2),pGetCoeff(p1));
609      t2 = nMult(pGetCoeff(a1),pGetCoeff(p2));
610      equal = nEqual(t1,t2);
611      nDelete(&t2);
612      nDelete(&t1);
613    }
614    if (!equal)
615    {
616      p_LmFree(m2,currRing);
617#ifdef HAVE_RINGS
618      if (is_Ring)
619      {
620          pSetCoeff0(m1, nSub(t1, t2));
621          nDelete(&lc1);
622          nDelete(&lc2);
623          nDelete(&t1);
624          nDelete(&t2);
625      }
626      else
627#endif
628        nNew(&(pGetCoeff(m1)));
629      return m1;
630    }
631    pIter(a1);
632    pIter(a2);
633#ifdef HAVE_RINGS
634    if (is_Ring)
635    {
636      if (a2 != NULL)
637      {
638        nDelete(&t1);
639        t1 = nMult(pGetCoeff(a2),lc1);
640      }
641      if (a1 != NULL)
642      {
643        nDelete(&t2);
644        t2 = nMult(pGetCoeff(a1),lc2);
645      }
646      while ((a1 != NULL) && nIsZero(t2))
647      {
648        pIter(a1);
649        if (a1 != NULL)
650        {
651          nDelete(&t2);
652          t2 = nMult(pGetCoeff(a1),lc2);
653        }
654      }
655      while ((a2 != NULL) && nIsZero(t1))
656      {
657        pIter(a2);
658        if (a2 != NULL)
659        {
660          nDelete(&t1);
661          t1 = nMult(pGetCoeff(a2),lc1);
662        }
663      }
664    }
665#endif
666    if (a2==NULL)
667    {
668      p_LmFree(m2,currRing);
669      if (a1==NULL)
670      {
671#ifdef HAVE_RINGS
672        if (is_Ring)
673        {
674          nDelete(&lc1);
675          nDelete(&lc2);
676          nDelete(&t1);
677          nDelete(&t2);
678        }
679#endif
680        p_LmFree(m1,currRing);
681        return NULL;
682      }
683      goto x1;
684    }
685    if (a1==NULL)
686    {
687      p_LmFree(m1,currRing);
688      goto x2;
689    }
690  }
691}
Note: See TracBrowser for help on using the repository browser.