source: git/libpolys/polys/kbuckets.cc @ 061eacd

fieker-DuValspielwiese
Last change on this file since 061eacd was 69f579, checked in by Hans Schoenemann <hannes@…>, 7 years ago
n_ExactDiv for Q: nlExactDiv (assumes integers as arguments)
  • Property mode set to 100644
File size: 31.9 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4
5#include <omalloc/omalloc.h>
6#include <misc/auxiliary.h>
7
8#include <polys/monomials/p_polys.h>
9//#include <kernel/pShallowCopyDelete.h>
10#include <coeffs/coeffs.h>
11#include <polys/monomials/ring.h>
12//#include <kernel/GBEngine/kutil.h>
13#include <polys/kbuckets.h>
14
15// #include <polys/operations/pShallowCopyDelete.h>
16
17
18#ifdef HAVE_COEF_BUCKETS
19#define USE_COEF_BUCKETS
20#endif
21
22#ifdef USE_COEF_BUCKETS
23#ifdef HAVE_RINGS_OLD
24#define MULTIPLY_BUCKET(B,I) do                                        \
25  { if (B->coef[I]!=NULL)                                              \
26    {                                                                  \
27      assume(p_IsConstant(B->Coef[i],B->bucket->ring));           \
28      B->buckets[I]=p_Mult_q(B->buckets[I],B->coef[I],B->bucket_ring); \
29      B->coef[I]=NULL;                                                 \
30    }                                                                  \
31  } while(0)                                                           \
32    if (rField_is_Ring(B->bucket_ring)) B->buckets_length[i] = pLength(B->buckets[i]);
33#else
34#define MULTIPLY_BUCKET(B,I) do                                        \
35  { if (B->coef[I]!=NULL)                                              \
36    {                                                                  \
37      B->buckets[I]=p_Mult_q(B->buckets[I],B->coef[I],B->bucket_ring); \
38      B->coef[I]=NULL;                                                 \
39    }                                                                  \
40  } while(0)
41#endif
42#else
43#define MULTIPLY_BUCKET(B,I)
44#endif
45static omBin kBucket_bin = omGetSpecBin(sizeof(kBucket));
46#ifdef USE_COEF_BUCKETS
47static int coef_start=1;
48#endif
49//////////////////////////////////////////////////////////////////////////
50///
51/// Some internal stuff
52///
53
54// returns ceil(log_4(l))
55inline unsigned int pLogLength(unsigned int l)
56{
57  unsigned int i = 0;
58
59  if (l == 0) return 0;
60  l--;
61#ifdef BUCKET_TWO_BASE
62  while ((l = (l >> 1))) i++;
63#else
64  while ((l = (l >> 2))) i++;
65#endif
66  return i+1;
67}
68
69// returns ceil(log_4(pLength(p)))
70inline unsigned int pLogLength(poly p)
71{
72  return pLogLength((unsigned int) pLength(p));
73}
74
75#ifdef KDEBUG
76
77#ifndef HAVE_PSEUDO_BUCKETS
78BOOLEAN kbTest_i(kBucket_pt bucket, int i)
79{//sBucketSortMerge
80  #ifdef USE_COEF_BUCKETS
81  assume(bucket->coef[0]==NULL);
82  if ((bucket->coef[i]!=NULL) && (bucket->buckets[i]==NULL))
83  {
84    dReportError("Bucket %d coef not NULL", i);
85  }
86  if (bucket->coef[i]!=NULL)
87  {
88    assume(bucket->buckets[i]!=NULL);
89    p_Test(bucket->coef[i],bucket->bucket_ring);
90  }
91  #endif
92  pFalseReturn(p_Test(bucket->buckets[i], bucket->bucket_ring));
93  if (bucket->buckets_length[i] != pLength(bucket->buckets[i]))
94  {
95    dReportError("Bucket %d lengths difference should:%d has:%d",
96                 i, bucket->buckets_length[i], pLength(bucket->buckets[i]));
97  }
98  else if (i > 0 && (int) pLogLength(bucket->buckets_length[i]) > i)
99  {
100    dReportError("Bucket %d too long %d",
101                 i, bucket->buckets_length[i]);
102  }
103  if (i==0 && bucket->buckets_length[0] > 1)
104  {
105    dReportError("Bucket 0 too long");
106  }
107  return TRUE;
108}
109
110
111BOOLEAN kbTest(kBucket_pt bucket)
112{
113  #ifdef HAVE_COEF_BUCKETS
114  assume(bucket->coef[0]==NULL);
115  #endif
116  int i;
117  poly lm = bucket->buckets[0];
118
119  omCheckAddrBin(bucket, kBucket_bin);
120  assume(bucket->buckets_used <= MAX_BUCKET);
121  if (! kbTest_i(bucket, 0)) return FALSE;
122  for (i=1; i<= (int) bucket->buckets_used; i++)
123  {
124    if (!kbTest_i(bucket, i)) return FALSE;
125    if (lm != NULL &&  bucket->buckets[i] != NULL
126        && p_LmCmp(lm, bucket->buckets[i], bucket->bucket_ring) != 1)
127    {
128      dReportError("Bucket %d larger or equal than lm", i);
129      if (p_LmCmp(lm, bucket->buckets[i], bucket->bucket_ring) ==0)
130        dReportError("Bucket %d equal to lm", i);
131      return FALSE;
132    }
133    if (!p_Test(bucket->buckets[i],bucket->bucket_ring))
134    {
135      dReportError("Bucket %d is not =0(4)", i);
136      return FALSE;
137    }
138  }
139
140  for (; i<=MAX_BUCKET; i++)
141  {
142    if (bucket->buckets[i] != NULL || bucket->buckets_length[i] != 0)
143    {
144      dReportError("Bucket %d not zero", i);
145      return FALSE;
146    }
147  }
148  for(i=0;i<=MAX_BUCKET;i++)
149  {
150    if (bucket->buckets[i]!=NULL)
151    {
152      int j;
153      for(j=i+1;j<=MAX_BUCKET;j++)
154      {
155        if (bucket->buckets[j]==bucket->buckets[i])
156        {
157          dReportError("Bucket %d %d equal", i,j);
158          return FALSE;
159        }
160      }
161    }
162    #ifdef HAVE_COEF_BUCKETS
163    if (bucket->coef[i]!=NULL)
164    {
165      int j;
166      for(j=i+1;j<=MAX_BUCKET;j++)
167      {
168        if (bucket->coef[j]==bucket->coef[i])
169        {
170          dReportError("internal coef %d %d equal", i,j);
171          return FALSE;
172        }
173      }
174    }
175    #endif
176  }
177  return TRUE;
178}
179
180#else // HAVE_PSEUDO_BUCKETS
181BOOLEAN kbTest(kBucket_pt bucket)
182{
183  return TRUE;
184}
185#endif // ! HAVE_PSEUDO_BUCKETS
186#endif // KDEBUG
187
188//////////////////////////////////////////////////////////////////////////
189///
190/// Creation/Destruction of buckets
191///
192
193kBucket_pt kBucketCreate(const ring bucket_ring)
194{
195  assume(bucket_ring != NULL);
196  kBucket_pt bucket = (kBucket_pt) omAlloc0Bin(kBucket_bin);
197  bucket->bucket_ring = bucket_ring;
198  return bucket;
199}
200void kBucketDestroy(kBucket_pt *bucket_pt)
201{
202  omFreeBin(*bucket_pt, kBucket_bin);
203  *bucket_pt = NULL;
204}
205
206
207void kBucketDeleteAndDestroy(kBucket_pt *bucket_pt)
208{
209  kBucket_pt bucket = *bucket_pt;
210  kbTest(bucket);
211  int i;
212  for (i=0; i<= bucket->buckets_used; i++)
213  {
214
215    if (bucket->buckets[i] != NULL)
216    {
217      p_Delete(&(bucket->buckets[i]), bucket->bucket_ring);
218#ifdef USE_COEF_BUCKETS
219      if (bucket->coef[i]!=NULL)
220        p_Delete(&(bucket->coef[i]), bucket->bucket_ring);
221#endif
222    }
223  }
224  omFreeBin(bucket, kBucket_bin);
225  *bucket_pt = NULL;
226}
227
228/////////////////////////////////////////////////////////////////////////////
229// Convertion from/to Bpolys
230//
231#ifndef HAVE_PSEUDO_BUCKETS
232
233inline void kBucketMergeLm(kBucket_pt bucket)
234{
235  kbTest(bucket);
236  if (bucket->buckets[0] != NULL)
237  {
238    poly lm = bucket->buckets[0];
239    int i = 1;
240#ifdef BUCKET_TWO_BASE
241    int l = 2;
242    while ( bucket->buckets_length[i] >= l)
243    {
244      i++;
245      l = l << 1;
246    }
247#else
248    int l = 4;
249    while ( bucket->buckets_length[i] >= l)
250    {
251      i++;
252      l = l << 2;
253    }
254#endif
255#ifndef USE_COEF_BUCKETS
256    MULTIPLY_BUCKET(bucket,i);
257    pNext(lm) = bucket->buckets[i];
258    bucket->buckets[i] = lm;
259    bucket->buckets_length[i]++;
260    assume(i <= bucket->buckets_used+1);
261    if (i > bucket->buckets_used)  bucket->buckets_used = i;
262    bucket->buckets[0] = NULL;
263    bucket->buckets_length[0] = 0;
264    kbTest(bucket);
265#else
266    if (i > bucket->buckets_used)  bucket->buckets_used = i;
267    assume(i!=0);
268    if (bucket->buckets[i]!=NULL)
269    {
270       MULTIPLY_BUCKET(bucket,i);
271       pNext(lm) = bucket->buckets[i];
272       bucket->buckets[i] = lm;
273       bucket->buckets_length[i]++;
274       assume(i <= bucket->buckets_used+1);
275    }
276    else
277    {
278      #if 1
279       assume(bucket->buckets[i]==NULL);
280       assume(bucket->coef[0]==NULL);
281       assume(pLength(lm)==1);
282       assume(pNext(lm)==NULL);
283       number coef=p_GetCoeff(lm,bucket->bucket_ring);
284       //WARNING: not thread_safe
285       p_SetCoeff0(lm, n_Init(1,bucket->bucket_ring), bucket->bucket_ring);
286       bucket->buckets[i]=lm;
287       bucket->buckets_length[i]=1;
288       bucket->coef[i]=p_NSet(n_Copy(coef,bucket->bucket_ring),bucket->bucket_ring);
289
290       bucket->buckets[i]=lm;
291       bucket->buckets_length[i]=1;
292      #else
293       MULTIPLY_BUCKET(bucket,i);
294       pNext(lm) = bucket->buckets[i];
295       bucket->buckets[i] = lm;
296       bucket->buckets_length[i]++;
297       assume(i <= bucket->buckets_used+1);
298      #endif
299    }
300    bucket->buckets[0]=NULL;
301    bucket->buckets_length[0] = 0;
302    bucket->coef[0]=NULL;
303    kbTest(bucket);
304    #endif
305  }
306
307}
308
309BOOLEAN kBucketIsCleared(kBucket_pt bucket)
310{
311  int i;
312
313  for (i = 0;i<=MAX_BUCKET;i++)
314  {
315    if (bucket->buckets[i] != NULL) return FALSE;
316    #ifdef HAVE_COEF_BUCKETS
317    if (bucket->coef[i] != NULL) return FALSE;
318    #endif
319    if (bucket->buckets_length[i] != 0) return FALSE;
320  }
321  return TRUE;
322}
323
324void kBucketInit(kBucket_pt bucket, poly lm, int length)
325{
326  //assume(false);
327  assume(bucket != NULL);
328  assume(length <= 0 || length == pLength(lm));
329  assume(kBucketIsCleared(bucket));
330
331  if (lm == NULL) return;
332
333  if (length <= 0)
334    length = pLength(lm);
335
336  bucket->buckets[0] = lm;
337  #ifdef HAVE_COEF_BUCKETS
338  assume(bucket->coef[0]==NULL);
339  #endif
340  #ifdef USE_COEF_BUCKETS
341  bucket->coef[0]=NULL;
342  #endif
343  if (lm!=NULL)
344    bucket->buckets_length[0] = 1;
345  else
346    bucket->buckets_length[0]= 0;
347  if (length > 1)
348  {
349    unsigned int i = pLogLength(length-1);
350    bucket->buckets[i] = pNext(lm);
351    pNext(lm) = NULL;
352    bucket->buckets_length[i] = length-1;
353    bucket->buckets_used = i;
354  }
355  else
356  {
357    bucket->buckets_used = 0;
358  }
359}
360
361int kBucketCanonicalize(kBucket_pt bucket)
362{
363  assume(bucket->buckets_used<=MAX_BUCKET);
364  MULTIPLY_BUCKET(bucket,1);
365  kbTest(bucket);
366  poly p = bucket->buckets[1];
367  poly lm;
368  int pl = bucket->buckets_length[1];//, i;
369  int i;
370  bucket->buckets[1] = NULL;
371  bucket->buckets_length[1] = 0;
372  #ifdef USE_COEF_BUCKETS
373    assume(bucket->coef[1]==NULL);
374  #endif
375  ring r=bucket->bucket_ring;
376
377
378  for (i=1; i<=bucket->buckets_used; i++)
379  {
380  #ifdef USE_COEF_BUCKETS
381    if (bucket->coef[i]!=NULL)
382    {
383      assume(bucket->buckets[i]!=NULL);
384      p = p_Plus_mm_Mult_qq(p, bucket->coef[i], bucket->buckets[i],
385                 pl, bucket->buckets_length[i], r);
386      p_Delete(&bucket->coef[i],r);
387      p_Delete(&bucket->buckets[i],r);
388    }
389    else
390    p = p_Add_q(p, bucket->buckets[i],
391                 pl, bucket->buckets_length[i], r);
392  #else
393    p = p_Add_q(p, bucket->buckets[i],
394                 pl, bucket->buckets_length[i], r);
395  #endif
396    if (i==1) continue;
397    bucket->buckets[i] = NULL;
398    bucket->buckets_length[i] = 0;
399  }
400  #ifdef HAVE_COEF_BUCKETS
401  assume(bucket->coef[0]==NULL);
402  #endif
403  lm = bucket->buckets[0];
404  if (lm != NULL)
405  {
406    pNext(lm) = p;
407    p = lm;
408    pl++;
409    bucket->buckets[0] = NULL;
410    bucket->buckets_length[0] = 0;
411  }
412  if (pl > 0)
413  {
414    i = pLogLength(pl);
415    bucket->buckets[i] = p;
416    bucket->buckets_length[i] = pl;
417  }
418  else
419  {
420    i = 0;
421  }
422  bucket->buckets_used = i;
423  assume(bucket->buckets_used <= MAX_BUCKET);
424  #ifdef USE_COEF_BUCKETS
425    assume(bucket->coef[0]==NULL);
426    assume(bucket->coef[i]==NULL);
427  #endif
428  assume(pLength(p) == (int) pl);
429  //if (TEST_OPT_PROT) { Print("C(%d)",pl); }
430  kbTest(bucket);
431  return i;
432}
433
434void kBucketClear(kBucket_pt bucket, poly *p, int *length)
435{
436  int i = kBucketCanonicalize(bucket);
437  if (i > 0)
438  {
439  #ifdef USE_COEF_BUCKETS
440    MULTIPLY_BUCKET(bucket,i);
441    //bucket->coef[i]=NULL;
442  #endif
443    *p = bucket->buckets[i];
444    *length = bucket->buckets_length[i];
445    bucket->buckets[i] = NULL;
446    bucket->buckets_length[i] = 0;
447    bucket->buckets_used = 0;
448
449  }
450  else
451  {
452    *p = NULL;
453    *length = 0;
454  }
455}
456
457void kBucketSetLm(kBucket_pt bucket, poly lm)
458{
459  kBucketMergeLm(bucket);
460  pNext(lm) = NULL;
461  bucket->buckets[0] = lm;
462  bucket->buckets_length[0] = 1;
463}
464
465#else // HAVE_PSEUDO_BUCKETS
466
467void kBucketInit(kBucket_pt bucket, poly lm, int length)
468{
469  int i;
470
471  assume(bucket != NULL);
472  assume(length <= 0 || length == pLength(lm));
473
474  bucket->p = lm;
475  if (length <= 0) bucket->l = pLength(lm);
476  else bucket->l = length;
477
478}
479
480const poly kBucketGetLm(kBucket_pt bucket)
481{
482  return bucket->p;
483}
484
485poly kBucketExtractLm(kBucket_pt bucket)
486{
487  poly lm = bucket->p;
488  assume(pLength(bucket->p) == bucket->l);
489  pIter(bucket->p);
490  (bucket->l)--;
491  pNext(lm) = NULL;
492  return lm;
493}
494
495void kBucketClear(kBucket_pt bucket, poly *p, int *length)
496{
497  assume(pLength(bucket->p) == bucket->l);
498  *p = bucket->p;
499  *length = bucket->l;
500  bucket->p = NULL;
501  bucket->l = 0;
502}
503
504#endif // ! HAVE_PSEUDO_BUCKETS
505//////////////////////////////////////////////////////////////////////////
506///
507/// For changing the ring of the Bpoly to new_tailBin
508///
509void kBucketShallowCopyDelete(kBucket_pt bucket,
510                              ring new_tailRing, omBin new_tailBin,
511                              pShallowCopyDeleteProc p_shallow_copy_delete)
512{
513#ifndef HAVE_PSEUDO_BUCKETS
514  int i;
515
516  kBucketCanonicalize(bucket);
517  for (i=0; i<= bucket->buckets_used; i++)
518    if (bucket->buckets[i] != NULL)
519    {
520      MULTIPLY_BUCKET(bucket,i);
521      bucket->buckets[i] = p_shallow_copy_delete(bucket->buckets[i],
522                                                 bucket->bucket_ring,
523                                                 new_tailRing,
524                                                 new_tailBin);
525    }
526#else
527  bucket->p = p_shallow_copy_delete(p,
528                                    bucket_ring,
529                                    new_tailRing,
530                                    new_tailBin);
531#endif
532  bucket->bucket_ring = new_tailRing;
533}
534
535//////////////////////////////////////////////////////////////////////////
536///
537/// Bucket number i from bucket is out of length sync, resync
538///
539void kBucketAdjust(kBucket_pt bucket, int i) {
540
541  MULTIPLY_BUCKET(bucket,i);
542
543  int l1 = bucket->buckets_length[i];
544  poly p1 = bucket->buckets[i];
545  bucket->buckets[i] = NULL;
546  bucket->buckets_length[i] = 0;
547  i = pLogLength(l1);
548
549  while (bucket->buckets[i] != NULL)
550  {
551    //kbTest(bucket);
552    MULTIPLY_BUCKET(bucket,i);
553    p1 = p_Add_q(p1, bucket->buckets[i],
554                 l1, bucket->buckets_length[i], bucket->bucket_ring);
555    bucket->buckets[i] = NULL;
556    bucket->buckets_length[i] = 0;
557    i = pLogLength(l1);
558  }
559
560  bucket->buckets[i] = p1;
561  bucket->buckets_length[i]=l1;
562  if (i >= bucket->buckets_used)
563    bucket->buckets_used = i;
564  else
565    kBucketAdjustBucketsUsed(bucket);
566}
567
568//////////////////////////////////////////////////////////////////////////
569///
570/// Multiply Bucket by number ,i.e. Bpoly == n*Bpoly
571///
572void kBucket_Mult_n(kBucket_pt bucket, number n)
573{
574#ifndef HAVE_PSEUDO_BUCKETS
575  kbTest(bucket);
576  ring r=bucket->bucket_ring;
577  int i;
578
579  for (i=0; i<= bucket->buckets_used; i++)
580  {
581    if (bucket->buckets[i] != NULL)
582    {
583#ifdef USE_COEF_BUCKETS
584      if (i<coef_start)
585        bucket->buckets[i] = p_Mult_nn(bucket->buckets[i], n, r);
586        /* Frank Seelisch on March 11, 2010:
587           This looks a bit strange: The following "if" is indented
588           like the previous line of code. But coded as it is,
589           it should actually be two spaces less indented.
590           Question: Should the following "if" also only be
591           performed when "(i<coef_start)" is true?
592           For the time being, I leave it as it is. */
593        if (rField_is_Ring(r) && !(rField_is_Domain(r)))
594        {
595          bucket->buckets_length[i] = pLength(bucket->buckets[i]);
596          kBucketAdjust(bucket, i);
597        }
598      else
599      if (bucket->coef[i]!=NULL)
600      {
601        bucket->coef[i] = p_Mult_nn(bucket->coef[i],n,r);
602      }
603      else
604      {
605        bucket->coef[i] = p_NSet(n_Copy(n,r),r);
606      }
607#else
608      bucket->buckets[i] = p_Mult_nn(bucket->buckets[i], n, r);
609      if (rField_is_Ring(r) && !(rField_is_Domain(r)))
610      {
611        bucket->buckets_length[i] = pLength(bucket->buckets[i]);
612        kBucketAdjust(bucket, i);
613      }
614#endif
615    }
616  }
617  kbTest(bucket);
618#else
619  bucket->p = p_Mult_nn(bucket->p, n, bucket->bucket_ring);
620#endif
621}
622
623
624//////////////////////////////////////////////////////////////////////////
625///
626/// Add to Bucket a poly ,i.e. Bpoly == q+Bpoly
627///
628void kBucket_Add_q(kBucket_pt bucket, poly q, int *l)
629{
630  if (q == NULL) return;
631  assume(*l <= 0 || pLength(q) == *l);
632
633  int i, l1;
634  ring r = bucket->bucket_ring;
635
636  if (*l <= 0)
637  {
638    l1 = pLength(q);
639    *l = l1;
640  }
641  else
642    l1 = *l;
643
644  kBucketMergeLm(bucket);
645  kbTest(bucket);
646  i = pLogLength(l1);
647
648  while (bucket->buckets[i] != NULL)
649  {
650    //MULTIPLY_BUCKET(bucket,i);
651  #ifdef USE_COEF_BUCKETS
652    if (bucket->coef[i]!=NULL)
653    {
654      q = p_Plus_mm_Mult_qq(q, bucket->coef[i], bucket->buckets[i],
655                 l1, bucket->buckets_length[i], r);
656      p_Delete(&bucket->coef[i],r);
657      p_Delete(&bucket->buckets[i],r);
658    }
659    else
660    q = p_Add_q(q, bucket->buckets[i],
661                 l1, bucket->buckets_length[i], r);
662  #else
663    q = p_Add_q(q, bucket->buckets[i],
664                 l1, bucket->buckets_length[i], r);
665  #endif
666    bucket->buckets[i] = NULL;
667    bucket->buckets_length[i] = 0;
668    i = pLogLength(l1);
669    assume(i<= MAX_BUCKET);
670    assume(bucket->buckets_used<= MAX_BUCKET);
671  }
672
673  kbTest(bucket);
674  bucket->buckets[i] = q;
675  bucket->buckets_length[i]=l1;
676  if (i >= bucket->buckets_used)
677    bucket->buckets_used = i;
678  else
679    kBucketAdjustBucketsUsed(bucket);
680  kbTest(bucket);
681}
682
683
684
685//////////////////////////////////////////////////////////////////////////
686///
687/// Bpoly == Bpoly - m*p; where m is a monom
688/// Does not destroy p and m
689/// assume (*l <= 0 || pLength(p) == *l)
690void kBucket_Minus_m_Mult_p(kBucket_pt bucket, poly m, poly p, int *l,
691                            poly spNoether)
692{
693  assume(*l <= 0 || pLength(p) == *l);
694  int i, l1;
695  poly p1 = p;
696  ring r = bucket->bucket_ring;
697
698  if (*l <= 0)
699  {
700    l1 = pLength(p1);
701    *l = l1;
702  }
703  else
704    l1 = *l;
705
706  if (m == NULL || p == NULL) return;
707
708#ifndef HAVE_PSEUDO_BUCKETS
709  kBucketMergeLm(bucket);
710  kbTest(bucket);
711  i = pLogLength(l1);
712
713#if defined(HAVE_PLURAL)
714  if ((rField_is_Ring(r) && !(rField_is_Domain(r)))
715  ||(rIsPluralRing(r)))
716  {
717    pSetCoeff0(m, n_InpNeg(pGetCoeff(m),r->cf));
718    p1=pp_Mult_mm(p,m,r);
719    pSetCoeff0(m, n_InpNeg(pGetCoeff(m),r->cf));
720    l1=pLength(p1);
721    i = pLogLength(l1);
722  }
723  else
724#endif
725  {
726    if ((i <= bucket->buckets_used) && (bucket->buckets[i] != NULL))
727    {
728      assume(pLength(bucket->buckets[i])==bucket->buckets_length[i]);
729//#ifdef USE_COEF_BUCKETS
730//     if(bucket->coef[i]!=NULL)
731//     {
732//       poly mult=p_Mult_mm(bucket->coef[i],m,r);
733//       bucket->coef[i]=NULL;
734//       p1 = p_Minus_mm_Mult_qq(bucket->buckets[i], mult, p1,
735//                               bucket->buckets_length[i], l1,
736//                             spNoether, r);
737//     }
738//     else
739//#endif
740      MULTIPLY_BUCKET(bucket,i);
741      p1 = p_Minus_mm_Mult_qq(bucket->buckets[i], m, p1,
742                            bucket->buckets_length[i], l1,
743                            spNoether, r);
744      l1 = bucket->buckets_length[i];
745      bucket->buckets[i] = NULL;
746      bucket->buckets_length[i] = 0;
747      i = pLogLength(l1);
748    }
749    else
750    {
751      pSetCoeff0(m, n_InpNeg(pGetCoeff(m),r->cf));
752      if (spNoether != NULL)
753      {
754        l1 = -1;
755        p1 = r->p_Procs->pp_Mult_mm_Noether(p1, m, spNoether, l1, r);
756        i = pLogLength(l1);
757      }
758      else
759      {
760        p1 = r->p_Procs->pp_Mult_mm(p1, m, r);
761      }
762      pSetCoeff0(m, n_InpNeg(pGetCoeff(m),r->cf));
763    }
764  }
765
766  while (bucket->buckets[i] != NULL)
767  {
768    //kbTest(bucket);
769    MULTIPLY_BUCKET(bucket,i);
770    p1 = p_Add_q(p1, bucket->buckets[i],
771                 l1, bucket->buckets_length[i], r);
772    bucket->buckets[i] = NULL;
773    bucket->buckets_length[i] = 0;
774    i = pLogLength(l1);
775  }
776
777  bucket->buckets[i] = p1;
778  bucket->buckets_length[i]=l1;
779  if (i >= bucket->buckets_used)
780    bucket->buckets_used = i;
781  else
782    kBucketAdjustBucketsUsed(bucket);
783#else // HAVE_PSEUDO_BUCKETS
784  bucket->p = p_Minus_mm_Mult_qq(bucket->p, m,  p,
785                               bucket->l, l1,
786                               spNoether, r);
787#endif
788}
789
790//////////////////////////////////////////////////////////////////////////
791///
792/// Bpoly == Bpoly + m*p; where m is a monom
793/// Does not destroy p and m
794/// assume (l <= 0 || pLength(p) == l)
795void kBucket_Plus_mm_Mult_pp(kBucket_pt bucket, poly m, poly p, int l)
796{
797    assume((!rIsPluralRing(bucket->bucket_ring))||p_IsConstant(m, bucket->bucket_ring));
798  assume(l <= 0 || pLength(p) == l);
799  int i, l1;
800  poly p1 = p;
801  ring r = bucket->bucket_ring;
802
803  if (m == NULL || p == NULL) return;
804
805  if (l <= 0)
806  {
807    l1 = pLength(p1);
808    l = l1;
809  }
810  else
811    l1 = l;
812
813  kBucketMergeLm(bucket);
814  kbTest(bucket);
815  i = pLogLength(l1);
816  #ifdef USE_COEF_BUCKETS
817  number n=n_Init(1,r->cf);
818  #endif
819  if (i <= bucket->buckets_used && bucket->buckets[i] != NULL)
820  {
821    //if (FALSE){
822    #ifdef USE_COEF_BUCKETS
823    if ((bucket->coef[i]!=NULL) &&(i>=coef_start))
824    {
825      number orig_coef=p_GetCoeff(bucket->coef[i],r);
826      //we take ownership:
827      p_SetCoeff0(bucket->coef[i],n_Init(0,r),r);
828      number add_coef=n_Copy(p_GetCoeff(m,r),r);
829      number gcd=n_Gcd(add_coef, orig_coef,r);
830
831      if (!(n_IsOne(gcd,r)))
832      {
833        number orig_coef2=n_ExactDiv(orig_coef,gcd,r);
834        number add_coef2=n_ExactDiv(add_coef, gcd,r);
835        n_Delete(&orig_coef,r);
836        n_Delete(&add_coef,r);
837        orig_coef=orig_coef2;
838        add_coef=add_coef2;
839
840        //p_Mult_nn(bucket->buckets[i], orig_coef,r);
841        n_Delete(&n,r);
842        n=gcd;
843      }
844
845      //assume(n_IsOne(n,r));
846      number backup=p_GetCoeff(m,r);
847
848      p_SetCoeff0(m,add_coef,r);
849      bucket->buckets[i]=p_Mult_nn(bucket->buckets[i],orig_coef,r);
850
851      n_Delete(&orig_coef,r);
852      p_Delete(&bucket->coef[i],r);
853
854      p1 = p_Plus_mm_Mult_qq(bucket->buckets[i], m, p1,
855                           bucket->buckets_length[i], l1, r);
856      l1=bucket->buckets_length[i];
857      bucket->buckets[i]=NULL;
858      bucket->buckets_length[i] = 0;
859      i = pLogLength(l1);
860      assume(l1==pLength(p1));
861
862      p_SetCoeff(m,backup,r); //deletes add_coef
863    }
864    else
865    #endif
866    {
867      MULTIPLY_BUCKET(bucket,i);
868      p1 = p_Plus_mm_Mult_qq(bucket->buckets[i], m, p1,
869                           bucket->buckets_length[i], l1, r);
870      l1 = bucket->buckets_length[i];
871      bucket->buckets[i] = NULL;
872      bucket->buckets_length[i] = 0;
873      i = pLogLength(l1);
874    }
875  }
876  else
877  {
878    #ifdef USE_COEF_BUCKETS
879    number swap_n=p_GetCoeff(m,r);
880
881    assume(n_IsOne(n,r));
882    p_SetCoeff0(m,n,r);
883    n=swap_n;
884    //p_SetCoeff0(n, swap_n, r);
885    //p_GetCoeff0(n, swap_n,r);
886    #endif
887    p1 = r->p_Procs->pp_Mult_mm(p1, m, r);
888    #ifdef USE_COEF_BUCKETS
889    //m may not be changed
890    p_SetCoeff(m,n_Copy(n,r),r);
891    #endif
892  }
893
894  while ((bucket->buckets[i] != NULL) && (p1!=NULL))
895  {
896    assume(i!=0);
897    #ifdef USE_COEF_BUCKETS
898    if ((bucket->coef[i]!=NULL) &&(i>=coef_start))
899    {
900      number orig_coef=p_GetCoeff(bucket->coef[i],r);
901      //we take ownership:
902      p_SetCoeff0(bucket->coef[i],n_Init(0,r),r);
903      number add_coef=n_Copy(n,r);
904      number gcd=n_Gcd(add_coef, orig_coef,r);
905
906      if (!(n_IsOne(gcd,r)))
907      {
908        number orig_coef2=n_ExactDiv(orig_coef,gcd,r);
909        number add_coef2=n_ExactDiv(add_coef, gcd,r);
910        n_Delete(&orig_coef,r);
911        n_Delete(&n,r);
912        n_Delete(&add_coef,r);
913        orig_coef=orig_coef2;
914        add_coef=add_coef2;
915        //p_Mult_nn(bucket->buckets[i], orig_coef,r);
916        n=gcd;
917      }
918      //assume(n_IsOne(n,r));
919      bucket->buckets[i]=p_Mult_nn(bucket->buckets[i],orig_coef,r);
920      p1=p_Mult_nn(p1,add_coef,r);
921
922      p1 = p_Add_q(p1, bucket->buckets[i],r);
923      l1=pLength(p1);
924
925      bucket->buckets[i]=NULL;
926      n_Delete(&orig_coef,r);
927      p_Delete(&bucket->coef[i],r);
928      //l1=bucket->buckets_length[i];
929      assume(l1==pLength(p1));
930    }
931    else
932    #endif
933    {
934      //don't do that, pull out gcd
935      #ifdef USE_COEF_BUCKETS
936      if(!(n_IsOne(n,r)))
937      {
938        p1=p_Mult_nn(p1, n, r);
939        n_Delete(&n,r);
940        n=n_Init(1,r);
941      }
942      #endif
943      MULTIPLY_BUCKET(bucket,i);
944      p1 = p_Add_q(p1, bucket->buckets[i],
945                 l1, bucket->buckets_length[i], r);
946      bucket->buckets[i] = NULL;
947      bucket->buckets_length[i] = 0;
948    }
949    i = pLogLength(l1);
950  }
951
952  bucket->buckets[i] = p1;
953#ifdef USE_COEF_BUCKETS
954  assume(bucket->coef[i]==NULL);
955
956  if (!(n_IsOne(n,r)))
957  {
958    bucket->coef[i]=p_NSet(n,r);
959  }
960  else
961  {
962    bucket->coef[i]=NULL;
963    n_Delete(&n,r);
964  }
965
966  if ((p1==NULL) && (bucket->coef[i]!=NULL))
967    p_Delete(&bucket->coef[i],r);
968#endif
969  bucket->buckets_length[i]=l1;
970  if (i > bucket->buckets_used)
971    bucket->buckets_used = i;
972  else
973    kBucketAdjustBucketsUsed(bucket);
974
975  kbTest(bucket);
976}
977
978poly kBucket_ExtractLarger(kBucket_pt bucket, poly q, poly append)
979{
980  if (q == NULL) return append;
981  poly lm;
982  loop
983  {
984    lm = kBucketGetLm(bucket);
985    if (lm == NULL) return append;
986    if (p_LmCmp(lm, q, bucket->bucket_ring) == 1)
987    {
988      lm = kBucketExtractLm(bucket);
989      pNext(append) = lm;
990      pIter(append);
991    }
992    else
993    {
994      return append;
995    }
996  }
997}
998
999/////////////////////////////////////////////////////////////////////////////
1000//
1001// Extract all monomials from bucket with component comp
1002// Return as a polynomial *p with length *l
1003// In other words, afterwards
1004// Bpoly = Bpoly - (poly consisting of all monomials with component comp)
1005// and components of monomials of *p are all 0
1006//
1007
1008// Hmm... for now I'm too lazy to implement those independent of currRing
1009// But better declare it extern than including polys.h
1010extern void p_TakeOutComp(poly *p, long comp, poly *q, int *lq, const ring r);
1011
1012void kBucketTakeOutComp(kBucket_pt bucket,
1013                        long comp,
1014                        poly *r_p, int *l)
1015{
1016  poly p = NULL, q;
1017  int i, lp = 0, lq;
1018
1019#ifndef HAVE_PSEUDO_BUCKETS
1020  kBucketMergeLm(bucket);
1021  for (i=1; i<=bucket->buckets_used; i++)
1022  {
1023    if (bucket->buckets[i] != NULL)
1024    {
1025      MULTIPLY_BUCKET(bucket,i);
1026      p_TakeOutComp(&(bucket->buckets[i]), comp, &q, &lq, bucket->bucket_ring);
1027      if (q != NULL)
1028      {
1029        assume(pLength(q) == lq);
1030        bucket->buckets_length[i] -= lq;
1031        assume(pLength(bucket->buckets[i]) == bucket->buckets_length[i]);
1032        p = p_Add_q(p, q, lp, lq, bucket->bucket_ring);
1033      }
1034    }
1035  }
1036  kBucketAdjustBucketsUsed(bucket);
1037#else
1038  p_TakeOutComp(&(bucket->p), comp, &p, &lp,bucket->bucket_ring);
1039  (bucket->l) -= lp;
1040#endif
1041  *r_p = p;
1042  *l = lp;
1043
1044  kbTest(bucket);
1045}
1046
1047/////////////////////////////////////////////////////////////////////////////
1048// Reduction of Bpoly with a given poly
1049//
1050
1051extern int ksCheckCoeff(number *a, number *b);
1052
1053number kBucketPolyRed(kBucket_pt bucket,
1054                      poly p1, int l1,
1055                      poly spNoether)
1056{
1057  ring r=bucket->bucket_ring;
1058  assume((!rIsPluralRing(r))||p_LmEqual(p1,kBucketGetLm(bucket), r));
1059  assume(p1 != NULL &&
1060         p_DivisibleBy(p1,  kBucketGetLm(bucket), r));
1061  assume(pLength(p1) == (int) l1);
1062
1063  poly a1 = pNext(p1), lm = kBucketExtractLm(bucket);
1064  BOOLEAN reset_vec=FALSE;
1065  number rn;
1066
1067  /* we shall reduce bucket=bn*lm+... by p1=an*t+a1 where t=lm(p1)
1068     and an,bn shall be defined further down only if lc(p1)!=1
1069     we already know: an|bn and t|lm */
1070  if(a1==NULL)
1071  {
1072    p_LmDelete(&lm, r);
1073    return n_Init(1,r->cf);
1074  }
1075
1076  if (! n_IsOne(pGetCoeff(p1),r->cf))
1077  {
1078    number an = pGetCoeff(p1), bn = pGetCoeff(lm);
1079//StringSetS("##### an = "); nWrite(an); PrintS(StringEndS("\n")); // NOTE/TODO: use StringAppendS("\n"); omFree(s);
1080//StringSetS("##### bn = "); nWrite(bn); PrintS(StringEndS("\n")); // NOTE/TODO: use StringAppendS("\n"); omFree(s);
1081    /* ksCheckCoeff: divide out gcd from an and bn: */
1082    int ct = ksCheckCoeff(&an, &bn,r->cf);
1083    /* the previous command returns ct=0 or ct=2 iff an!=1
1084       note: an is now 1 or -1 */
1085
1086    /* setup factor for p1 which cancels leading terms */
1087    p_SetCoeff(lm, bn, r);
1088    if ((ct == 0) || (ct == 2))
1089    {
1090      /* next line used to be here before but is WRONG:
1091      kBucket_Mult_n(bucket, an);
1092        its use would result in a wrong sign for the tail of bucket
1093        in the reduction */
1094
1095      /* correct factor for cancelation by changing sign if an=-1 */
1096      if (rField_is_Ring(r))
1097        lm = p_Mult_nn(lm, an, r);
1098      else
1099        kBucket_Mult_n(bucket, an);
1100    }
1101    rn = an;
1102  }
1103  else
1104  {
1105    rn = n_Init(1,r->cf);
1106  }
1107
1108  if (p_GetComp(p1, r) != p_GetComp(lm, r))
1109  {
1110    p_SetCompP(a1, p_GetComp(lm, r), r);
1111    reset_vec = TRUE;
1112    p_SetComp(lm, p_GetComp(p1, r), r);
1113    p_Setm(lm, r);
1114  }
1115
1116  p_ExpVectorSub(lm, p1, r);
1117  l1--;
1118
1119  assume(l1==pLength(a1));
1120#if 0
1121  BOOLEAN backuped=FALSE;
1122  number coef;
1123  //@Viktor, don't ignore coefficients on monomials
1124  if(l1==1) {
1125
1126    //if (rField_is_Q(r)) {
1127      //avoid this for function fields, as gcds are expensive at the moment
1128
1129
1130      coef=p_GetCoeff(a1,r);
1131      lm=p_Mult_nn(lm, coef, r);
1132      p_SetCoeff0(a1, n_Init(1,r), r);
1133      backuped=TRUE;
1134      //WARNING: not thread_safe
1135    //deletes coef as side effect
1136    //}
1137  }
1138#endif
1139
1140  kBucket_Minus_m_Mult_p(bucket, lm, a1, &l1, spNoether);
1141
1142#if 0
1143  if (backuped)
1144    p_SetCoeff0(a1,coef,r);
1145#endif
1146
1147  p_LmDelete(&lm, r);
1148  if (reset_vec) p_SetCompP(a1, 0, r);
1149  kbTest(bucket);
1150  return rn;
1151}
1152
1153#ifndef USE_COEF_BUCKETS
1154void kBucketSimpleContent(kBucket_pt) {}
1155#else
1156static BOOLEAN nIsPseudoUnit(number n, ring r)
1157{
1158  if (rField_is_Zp(r))
1159    return TRUE;
1160
1161  if (rParameter(r)==NULL)
1162  {
1163    return (n_Size(n,r->cf)==1);
1164  }
1165  //if (r->parameter!=NULL)
1166  return (n_IsOne(n,r->cf) || n_IsMOne(n,r->cf));
1167}
1168
1169void kBucketSimpleContent(kBucket_pt bucket)
1170{
1171  ring r=bucket->bucket_ring;
1172  int i;
1173  //PrintS("HHHHHHHHHHHHH");
1174  for (i=0;i<=MAX_BUCKET;i++)
1175  {
1176    //if ((bucket->buckets[i]!=NULL) && (bucket->coef[i]!=NULL))
1177    //    PrintS("H2H2H2");
1178    if (i==0)
1179    {
1180      assume(bucket->buckets[i]==NULL);
1181    }
1182    if ((bucket->buckets[i]!=NULL) && (bucket->coef[i]==NULL))
1183      return;
1184  }
1185  for (i=0;i<=MAX_BUCKET;i++)
1186  {
1187    //if ((bucket->buckets[i]!=NULL) && (bucket->coef[i]!=NULL))
1188    //    PrintS("H2H2H2");
1189    if (i==0)
1190    {
1191      assume(bucket->buckets[i]==NULL);
1192    }
1193    if ((bucket->buckets[i]!=NULL)
1194    && (nIsPseudoUnit(p_GetCoeff(bucket->coef[i],r),r)))
1195      return;
1196  }
1197  //return;
1198
1199  number coef=n_Init(0,r);
1200  //ATTENTION: will not work correct for GB over ring
1201  //if (TEST_OPT_PROT)
1202  //    PrintS("CCCCCCCCCCCCC");
1203  for (i=MAX_BUCKET;i>=0;i--)
1204  {
1205    if (i==0)
1206    {
1207      assume(bucket->buckets[i]==NULL);
1208    }
1209    if (bucket->buckets[i]!=NULL)
1210    {
1211      assume(bucket->coef[i]!=NULL);
1212      assume(!(n_IsZero(pGetCoeff(bucket->coef[i]),r)));
1213
1214      //in this way it should crash on programming errors, yeah
1215      number temp=n_Gcd(coef, pGetCoeff(bucket->coef[i]),r);
1216      n_Delete(&coef,r );
1217      coef=temp;
1218      if (nIsPseudoUnit(coef,r))
1219      {
1220        n_Delete(&coef,r);
1221        return;
1222      }
1223      assume(!(n_IsZero(coef,r)));
1224    }
1225  }
1226  if (n_IsZero(coef,r))
1227  {
1228    n_Delete(&coef,r);
1229    return;
1230  }
1231  if (TEST_OPT_PROT)
1232    PrintS("S");
1233  for(i=0;i<=MAX_BUCKET;i++)
1234  {
1235    if (bucket->buckets[i]!=NULL)
1236    {
1237      assume(!(n_IsZero(coef,r)));
1238      assume(bucket->coef[i]!=NULL);
1239      number lc=p_GetCoeff(bucket->coef[i],r);
1240      p_SetCoeff(bucket->coef[i], n_ExactDiv(lc,coef,r),r);
1241      assume(!(n_IsZero(p_GetCoeff(bucket->coef[i],r),r)));
1242    }
1243  }
1244  n_Delete(&coef,r);
1245}
1246#endif
1247
1248
1249poly kBucketExtractLmOfBucket(kBucket_pt bucket, int i)
1250{
1251  assume(bucket->buckets[i]!=NULL);
1252
1253  poly p=bucket->buckets[i];
1254  bucket->buckets_length[i]--;
1255#ifdef USE_COEF_BUCKETS
1256  ring r=bucket->bucket_ring;
1257  if (bucket->coef[i]!=NULL)
1258  {
1259    poly next=pNext(p);
1260    if (next==NULL)
1261    {
1262      MULTIPLY_BUCKET(bucket,i);
1263      p=bucket->buckets[i];
1264      bucket->buckets[i]=NULL;
1265      return p;
1266    }
1267    else
1268    {
1269      bucket->buckets[i]=next;
1270      number c=p_GetCoeff(bucket->coef[i],r);
1271      pNext(p)=NULL;
1272      p=p_Mult_nn(p,c,r);
1273      assume(p!=NULL);
1274      return p;
1275    }
1276  }
1277  else
1278#endif
1279  {
1280    bucket->buckets[i]=pNext(bucket->buckets[i]);
1281    pNext(p)=NULL;
1282    assume(p!=NULL);
1283    return p;
1284  }
1285}
1286
1287/*
1288* input - output: a, b
1289* returns:
1290*   a := a/gcd(a,b), b := b/gcd(a,b)
1291*   and return value
1292*       0  ->  a != 1,  b != 1
1293*       1  ->  a == 1,  b != 1
1294*       2  ->  a != 1,  b == 1
1295*       3  ->  a == 1,  b == 1
1296*   this value is used to control the spolys
1297*/
1298int ksCheckCoeff(number *a, number *b, const coeffs r)
1299{
1300  int c = 0;
1301  number an = *a, bn = *b;
1302  n_Test(an,r);
1303  n_Test(bn,r);
1304
1305  number cn = n_SubringGcd(an, bn, r);
1306
1307  if(n_IsOne(cn, r))
1308  {
1309    an = n_Copy(an, r);
1310    bn = n_Copy(bn, r);
1311  }
1312  else
1313  {
1314    an = n_ExactDiv(an, cn, r); n_Normalize(an,r);
1315    bn = n_ExactDiv(bn, cn, r); n_Normalize(bn,r);
1316  }
1317  n_Delete(&cn, r);
1318  if (n_IsOne(an, r))
1319  {
1320    c = 1;
1321  }
1322  if (n_IsOne(bn, r))
1323  {
1324    c += 2;
1325  }
1326  *a = an;
1327  *b = bn;
1328  return c;
1329}
1330
Note: See TracBrowser for help on using the repository browser.