source: git/libpolys/polys/sbuckets.cc @ 0b7fb8

spielwiese
Last change on this file since 0b7fb8 was 0b7fb8, checked in by Oleksandr Motsak <motsak@…>, 10 years ago
Added sIsEmpty + fixed *Copy
  • Property mode set to 100644
File size: 8.1 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    sbuckets.cc
6 *  Purpose: implementation of routines for sorting polys using
7 *           a bucket sort
8 *  Author:  obachman (Olaf Bachmann)
9 *  Created: 9/00
10 *******************************************************************/
11//#include <kernel/mod2.h>
12
13#include <omalloc/omalloc.h>
14
15
16
17
18#include <misc/auxiliary.h>
19
20#include <polys/sbuckets.h>
21
22#include <polys/monomials/ring.h>
23//#include <kernel/p_Procs.h>
24#include <polys/monomials/p_polys.h>
25
26
27
28//////////////////////////////////////////////////////////////////////////
29// Declarations
30//
31
32class sBucketPoly
33{
34public:
35  poly p;
36  long length;
37};
38
39class sBucket
40{
41public:
42  ring          bucket_ring;
43  long          max_bucket;
44  sBucketPoly   buckets[BIT_SIZEOF_LONG - 3];
45}
46;
47
48static omBin sBucket_bin = omGetSpecBin(sizeof(sBucket));
49
50
51//////////////////////////////////////////////////////////////////////////
52// New API:
53//
54
55/// Returns bucket ring
56ring sBucketGetRing(const sBucket_pt bucket)
57{ return bucket->bucket_ring; }
58
59
60bool sIsEmpty(const sBucket_pt bucket)
61{
62  for(int i = 0; i < (BIT_SIZEOF_LONG - 3); i++)
63  {   
64    assume( i < (BIT_SIZEOF_LONG - 3) );
65    assume( pLength(bucket->buckets[i].p) == bucket->buckets[i].length );
66
67    if( bucket->buckets[i].p != NULL )
68      return false;
69
70    if( bucket->buckets[i].length != 0 )
71      return false;
72  }
73
74  return( bucket->max_bucket == 0 );
75
76}
77
78
79/// Copy sBucket non-intrusive!!!
80sBucket_pt    sBucketCopy(const sBucket_pt bucket)
81{
82  const ring r = bucket->bucket_ring;
83
84  sBucket_pt newbucket = sBucketCreate(r);
85
86  newbucket->max_bucket = bucket->max_bucket;
87
88  for(int i = 0; i <= bucket->max_bucket; i++)
89  {   
90    assume( i < (BIT_SIZEOF_LONG - 3) );
91    assume( pLength(bucket->buckets[i].p) == bucket->buckets[i].length );
92
93    newbucket->buckets[i].p = p_Copy(bucket->buckets[i].p, r);
94    newbucket->buckets[i].length = bucket->buckets[i].length;
95
96    assume( pLength(newbucket->buckets[i].p) == newbucket->buckets[i].length );
97  }
98
99  return newbucket;
100}
101
102/////////////////////////////////////////////////////////////////////////////
103// internal routines
104//
105// returns floor(log_2(i))
106static inline int LOG2(int i)
107{
108  assume (i > 0);
109  int j = 0;
110
111  do
112  {
113    i = i >> 1;
114    if (i == 0) return j;
115    j++;
116  }
117  while (1);
118
119  return j;
120}
121
122//////////////////////////////////////////////////////////////////////////
123// Creation/Destruction of buckets
124//
125sBucket_pt    sBucketCreate(ring r)
126{
127  sBucket_pt bucket = (sBucket_pt) omAlloc0Bin(sBucket_bin);
128  bucket->bucket_ring = r;
129  return bucket;
130}
131
132void          sBucketDestroy(sBucket_pt *bucket)
133{
134  assume(bucket != NULL);
135  omFreeBin(*bucket, sBucket_bin);
136  *bucket = NULL;
137}
138
139void sBucketDeleteAndDestroy(sBucket_pt *bucket_pt)
140{
141  sBucket_pt bucket = *bucket_pt;
142  int i;
143  for (i=0; i<= bucket->max_bucket; i++)
144  {
145
146    if (bucket->buckets[i].p != NULL)
147    {
148      p_Delete(&(bucket->buckets[i].p), bucket->bucket_ring);
149    }
150  }
151  omFreeBin(bucket, sBucket_bin);
152  *bucket_pt = NULL;
153}
154
155
156/////////////////////////////////////////////////////////////////////////////
157// Convertion from/to SBpolys
158//
159
160static void sBucket_Merge_m(sBucket_pt bucket, poly p)
161{
162  assume(p != NULL && pNext(p) == NULL);
163  int length = 1;
164  int i = 0;
165
166  while (bucket->buckets[i].p != NULL)
167  {
168    p = p_Merge_q(p, bucket->buckets[i].p, bucket->bucket_ring);
169    length += bucket->buckets[i].length;
170    bucket->buckets[i].p = NULL;
171    bucket->buckets[i].length = 0;
172    i++;
173    assume(LOG2(length) == i);
174  }
175
176  bucket->buckets[i].p = p;
177  bucket->buckets[i].length = length;
178  if (i > bucket->max_bucket) bucket->max_bucket = i;
179}
180
181void sBucket_Merge_p(sBucket_pt bucket, poly p, int length)
182{
183  assume(bucket != NULL);
184  assume(length <= 0 || length == pLength(p));
185
186  if (p == NULL) return;
187  if (length <= 0) length = pLength(p);
188
189  int i = LOG2(length);
190
191  while (bucket->buckets[i].p != NULL)
192  {
193    p = p_Merge_q(p, bucket->buckets[i].p, bucket->bucket_ring);
194    length += bucket->buckets[i].length;
195    bucket->buckets[i].p = NULL;
196    bucket->buckets[i].length = 0;
197    i++;
198    assume(LOG2(length) == i);
199  }
200
201  bucket->buckets[i].p = p;
202  bucket->buckets[i].length = length;
203  if (i > bucket->max_bucket) bucket->max_bucket = i;
204}
205
206void sBucket_Add_p(sBucket_pt bucket, poly p, int length)
207{
208  assume(bucket != NULL);
209  assume(length <= 0 || length == pLength(p));
210
211  if (p == NULL) return;
212  if (length <= 0) length = pLength(p);
213
214  int i = LOG2(length);
215
216  while (bucket->buckets[i].p != NULL)
217  {
218    p = p_Add_q(p, bucket->buckets[i].p, length, bucket->buckets[i].length,
219                bucket->bucket_ring);
220    bucket->buckets[i].p = NULL;
221    bucket->buckets[i].length = 0;
222    if (p==NULL)
223    {
224      if (i > bucket->max_bucket) bucket->max_bucket = i;
225      return;
226    }
227    i = LOG2(length);
228  }
229
230  bucket->buckets[i].p = p;
231  bucket->buckets[i].length = length;
232  if (i > bucket->max_bucket) bucket->max_bucket = i;
233}
234
235// Converts SBpoly into a poly and clears bucket
236// i.e., afterwards SBpoly == 0
237void sBucketClearMerge(sBucket_pt bucket, poly *p, int *length)
238{
239  poly pr = NULL;
240  int  lr = 0;
241  int i = 0;
242
243  while (bucket->buckets[i].p == NULL)
244  {
245    i++;
246    if (i > bucket->max_bucket) goto done;
247  }
248
249  pr = bucket->buckets[i].p;
250  lr = bucket->buckets[i].length;
251  bucket->buckets[i].p = NULL;
252  bucket->buckets[i].length = 0;
253  i++;
254
255  while (i <= bucket->max_bucket)
256  {
257    if (bucket->buckets[i].p != NULL)
258    {
259      pr = p_Merge_q(pr, bucket->buckets[i].p,bucket->bucket_ring);
260      lr += bucket->buckets[i].length;
261      bucket->buckets[i].p = NULL;
262      bucket->buckets[i].length = 0;
263    }
264    i++;
265  }
266
267  done:
268  *p = pr;
269  *length = lr;
270  bucket->max_bucket = 0;
271}
272
273// Converts SBpoly into a poly and clears bucket
274// i.e., afterwards SBpoly == 0
275void sBucketClearAdd(sBucket_pt bucket, poly *p, int *length)
276{
277  poly pr = NULL;
278  int  lr = 0;
279  int i = 0;
280
281  while (bucket->buckets[i].p == NULL)
282  {
283    assume( bucket->buckets[i].length == 0 );
284    i++;
285    if (i > bucket->max_bucket) goto done;
286  }
287
288  pr = bucket->buckets[i].p;
289  lr = bucket->buckets[i].length;
290
291  assume( pr != NULL && (lr > 0) );
292 
293  bucket->buckets[i].p = NULL;
294  bucket->buckets[i].length = 0;
295  i++;
296
297  while (i <= bucket->max_bucket)
298  {
299    if (bucket->buckets[i].p != NULL)
300    {
301      assume( bucket->buckets[i].length == pLength(bucket->buckets[i].p) );
302     
303      pr = p_Add_q(pr, bucket->buckets[i].p, lr, bucket->buckets[i].length,
304                   bucket->bucket_ring);
305     
306      bucket->buckets[i].p = NULL;
307      bucket->buckets[i].length = 0;
308    }
309
310    assume( bucket->buckets[i].p == NULL );
311    assume( bucket->buckets[i].length == 0 );   
312    i++;
313  }
314
315done:
316 
317  *p = pr;
318  *length = lr;
319 
320  bucket->max_bucket = 0;
321
322  assume( sIsEmpty(bucket) );
323}
324
325
326
327
328/////////////////////////////////////////////////////////////////////////////
329// Sorts a poly using BucketSort
330//
331
332poly sBucketSortMerge(poly p, ring r)
333{
334#ifdef HAVE_ASSUME
335  int l_in = pLength(p);
336#endif
337
338  if (p == NULL || pNext(p) == NULL) return p;
339
340  sBucket_pt bucket = sBucketCreate(r);
341  poly pn = pNext(p);
342
343  do
344  {
345    pNext(p) = NULL;
346    sBucket_Merge_m(bucket, p);
347    p = pn;
348    if (p == NULL) break;
349    pn = pNext(pn);
350  }
351  while (1);
352
353  int l_dummy;
354  sBucketClearMerge(bucket, &pn, &l_dummy);
355  sBucketDestroy(&bucket);
356
357  p_Test(pn, r);
358#ifdef HAVE_ASSUME
359  assume(l_dummy == pLength(pn));
360  assume(l_in == l_dummy);
361#endif
362  return pn;
363}
364
365/////////////////////////////////////////////////////////////////////////////
366// Sorts a poly using BucketSort
367//
368
369poly sBucketSortAdd(poly p, ring r)
370{
371#ifdef HAVE_ASSUME
372  int l_in = pLength(p);
373#endif
374
375  if (p == NULL || pNext(p) == NULL) return p;
376
377  sBucket_pt bucket = sBucketCreate(r);
378  poly pn = pNext(p);
379
380  do
381  {
382    pNext(p) = NULL;
383    sBucket_Add_p(bucket, p, 1);
384    p = pn;
385    if (p == NULL) break;
386    pn = pNext(pn);
387  }
388  while (1);
389
390  int l_dummy;
391  sBucketClearAdd(bucket, &pn, &l_dummy);
392  sBucketDestroy(&bucket);
393
394  p_Test(pn, r);
395#ifdef HAVE_ASSUME
396  assume(l_dummy == pLength(pn));
397  assume(l_in >= l_dummy);
398#endif
399  return pn;
400}
Note: See TracBrowser for help on using the repository browser.