source: git/kernel/sbuckets.cc @ a795c77

spielwiese
Last change on this file since a795c77 was a795c77, checked in by Motsak Oleksandr <motsak@…>, 15 years ago
*motsak: more sBucket API git-svn-id: file:///usr/local/Singular/svn/trunk@11848 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 7.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 *  Version: $Id: sbuckets.cc,v 1.3 2009-05-27 16:15:14 motsak Exp $
11 *******************************************************************/
12#include "mod2.h"
13
14#include "sbuckets.h"
15#include "omalloc.h"
16#include "ring.h"
17#include "p_Procs.h"
18#include "p_polys.h"
19
20
21
22//////////////////////////////////////////////////////////////////////////
23// Declarations
24//
25
26class sBucketPoly
27{
28public:
29  poly p;
30  long length;
31};
32
33class sBucket
34{
35public:
36  ring          bucket_ring;
37  long          max_bucket;
38  sBucketPoly   buckets[BIT_SIZEOF_LONG - 3];
39}
40;
41
42static omBin sBucket_bin = omGetSpecBin(sizeof(sBucket));
43
44
45//////////////////////////////////////////////////////////////////////////
46// New API:
47//
48
49/// Returns bucket ring
50const ring sBucketGetRing(const sBucket_pt bucket)
51{ return bucket->bucket_ring; }
52
53/// Copy sBucket non-intrusive!!!
54sBucket_pt    sBucketCopy(const sBucket_pt bucket)
55{
56  const ring r = bucket->bucket_ring;
57
58  sBucket_pt newbucket = sBucketCreate(r);
59
60  for(int i = 0; bucket->buckets[i].p != NULL; i++)
61  {
62    assume( i < (BIT_SIZEOF_LONG - 3) );
63    assume( pLength(bucket->buckets[i].p) == bucket->buckets[i].length );
64
65    newbucket->buckets[i].p = p_Copy(bucket->buckets[i].p, r);
66    newbucket->buckets[i].length = bucket->buckets[i].length;
67
68    assume( pLength(newbucket->buckets[i].p) == newbucket->buckets[i].length );
69  }
70
71  return newbucket;
72}
73
74/////////////////////////////////////////////////////////////////////////////
75// internal routines
76//
77// returns floor(log_2(i))
78inline int LOG2(int i)
79{
80  assume (i > 0);
81  int j = 0;
82
83  do
84  {
85    i = i >> 1;
86    if (i == 0) return j;
87    j++;
88  }
89  while (1);
90
91  return j;
92}
93
94//////////////////////////////////////////////////////////////////////////
95// Creation/Destruction of buckets
96//
97sBucket_pt    sBucketCreate(ring r)
98{
99  sBucket_pt bucket = (sBucket_pt) omAlloc0Bin(sBucket_bin);
100  bucket->bucket_ring = r;
101  return bucket;
102}
103
104void          sBucketDestroy(sBucket_pt *bucket)
105{
106  assume(bucket != NULL);
107  omFreeBin(*bucket, sBucket_bin);
108  *bucket = NULL;
109}
110
111/////////////////////////////////////////////////////////////////////////////
112// Convertion from/to SBpolys
113//
114
115static void sBucket_Merge_m(sBucket_pt bucket, poly p)
116{
117  assume(p != NULL && pNext(p) == NULL);
118  int length = 1;
119  int i = 0;
120
121  while (bucket->buckets[i].p != NULL)
122  {
123    p = p_Merge_q(p, bucket->buckets[i].p, bucket->bucket_ring);
124    length += bucket->buckets[i].length;
125    bucket->buckets[i].p = NULL;
126    bucket->buckets[i].length = 0;
127    i++;
128    assume(LOG2(length) == i);
129  }
130
131  bucket->buckets[i].p = p;
132  bucket->buckets[i].length = length;
133  if (i > bucket->max_bucket) bucket->max_bucket = i;
134}
135
136void sBucket_Merge_p(sBucket_pt bucket, poly p, int length)
137{
138  assume(bucket != NULL);
139  assume(length <= 0 || length == pLength(p));
140
141  if (p == NULL) return;
142  if (length <= 0) length = pLength(p);
143
144  int i = LOG2(length);
145
146  while (bucket->buckets[i].p != NULL)
147  {
148    p = p_Merge_q(p, bucket->buckets[i].p, bucket->bucket_ring);
149    length += bucket->buckets[i].length;
150    bucket->buckets[i].p = NULL;
151    bucket->buckets[i].length = 0;
152    i++;
153    assume(LOG2(length) == i);
154  }
155
156  bucket->buckets[i].p = p;
157  bucket->buckets[i].length = length;
158  if (i > bucket->max_bucket) bucket->max_bucket = i;
159}
160
161void sBucket_Add_p(sBucket_pt bucket, poly p, int length)
162{
163  assume(bucket != NULL);
164  assume(length <= 0 || length == pLength(p));
165
166  if (p == NULL) return;
167  if (length <= 0) length = pLength(p);
168
169  int i = LOG2(length);
170
171  while (bucket->buckets[i].p != NULL)
172  {
173    p = p_Add_q(p, bucket->buckets[i].p, length, bucket->buckets[i].length,
174                bucket->bucket_ring);
175    bucket->buckets[i].p = NULL;
176    bucket->buckets[i].length = 0;
177    if (p==NULL)
178    {
179      if (i > bucket->max_bucket) bucket->max_bucket = i;
180      return;
181    }
182    i = LOG2(length);
183  }
184
185  bucket->buckets[i].p = p;
186  bucket->buckets[i].length = length;
187  if (i > bucket->max_bucket) bucket->max_bucket = i;
188}
189
190// Converts SBpoly into a poly and clears bucket
191// i.e., afterwards SBpoly == 0
192void sBucketClearMerge(sBucket_pt bucket, poly *p, int *length)
193{
194  poly pr = NULL;
195  int  lr = 0;
196  int i = 0;
197
198  while (bucket->buckets[i].p == NULL)
199  {
200    i++;
201    if (i > bucket->max_bucket) goto done;
202  }
203
204  pr = bucket->buckets[i].p;
205  lr = bucket->buckets[i].length;
206  bucket->buckets[i].p = NULL;
207  bucket->buckets[i].length = 0;
208  i++;
209
210  while (i <= bucket->max_bucket)
211  {
212    if (bucket->buckets[i].p != NULL)
213    {
214      pr = p_Merge_q(pr, bucket->buckets[i].p,bucket->bucket_ring);
215      lr += bucket->buckets[i].length;
216      bucket->buckets[i].p = NULL;
217      bucket->buckets[i].length = 0;
218    }
219    i++;
220  }
221
222  done:
223  *p = pr;
224  *length = lr;
225  bucket->max_bucket = 0;
226}
227
228// Converts SBpoly into a poly and clears bucket
229// i.e., afterwards SBpoly == 0
230void sBucketClearAdd(sBucket_pt bucket, poly *p, int *length)
231{
232  poly pr = NULL;
233  int  lr = 0;
234  int i = 0;
235
236  while (bucket->buckets[i].p == NULL)
237  {
238    i++;
239    if (i > bucket->max_bucket) goto done;
240  }
241
242  pr = bucket->buckets[i].p;
243  lr = bucket->buckets[i].length;
244  bucket->buckets[i].p = NULL;
245  bucket->buckets[i].length = 0;
246  i++;
247
248  while (i <= bucket->max_bucket)
249  {
250    if (bucket->buckets[i].p != NULL)
251    {
252      pr = p_Add_q(pr, bucket->buckets[i].p, lr, bucket->buckets[i].length,
253                   bucket->bucket_ring);
254      bucket->buckets[i].p = NULL;
255      bucket->buckets[i].length = 0;
256    }
257    i++;
258  }
259
260  done:
261  *p = pr;
262  *length = lr;
263  bucket->max_bucket = 0;
264}
265
266/////////////////////////////////////////////////////////////////////////////
267// Sorts a poly using BucketSort
268//
269
270poly sBucketSortMerge(poly p, ring r)
271{
272#ifdef HAVE_ASSUME
273  int l_in = pLength(p);
274#endif
275
276  if (p == NULL || pNext(p) == NULL) return p;
277
278  sBucket_pt bucket = sBucketCreate(r);
279  poly pn = pNext(p);
280
281  do
282  {
283    pNext(p) = NULL;
284    sBucket_Merge_m(bucket, p);
285    p = pn;
286    if (p == NULL) break;
287    pn = pNext(pn);
288  }
289  while (1);
290
291  int l_dummy;
292  sBucketClearMerge(bucket, &pn, &l_dummy);
293  sBucketDestroy(&bucket);
294
295  p_Test(pn, r);
296#ifdef HAVE_ASSUME
297  assume(l_dummy == pLength(pn));
298  assume(l_in == l_dummy);
299#endif
300  return pn;
301}
302
303/////////////////////////////////////////////////////////////////////////////
304// Sorts a poly using BucketSort
305//
306
307poly sBucketSortAdd(poly p, ring r)
308{
309#ifdef HAVE_ASSUME
310  int l_in = pLength(p);
311#endif
312
313  if (p == NULL || pNext(p) == NULL) return p;
314
315  sBucket_pt bucket = sBucketCreate(r);
316  poly pn = pNext(p);
317
318  do
319  {
320    pNext(p) = NULL;
321    sBucket_Add_p(bucket, p, 1);
322    p = pn;
323    if (p == NULL) break;
324    pn = pNext(pn);
325  }
326  while (1);
327
328  int l_dummy;
329  sBucketClearAdd(bucket, &pn, &l_dummy);
330  sBucketDestroy(&bucket);
331
332  p_Test(pn, r);
333#ifdef HAVE_ASSUME
334  assume(l_dummy == pLength(pn));
335  assume(l_in >= l_dummy);
336#endif
337  return pn;
338}
Note: See TracBrowser for help on using the repository browser.