source: git/kernel/kspoly.cc @ a82c308

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